Beispiel #1
0
    def test_mac_is_multicast(self):
        addr = b'\x01\x23\x45\x67\x89\x0a'
        val = True

        res = mac.is_multicast(addr)

        eq_(val, res)
Beispiel #2
0
    def test_mac_is_multicast(self):
        addr = b"\x01\x23\x45\x67\x89\x0a"
        val = True

        res = mac.is_multicast(addr)

        eq_(val, res)
Beispiel #3
0
def mac_addr_is_unicast(mac_addr):
    """Returns True if mac_addr is a unicast Ethernet address.

    Args:
        mac_addr (str): MAC address.
    Returns:
        bool: True if a unicast Ethernet address.
    """
    mac_bin = haddr_to_bin(mac_addr)
    if mac_bin == BROADCAST:
        return False
    return not is_multicast(mac_bin)
Beispiel #4
0
def mac_addr_is_unicast(mac_addr):
    """Returns True if mac_addr is a unicast Ethernet address.

    Args:
        mac_addr (str): MAC address.
    Returns:
        bool: True if a unicast Ethernet address.
    """
    mac_bin = haddr_to_bin(mac_addr)
    if mac_bin == BROADCAST:
        return False
    return not is_multicast(mac_bin)
Beispiel #5
0
    def _packet_in_handler(self, ev):
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto

        dst, src, _eth_type = struct.unpack_from("!6s6sH", buffer(msg.data), 0)

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

        LOG.info("packet in %s %s %s %s", dpid, haddr_to_str(src), haddr_to_str(dst), msg.in_port)

        # learn a mac address to avoid FLOOD next time.
        self.mac_to_port[dpid][src] = msg.in_port
        broadcast = (dst == mac.BROADCAST) or mac.is_multicast(dst)

        if broadcast:
            out_port = ofproto.OFPP_FLOOD
            LOG.info("broadcast frame, flood and install flow")
        elif src != dst:
            if dst in self.mac_to_port[dpid]:
                out_port = self.mac_to_port[dpid][dst]
            else:
                LOG.info("out_port not found")
                out_port = ofproto.OFPP_FLOOD
        else:
            self._drop_packet(msg)
            return

        actions = [datapath.ofproto_parser.OFPActionOutput(out_port)]

        # install a flow to avoid packet_in next time
        if broadcast or (out_port != ofproto.OFPP_FLOOD):
            self.add_flow(datapath, msg.in_port, dst, actions)

        out = datapath.ofproto_parser.OFPPacketOut(
            datapath=datapath, buffer_id=msg.buffer_id, in_port=msg.in_port, actions=actions
        )
        datapath.send_msg(out)
Beispiel #6
0
    def packet_in_handler(self, ev):
        self.mac_to_port = dict()  # Creacion diccionario vacio
        msg = ev.msg  # Objeto que representa la estuctura de datos PacketIn.
        datapath = msg.datapath  # Identificador del datapath correspondiente al switch.
        ofproto = datapath.ofproto  # Protocolo utilizado que se fija en una etapa
        # de negociacion entre controlador y switch

        ofp_parser = datapath.ofproto_parser  # Parser con la version OF
        # correspondiente

        in_port = msg.match['in_port']  # Puerto de entrada.

        # Ahora analizamos el paquete utilizando las clases de la libreria packet.
        pkt = packet.Packet(msg.data)
        eth = pkt.get_protocol(ethernet.ethernet)

        # Extraemos la MAC de destino

        dst = eth.dst
        src = eth.src
        self.mac_to_port[src] = in_port

        if dst in self.mac_to_port.keys():
            match = ofp_parser.OFPMatch(eth_dst=dst)
            actions = [ofp_parser.OFPActionOutput(self.mac_to_port[dst])]
            self.add_flow(datapath, 0, match, actions, msg.buffer_id)
        elif haddr_to_bin(dst) == mac.BROADCAST or mac.is_multicast(
                haddr_to_bin(dst)):
            # Ahora creamos el match
            # fijando los valores de los campos
            # que queremos casar.
            match = ofp_parser.OFPMatch(eth_dst=dst)

            # Creamos el conjunto de acciones: FLOOD
            actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_FLOOD)]
            self.add_flow(datapath, 0, match, actions, msg.buffer_id)
        else:
            self.send_packet(datapath, ofproto.OFPP_FLOOD, pkt)
Beispiel #7
0
    def packet_in_handler(self, ev):
        def drop():
            LOG.error("\tImplement drop function")

        def flood():
            LOG.warn("\tFlooding packet")
            for (iDpid, switch) in self.G.nodes(data='switch'):

                #Initialize ports
                ports = []
                #Add local port if that is not the originating port
                #if (iDpid,ofp.OFPP_LOCAL) != (dpid, in_port):
                #    ports += [ofp.OFPP_LOCAL]

                #Exclude the inter-switch and possible other incoming ports from flooding
                ports += [
                    p.port_no for p in switch.ports
                    if (iDpid,
                        p.port_no) != (dpid, in_port) and p.port_no not in [
                            self.G.get_edge_data(iDpid, jDpid)['port']
                            for jDpid in self.G.neighbors(iDpid)
                        ]
                ]

                actions = [parser.OFPActionOutput(port, 0) for port in ports]

                if iDpid == dpid and buffer_id != None:
                    LOG.warn(
                        "\t\tFlooding Originating Switch %d using Buffer ID" %
                        (iDpid))
                    req = parser.OFPPacketOut(dp,
                                              buffer_id=buffer_id,
                                              in_port=in_port,
                                              actions=actions)
                    switch.dp.send_msg(req)

                elif len(actions) > 0:
                    LOG.warn("\t\tFlooding Switch %d" % (iDpid))
                    req = parser.OFPPacketOut(dp,
                                              buffer_id=ofp.OFP_NO_BUFFER,
                                              in_port=ofp.OFPP_CONTROLLER,
                                              actions=actions,
                                              data=data)
                    switch.dp.send_msg(req)

        def output(tDpid, port):
            LOG.warn("\tOutputting packet")

            action = parser.OFPActionOutput(port, 0)

            if buffer_id != None:
                #Drop the packet from the buffer on the incoming switch to prevent buffer overflows.
                if tDpid != dpid:
                    LOG.warn("\tDropping buffer_id on incoming switch %d" %
                             (dpid))
                    actions = []
                #Or forward if that is also the destination switch.
                else:
                    LOG.warn("\tOutputting via buffer_id on switch %d" %
                             (tDpid))
                    actions = [action]

                req = parser.OFPPacketOut(dp,
                                          buffer_id=buffer_id,
                                          in_port=in_port,
                                          actions=actions)
                dp.send_msg(req)

            #Forward packet through data-field.
            if buffer_id == None or tDpid != dpid:
                LOG.warn("\tOutputting on outgoing switch %d" % (tDpid))
                switch = self.G.node[tDpid]['switch']
                actions = [action]
                req = parser.OFPPacketOut(dp,
                                          buffer_id=ofp.OFP_NO_BUFFER,
                                          in_port=ofp.OFPP_CONTROLLER,
                                          actions=actions,
                                          data=data)
                switch.dp.send_msg(req)

        msg = ev.msg
        dp = msg.datapath
        dpid = msg.datapath.id
        in_port = msg.match['in_port']
        buffer_id = msg.buffer_id

        ofp = msg.datapath.ofproto
        parser = msg.datapath.ofproto_parser

        if msg.reason == ofp.OFPR_NO_MATCH:
            reason = 'NO MATCH'
        elif msg.reason == ofp.OFPR_ACTION:
            reason = 'ACTION'
        elif msg.reason == ofp.OFPR_INVALID_TTL:
            reason = 'INVALID TTL'
        else:
            reason = 'unknown'

        data = msg.data
        pkt = packet.Packet(data)
        eth = pkt.get_protocol(ethernet.ethernet)

        #LOG.debug("OpenFlowBackupRules: New incoming packet from %s at switch %d, port %d, for reason %s"%(eth.src,dpid,in_port,reason))

        if self.CONF.observe_links and eth.ethertype == ether_types.ETH_TYPE_LLDP:
            # ignore LLDP related messages IF topology module has been enabled.
            #LOG.debug("\tIgnored LLDP packet due to enabled topology module")
            return

        LOG.warn(
            "OpenFlowBackupRules: Accepted incoming packet from %s at switch %d, port %d, for reason %s"
            % (eth.src, dpid, in_port, reason))
        LOG.debug("\t%s" % (msg))
        LOG.debug("\t%s" % (pkt))

        SwitchPort = namedtuple('SwitchPort', 'dpid port')

        #if in_port not in [port for _,port  in self.G.neighbors(dpid, data="port")]:
        if in_port not in [
                self.G.get_edge_data(dpid, jDpid)['port']
                for jDpid in self.G.neighbors(dpid)
        ]:
            # only relearn locations if they arrived from non-interswitch links
            self.mac_learning[eth.src] = SwitchPort(
                dpid, in_port)  #relearn the location of the mac-address
            LOG.warn("\tLearned or updated MAC address")
        else:
            LOG.warn(
                "\tIncoming packet from switch-to-switch link, this should NOT occur."
            )
            #DROP it

        if mac.is_multicast(mac.haddr_to_bin(eth.dst)):
            #Maybe we should do something with preconfigured broadcast trees, but that is a different problem for now.
            flood()
            LOG.warn("\tFlooded multicast packet")
        elif eth.dst not in self.mac_learning:
            flood()
            LOG.warn("\tFlooded unicast packet, unknown MAC address location")

        #ARP messages are too infrequent and volatile of nature to create flows for, output immediately
        elif eth.ethertype == ether_types.ETH_TYPE_ARP:
            output(self.mac_learning[eth.dst].dpid,
                   self.mac_learning[eth.dst].port)
            LOG.warn("\tProcessed packet, send to recipient at %s" %
                     (self.mac_learning[eth.dst], ))
        #Create flow and output or forward.
        else:

            self._install_path(dpid, in_port, pkt)

            #Output the first packet to its destination
            output(self.mac_learning[eth.dst].dpid,
                   self.mac_learning[eth.dst].port)
            LOG.warn("\tProcessed packet, sent to recipient at %s" %
                     (self.mac_learning[eth.dst], ))
Beispiel #8
0
    def packet_in_handler(self, ev):
        # LOG.debug('packet in ev %s msg %s', ev, ev.msg)
        msg = ev.msg
        datapath = msg.datapath

        dst, src, _eth_type = struct.unpack_from('!6s6sH', buffer(msg.data), 0)

        try:
            port_nw_id = self.nw.get_network(datapath.id, msg.in_port)
        except PortUnknown:
            port_nw_id = NW_ID_UNKNOWN

        if port_nw_id != NW_ID_UNKNOWN:
            # Here it is assumed that the
            # (port <-> network id)/(mac <-> network id) relationship
            # is stable once the port is created. The port will be destroyed
            # before assigning new network id to the given port.
            # This is correct nova-network/nova-compute.
            try:
                # allow external -> known nw id change
                self.mac2net.add_mac(src, port_nw_id, NW_ID_EXTERNAL)
            except MacAddressDuplicated:
                LOG.warn(
                    'mac address %s is already in use.'
                    ' So (dpid %s, port %s) can not use it', haddr_to_str(src),
                    datapath.id, msg.in_port)
                #
                # should we install drop action pro-actively for future?
                #
                self._drop_packet(msg)
                return

        old_port = self.mac2port.port_add(datapath.id, msg.in_port, src)
        if old_port is not None and old_port != msg.in_port:
            # We really overwrite already learned mac address.
            # So discard already installed stale flow entry which conflicts
            # new port.
            rule = nx_match.ClsRule()
            rule.set_dl_dst(src)
            datapath.send_flow_mod(
                rule=rule,
                cookie=0,
                command=datapath.ofproto.OFPFC_DELETE,
                idle_timeout=0,
                hard_timeout=0,
                priority=datapath.ofproto.OFP_DEFAULT_PRIORITY,
                out_port=old_port)

            # to make sure the old flow entries are purged.
            datapath.send_barrier()

        src_nw_id = self.mac2net.get_network(src, NW_ID_UNKNOWN)
        dst_nw_id = self.mac2net.get_network(dst, NW_ID_UNKNOWN)

        # we handle multicast packet as same as broadcast
        broadcast = (dst == mac.BROADCAST) or mac.is_multicast(dst)
        out_port = self.mac2port.port_get(datapath.id, dst)

        #
        # there are several combinations:
        # in_port: known nw_id, external, unknown nw,
        # src mac: known nw_id, external, unknown nw,
        # dst mac: known nw_id, external, unknown nw, and broadcast/multicast
        # where known nw_id: is quantum network id
        #       external: means that these ports are connected to outside
        #       unknown nw: means that we don't know this port is bounded to
        #                   specific nw_id or external
        #       broadcast: the destination mac address is broadcast address
        #                  (or multicast address)
        #
        # Can the following logic be refined/shortened?
        #

        # When NW_ID_UNKNOWN is found, registering ports might be delayed.
        # So just drop only this packet and not install flow entry.
        # It is expected that when next packet arrives, the port is registers
        # with some network id

        if port_nw_id != NW_ID_EXTERNAL and port_nw_id != NW_ID_UNKNOWN:
            if broadcast:
                # flood to all ports of external or src_nw_id
                self._flood_to_nw_id(msg, src, dst, src_nw_id)
            elif src_nw_id == NW_ID_EXTERNAL:
                self._modflow_and_drop_packet(msg, src, dst)
                return
            elif src_nw_id == NW_ID_UNKNOWN:
                self._drop_packet(msg)
                return
            else:
                # src_nw_id != NW_ID_EXTERNAL and src_nw_id != NW_ID_UNKNOWN:
                #
                # try learned mac check if the port is net_id
                # or
                # flood to all ports of external or src_nw_id
                self._learned_mac_or_flood_to_nw_id(msg, src, dst, src_nw_id,
                                                    out_port)

        elif port_nw_id == NW_ID_EXTERNAL:
            if src_nw_id != NW_ID_EXTERNAL and src_nw_id != NW_ID_UNKNOWN:
                if broadcast:
                    # flood to all ports of external or src_nw_id
                    self._flood_to_nw_id(msg, src, dst, src_nw_id)
                elif (dst_nw_id != NW_ID_EXTERNAL
                      and dst_nw_id != NW_ID_UNKNOWN):
                    if src_nw_id == dst_nw_id:
                        # try learned mac
                        # check if the port is external or same net_id
                        # or
                        # flood to all ports of external or src_nw_id
                        self._learned_mac_or_flood_to_nw_id(
                            msg, src, dst, src_nw_id, out_port)
                    else:
                        # should not occur?
                        LOG.debug("should this case happen?")
                        self._drop_packet(msg)
                elif dst_nw_id == NW_ID_EXTERNAL:
                    # try learned mac
                    # or
                    # flood to all ports of external or src_nw_id
                    self._learned_mac_or_flood_to_nw_id(
                        msg, src, dst, src_nw_id, out_port)
                else:
                    assert dst_nw_id == NW_ID_UNKNOWN
                    LOG.debug("Unknown dst_nw_id")
                    self._drop_packet(msg)
            elif src_nw_id == NW_ID_EXTERNAL:
                self._modflow_and_drop_packet(msg, src, dst)
            else:
                # should not occur?
                assert src_nw_id == NW_ID_UNKNOWN
                self._drop_packet(msg)
        else:
            # drop packets
            assert port_nw_id == NW_ID_UNKNOWN
            self._drop_packet(msg)
Beispiel #9
0
    def packet_in_handler(self, ev):
        # self.logger.debug('packet in ev %s msg %s', ev, ev.msg)
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto

        dst, src, _eth_type = struct.unpack_from("!6s6sH", buffer(msg.data), 0)

        try:
            port_nw_id = self.nw.get_network(datapath.id, msg.in_port)
        except PortUnknown:
            port_nw_id = NW_ID_UNKNOWN

        if port_nw_id != NW_ID_UNKNOWN:
            # Here it is assumed that the
            # (port <-> network id)/(mac <-> network id) relationship
            # is stable once the port is created. The port will be destroyed
            # before assigning new network id to the given port.
            # This is correct nova-network/nova-compute.
            try:
                # allow external -> known nw id change
                self.mac2net.add_mac(src, port_nw_id, NW_ID_EXTERNAL)
            except MacAddressDuplicated:
                self.logger.warn(
                    "mac address %s is already in use." " So (dpid %s, port %s) can not use it",
                    haddr_to_str(src),
                    datapath.id,
                    msg.in_port,
                )
                #
                # should we install drop action pro-actively for future?
                #
                self._drop_packet(msg)
                return

        old_port = self.mac2port.port_add(datapath.id, msg.in_port, src)
        if old_port is not None and old_port != msg.in_port:
            # We really overwrite already learned mac address.
            # So discard already installed stale flow entry which conflicts
            # new port.
            rule = nx_match.ClsRule()
            rule.set_dl_dst(src)
            datapath.send_flow_mod(
                rule=rule,
                cookie=0,
                command=ofproto.OFPFC_DELETE,
                idle_timeout=0,
                hard_timeout=0,
                priority=ofproto.OFP_DEFAULT_PRIORITY,
                out_port=old_port,
            )

            # to make sure the old flow entries are purged.
            datapath.send_barrier()

        src_nw_id = self.mac2net.get_network(src, NW_ID_UNKNOWN)
        dst_nw_id = self.mac2net.get_network(dst, NW_ID_UNKNOWN)

        # we handle multicast packet as same as broadcast
        broadcast = (dst == mac.BROADCAST) or mac.is_multicast(dst)
        out_port = self.mac2port.port_get(datapath.id, dst)

        #
        # there are several combinations:
        # in_port: known nw_id, external, unknown nw,
        # src mac: known nw_id, external, unknown nw,
        # dst mac: known nw_id, external, unknown nw, and broadcast/multicast
        # where known nw_id: is quantum network id
        #       external: means that these ports are connected to outside
        #       unknown nw: means that we don't know this port is bounded to
        #                   specific nw_id or external
        #       broadcast: the destination mac address is broadcast address
        #                  (or multicast address)
        #
        # Can the following logic be refined/shortened?
        #

        # When NW_ID_UNKNOWN is found, registering ports might be delayed.
        # So just drop only this packet and not install flow entry.
        # It is expected that when next packet arrives, the port is registers
        # with some network id

        if port_nw_id != NW_ID_EXTERNAL and port_nw_id != NW_ID_UNKNOWN:
            if broadcast:
                # flood to all ports of external or src_nw_id
                self._flood_to_nw_id(msg, src, dst, src_nw_id)
            elif src_nw_id == NW_ID_EXTERNAL:
                self._modflow_and_drop_packet(msg, src, dst)
                return
            elif src_nw_id == NW_ID_UNKNOWN:
                self._drop_packet(msg)
                return
            else:
                # src_nw_id != NW_ID_EXTERNAL and src_nw_id != NW_ID_UNKNOWN:
                #
                # try learned mac check if the port is net_id
                # or
                # flood to all ports of external or src_nw_id
                self._learned_mac_or_flood_to_nw_id(msg, src, dst, src_nw_id, out_port)

        elif port_nw_id == NW_ID_EXTERNAL:
            if src_nw_id != NW_ID_EXTERNAL and src_nw_id != NW_ID_UNKNOWN:
                if broadcast:
                    # flood to all ports of external or src_nw_id
                    self._flood_to_nw_id(msg, src, dst, src_nw_id)
                elif dst_nw_id != NW_ID_EXTERNAL and dst_nw_id != NW_ID_UNKNOWN:
                    if src_nw_id == dst_nw_id:
                        # try learned mac
                        # check if the port is external or same net_id
                        # or
                        # flood to all ports of external or src_nw_id
                        self._learned_mac_or_flood_to_nw_id(msg, src, dst, src_nw_id, out_port)
                    else:
                        # should not occur?
                        self.logger.debug("should this case happen?")
                        self._drop_packet(msg)
                elif dst_nw_id == NW_ID_EXTERNAL:
                    # try learned mac
                    # or
                    # flood to all ports of external or src_nw_id
                    self._learned_mac_or_flood_to_nw_id(msg, src, dst, src_nw_id, out_port)
                else:
                    assert dst_nw_id == NW_ID_UNKNOWN
                    self.logger.debug("Unknown dst_nw_id")
                    self._drop_packet(msg)
            elif src_nw_id == NW_ID_EXTERNAL:
                self._modflow_and_drop_packet(msg, src, dst)
            else:
                # should not occur?
                assert src_nw_id == NW_ID_UNKNOWN
                self._drop_packet(msg)
        else:
            # drop packets
            assert port_nw_id == NW_ID_UNKNOWN
            self._drop_packet(msg)
Beispiel #10
0
    def packet_in_handler(self, ev):
        msg = ev.msg               # Objeto que representa la estuctura de datos PacketIn.
        datapath = msg.datapath    # Identificador del datapath correspondiente al switch.
        ofproto = datapath.ofproto # Protocolo utilizado que se fija en una etapa 
                                   # de negociacion entre controlador y switch

        ofp_parser=datapath.ofproto_parser # Parser con la version OF
                       # correspondiente
        print("===========================================================================")
        print("PAQUETE ENTRANTE")
        in_port = msg.match['in_port'] # Puerto de entrada.
        print("PUERTO: ", in_port)
        # Ahora analizamos el paquete utilizando las clases de la libreria packet.
        pkt = packet.Packet(msg.data)
        eth = pkt.get_protocol(ethernet.ethernet)
        print("ETH: ", eth)
        # Extraemos la MAC de destino

        dst = eth.dst  
        print("MAC DE DESTINO: ", dst)
        #Extramos la MAC de origen
        src = eth.src
        print("MAC DE ORIGEN: ", src)
        
        if src not in self.mac_to_port.keys():
            print("NO TENGO EL ORIGEN")
            self.mac_to_port[src]=in_port
        
        
        if haddr_to_bin(dst) == mac.BROADCAST or mac.is_multicast(haddr_to_bin(dst)):
            # Creamos el conjunto de acciones: FLOOD PENE
            
            if eth.ethertype==ether.ETH_TYPE_ARP:
                pkt_arp=pkt.get_protocol(arp.arp)
                print("ARP POR BROADCAST!!")
                #for INTERFACE in self.interfaces_virtuales.keys():
                if self.paraipinterfaz(pkt_arp.dst_ip):
                    print("ES PA TI RESPONDE A ESE ARP MARICONA")
                    self.ARPPacket(pkt_arp,in_port,datapath)
                else: 
                    print("Retransmito ese arp cual swtich normal")
                    actions = []
                    print("-------------------------------------------------------")
                    for j in self.tabla_vlan.keys():
                        print("Puerto? ", j)
                        if self.tabla_vlan.get(j)==self.tabla_vlan.get(in_port) and j !=in_port :
                            actions.append(ofp_parser.OFPActionOutput(j))
                            print("Vlan ", self.tabla_vlan.get(j),"puerto de entrada", in_port, "otros puertos ", j)
                    # Ahora creamos el match  
                    # fijando los valores de los campos 
                    # que queremos casar.
                    match = ofp_parser.OFPMatch(eth_dst=dst,eth_src=src)
                    # Creamos el conjunto de instrucciones.
                    inst = [ofp_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]
                    # Creamos el mensaje OpenFlow 
                    mod = ofp_parser.OFPFlowMod(datapath=datapath, priority=0, match=match, instructions=inst, idle_timeout=30, buffer_id=msg.buffer_id)
                    # Enviamos el mensaje.
                    datapath.send_msg(mod)
            else: 
                print("BROADCAST NORMAL")
                actions = []
                print("-------------------------------------------------------")
                for j in self.tabla_vlan.keys():
                    print("Puerto? ", j)
                    if self.tabla_vlan.get(j)==self.tabla_vlan.get(in_port) and j !=in_port :
                        actions.append(ofp_parser.OFPActionOutput(j))
                        print("Vlan ", self.tabla_vlan.get(j),"puerto de entrada", in_port, "otros puertos ", j)
                print("-------------------------------------------------------")
                # Ahora creamos el match  
                # fijando los valores de los campos 
                # que queremos casar.
                match = ofp_parser.OFPMatch(eth_dst=dst,eth_src=src)
                # Creamos el conjunto de instrucciones.
                inst = [ofp_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]
                # Creamos el mensaje OpenFlow 
                mod = ofp_parser.OFPFlowMod(datapath=datapath, priority=0, match=match, instructions=inst, idle_timeout=30, buffer_id=msg.buffer_id)
                # Enviamos el mensaje.
                datapath.send_msg(mod)
                
        elif self.paramacinterfaz(dst):
              #eth = pkt.get_protocol(ethernet.ethernet)
            pkt_arp=pkt.get_protocol(arp.arp)
            #PROCESAR ARPREPLY PARA LAS INTERFACES VIRTUALES <---------
            print("Para la interfaz virtual")
            for INTERFACE in self.interfaces_virtuales.keys():
               if(self.interfaces_virtuales.get(INTERFACE)[0]==dst):
                    if eth.ethertype==0x0800: #Si es IP
                        pkt_ipv4=pkt.get_protocol(ipv4.ipv4)
                        if self.paraipinterfaz(pkt_ipv4.dst):
                            pkt_icmp=pkt.get_protocol(icmp.icmp)
                            if (pkt_icmp): #Si es ICMP
                                print("ESE IP ES PARA MI, RESPONDERE")
                                self.ICMPPacket(datapath, in_port, eth, pkt_ipv4, pkt_icmp)
                        else:
                            print("ESTO PAQUETE IP NO ES PA MI, LO ENRUTARE")
                            match = ofp_parser.OFPMatch(eth_dst=self.interfaces_virtuales.get(INTERFACE)[0])
                            goto = ofp_parser.OFPInstructionGotoTable(1)
                            mod = ofp_parser.OFPFlowMod(datapath=datapath,priority=0, match=match,table_id=0,instructions=[goto],buffer_id=msg.buffer_id)
                            #mod = ofp_parser.OFPFlowMod(datapath=datapath,priority=0, match=match,table_id=0,instructions=[goto])
                            datapath.send_msg(mod)
                            self.paquete_para_enrutar(ev)

                    elif eth.ethertype==ether.ETH_TYPE_ARP:
                        print("UN ARP CON MI NOMBRE :O")
                        pkt_arp=pkt.get_protocol(arp.arp)
                        self.ARPPacket(pkt_arp,in_port,datapath)
               
        elif dst not in self.mac_to_port.keys() :
            #actions = [ofp_parser.OFPPacketOut(ofproto.OFPP_FLOOD)]
               # Creamos el conjunto de acciones: FLOOD PENE
            pkt_arp=pkt.get_protocol(arp.arp)
            if(pkt_arp):
                for INTERFACE in self.interfaces_virtuales.keys():
                    if eth.ethertype==ether.ETH_TYPE_ARP and self.interfaces_virtuales.get(INTERFACE)[2]==pkt_arp.dst_ip:
                        print("AL ENRUTAMOVIL! PIRIRIRIRIRIRI")
                        self.ARPPacket(pkt_arp,in_port,datapath)
            else: 
                actions = []
                print("NO CONOZCO LA MAC ", dst)
                
                for i in self.tabla_vlan.keys():
                    if self.tabla_vlan.get(i)==self.tabla_vlan.get(in_port) and i !=in_port :
                        actions.append(ofp_parser.OFPActionOutput(i))
                        print i
                
                print("QUIEN DE LA VLAN ", self.tabla_vlan.get(in_port), " TIENE LA MAC ", dst,"?")
                #Aqui esta el fallo en buffer id os dejo el mensaje que sale
                
                req = ofp_parser.OFPPacketOut(datapath=datapath, buffer_id=ofproto.OFP_NO_BUFFER, in_port=in_port, actions=actions, data=msg.data)
                print("MANDAMOS REQ")
                datapath.send_msg(req)
                print("MANDADO!")
            
        elif self.tabla_vlan.get(self.mac_to_port.get(src)) == self.tabla_vlan.get(self.mac_to_port.get(dst)) :
            actions = [ofp_parser.OFPActionOutput(self.mac_to_port[dst])]
            print("PASANDO PAQUETES DENTRO DE LA VLAN ", self.tabla_vlan.get(self.mac_to_port.get(src)))
            # Ahora creamos el match  
            # fijando los valores de los campos 
            # que queremos casar.
            match = ofp_parser.OFPMatch(eth_dst=dst,eth_src=src)
    
            # Creamos el conjunto de instrucciones.
            inst = [ofp_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]
    
            # Creamos el mensaje OpenFlow 
            #mod = ofp_parser.OFPFlowMod(datapath=datapath, priority=0, match=match, instructions=inst, buffer_id=msg.buffer_id)
            mod = ofp_parser.OFPFlowMod(datapath=datapath, priority=0, match=match, instructions=inst, idle_timeout=30, buffer_id=msg.buffer_id)
    
            # Enviamos el mensaje.
            datapath.send_msg(mod)
        else: #Si no son de la misma vlan, tira el paquete
            #eth = pkt.get_protocol(ethernet.ethernet)
            pkt_arp=pkt.get_protocol(arp.arp)
            #PROCESAR ARPREPLY PARA LAS INTERFACES VIRTUALES <---------
            print("ESTOY EN EL ELSE")
Beispiel #11
0
    def packet_in_handler(self, ev):
        msg = ev.msg               
        datapath = msg.datapath    
        ofproto = datapath.ofproto 
        ofp_parser=datapath.ofproto_parser 
        
        print("===========================================================================")
        print("PAQUETE ENTRANTE")
        in_port = msg.match['in_port']
        print("PUERTO: ", in_port)
        # We extract the packet from the data
        pkt = packet.Packet(msg.data)
        # And we extract the ethernet protocol
        eth = pkt.get_protocol(ethernet.ethernet) 

        src = eth.src #Source MAC
        dst = eth.dst #Destiny MAC
        print("SOURCE MAC: ", src)
        print("DESTINY MAC: ", dst)
        
        if src not in self.mac_to_port.keys():
            print("I DON'T KNOW THAT MAC, SAVING MAC-PORT")
            self.mac_to_port[src]=in_port

        if haddr_to_bin(dst) == mac.BROADCAST or mac.is_multicast(haddr_to_bin(dst)):
            if eth.ethertype==ether.ETH_TYPE_ARP:
                pkt_arp=pkt.get_protocol(arp.arp)
                print("ARP CAME BY BROADCAST")
                if self.paraIpInterfaz(pkt_arp.dst_ip)!=None:
                    print("IT'S FOR A SVI, WE SHOULD ANSWER THAT")
                    self.handleArpPacket(pkt_arp,in_port,datapath)
                else:
                    print("NORMAL BROADCAST")
                    #We just have to fordward the packet thourgh the ports
                    #in the same vlan as the in_port
                    self.addForwardVlanFlow(datapath,ofproto,ofp_parser,dst,src,in_port,msg)
            else: 
                print("NORMAL BROADCAST")
                #We just have to fordward the packet thourgh the ports
                #in the same vlan as the in_port 
                self.addForwardVlanFlow(datapath,ofproto,ofp_parser,dst,src,in_port,msg)
                
        else:
            interfazdestino=self.paraMacInterfaz(dst)
            if interfazdestino!=None:
            #If it goes for an svi, we have to check a few things more
                pkt_arp=pkt.get_protocol(arp.arp)
                print("THAT MAC IS FOR ANY SVI")
                INTERFACE=interfazdestino

                if eth.ethertype==0x0800: 
                    #We should check that is ip
                    pkt_ipv4=pkt.get_protocol(ipv4.ipv4)
                    if self.paraIpInterfaz(pkt_ipv4.dst):
                        #If the destionation ip is the virtual interface
                        #we must check that is ICMP
                        pkt_icmp=pkt.get_protocol(icmp.icmp)
                        if (pkt_icmp): 
                            #If is ICMP we should manage that
                            print("ESE IP ES PARA MI, RESPONDERE")
                            self.handleIcmpPacket(datapath, in_port, eth, pkt_ipv4, pkt_icmp)
                        else:
                            #An ip packet arrives to the interface and is not for it
                            #We should drop it, for that we must add a rule with higher priority 
                            #than the go to
                            actions=[]
                            match = ofp_parser.OFPMatch(eth_dst=dst,ipv4_dst=pkt_ipv4.dst,ip_proto=pkt_ipv4.ip_proto)
                            inst = [ofp_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]
                            mod = ofp_parser.OFPFlowMod(datapath=datapath, priority=10, match=match, 
                                            instructions=inst,idle_timeout=60, buffer_id=msg.buffer_id)
                            datapath.send_msg(mod)
                    else:
                        print("THIS IS IP PACKET IS NOT FOR ME, I WILL ROUTE THAT")
                        #We add the entry to the table 0 who makes the GoTo to the table 1
                        print("ALL THIS PACKET SHOULD BE PROCESSED ON THE TABLE 1 ADDING GOTO")
                        match = ofp_parser.OFPMatch(eth_dst=self.interfaces_virtuales.get(INTERFACE)[0])
                        goto = ofp_parser.OFPInstructionGotoTable(1)
                        mod = ofp_parser.OFPFlowMod(datapath=datapath,priority=0,match=match,table_id=0,instructions=[goto],
                            buffer_id=ofproto.OFP_NO_BUFFER,idle_timeout=60,command=ofproto.OFPFC_ADD)
                        print(mod)
                        datapath.send_msg(mod)
                        #And we process the packet for routing
                        self.paquete_para_enrutar(msg)

                elif eth.ethertype==ether.ETH_TYPE_ARP:
                    print("AN ARP FOR ME, I WILL MANAGE THAT")
                    pkt_arp=pkt.get_protocol(arp.arp)
                    self.handleArpPacket(pkt_arp,in_port,datapath)

            #If the packet isn't going to the interface
            #it might go to the same vlan, so we have to forward it      
            else:
                if dst not in self.mac_to_port.keys() :
                    print("I DON'T KNOW THAT MAC ", dst)
                    print("IN THE VLAN ", self.tabla_vlan.get(in_port), " WHO HAS MAC: ", dst,"?")
                    actions = self.forwardPortsSameVlan(ofp_parser,in_port)
                    req = ofp_parser.OFPPacketOut(datapath=datapath, buffer_id=ofproto.OFP_NO_BUFFER,
                                                  in_port=in_port, actions=actions, data=msg.data)
                    datapath.send_msg(req)
                    
                else:
                    puertodestino=self.mac_to_port[dst]
                    if self.tabla_vlan.get(self.mac_to_port.get(src)) == self.tabla_vlan.get(puertodestino) :
                        #We know the macs, and we know they are on the same vlan
                        #Direct forwarding
                        actions = [ofp_parser.OFPActionOutput(puertodestino)]
                        print("FORWARDING INSIDE THE VLAN: ", self.tabla_vlan.get(puertodestino))
                    else: 
                        #If they do not belong the same vlan
                        #and they are trying to go directly
                        #we must drop the packet this is an error
                        print("CANNOT DIRECT FORWARD THROUGH VLANS ALL PACKETS WILL BE DROPPED")
                        actions=[]
                    match = ofp_parser.OFPMatch(eth_dst=dst,eth_src=src)
                    inst = [ofp_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]
                    mod = ofp_parser.OFPFlowMod(datapath=datapath, priority=0, match=match, 
                                                instructions=inst, idle_timeout=60, buffer_id=msg.buffer_id)
                    datapath.send_msg(mod)
Beispiel #12
0
Datei: rest.py Projekt: t-lin/ryu
    def assignNetwork(self, req, sliceName, network_id):
        status = 200
        body = ""

        # Check if network has been assigned to another controller
        # If so, must unassign it from the other controller first
        slice = self.fv_cli.getSliceName(network_id)
        if slice:
            if (slice == sliceName):  # Should this result in an error instead?
                return Response(status=status)

            response = self.unassignNetwork(req, network_id)
            status = response.status_code
        
        if (status == 200) and (sliceName != self.fv_cli.defaultSlice):
            # Install FV rules to route packets to controller
            for (dpid, port) in self.nw.list_ports(network_id):
                for mac in self.mac2port.mac_list(dpid, port):
                    if not is_multicast(mac):
                        # Install rule for MAC for all EXTERNAL ports throughout network
                        for (dpid2, port2) in self.nw.list_ports(NW_ID_EXTERNAL):
                            if (dpid2 == dpid):
                                continue

                            body = self.fv_cli.addFlowSpace(sliceName, dpid2, port2, haddr_to_str(mac))
                            if (body.find("success") == -1):
                                status = 500
                                break

                            self.fv_cli.addFlowSpaceID(dpid2, port2, mac, int(body[9:]))

                        if (status == 500):
                            break

                        # Now install rule for the target switch 
                        body = self.fv_cli.addFlowSpace(sliceName, dpid, port, haddr_to_str(mac))
                        if (body.find("success") == -1):
                            # Error occured while attempting to install FV rule
                            status = 500
                            break

                        # Keep track of installed rules related to network
                        self.fv_cli.addFlowSpaceID(dpid, port, mac, int(body[9:]))
                            
                if (status == 500):
                    break

                # Now delete rules installed in the switches
                dp = self.dpset.get(dpid)
                if dp is not None:
                    dp.send_delete_all_flows()

        if (status == 500):
            # Error occured in the middle of installing rules
            # Previously installed rules be deleted
            self.unassignNetwork(req, network_id)

        if (status == 200):
            self.fv_cli.slice2nw_add(sliceName, network_id)

        return Response(status=status, content_type='application/json', body=body)
Beispiel #13
0
    def packet_in_handler(self, ev):
        # LOG.debug('packet in ev %s msg %s', ev, ev.msg)
        msg = ev.msg
        datapath = msg.datapath

        dst, src, _eth_type = struct.unpack_from('!6s6sH', buffer(msg.data), 0)

        try:
            port_nw_id = self.nw.get_network(datapath.id, msg.in_port)
        except PortUnknown:
            port_nw_id = NW_ID_UNKNOWN

        if port_nw_id != NW_ID_UNKNOWN:
            # Here it is assumed that the
            # (port <-> network id)/(mac <-> network id) relationship
            # is stable once the port is created. The port will be destroyed
            # before assigning new network id to the given port.
            # This is correct nova-network/nova-compute.
            try:
                # allow external -> known nw id change
                self.mac2net.add_mac(src, port_nw_id, NW_ID_EXTERNAL)
            except MacAddressDuplicated:
                LOG.warn('mac address %s is already in use.'
                         ' So (dpid %s, port %s) can not use it',
                         haddr_to_str(src), datapath.id, msg.in_port)
                #
                # should we install drop action pro-actively for future?
                #
                self._drop_packet(msg)
                return

        old_port = self.mac2port.port_add(datapath.id, msg.in_port, src)
        if old_port is not None and old_port != msg.in_port:
            # We really overwrite already learned mac address.
            # So discard already installed stale flow entry which conflicts
            # new port.
            rule = nx_match.ClsRule()
            rule.set_dl_dst(src)
            datapath.send_flow_mod(rule=rule, cookie=0,
                command=datapath.ofproto.OFPFC_DELETE, idle_timeout=0,
                hard_timeout=0, priority=datapath.ofproto.OFP_DEFAULT_PRIORITY,
                out_port=old_port)

            # to make sure the old flow entries are purged.
            datapath.send_barrier()

        src_nw_id = self.mac2net.get_network(src, NW_ID_UNKNOWN)
        dst_nw_id = self.mac2net.get_network(dst, NW_ID_UNKNOWN)

        # If (input port belongs to a delegated network):
        #    Add FlowSpace for (dpid, port, src_mac)
        #    Drop current packet
        # Else if ((port is an external) AND (src_mac belongs to a delegated network)):
        #    Add FlowSpace for (dpid, port, src_mac)
        #    Drop current packet
        port_sliceName = self.fv_cli.getSliceName(port_nw_id)
        src_sliceName = self.fv_cli.getSliceName(src_nw_id)
        if port_sliceName or \
           ((port_nw_id == NW_ID_EXTERNAL) and src_sliceName):
            sliceName = port_sliceName or src_sliceName

            # Add FV rules if target the slice is not the default slice and if
            #    there currently exists no rules matching (dpid, port, mac).
            #    The second condition avoids installing duplicate rules if subsequent
            #    packets are queued in Ryu before rule installation triggered
            #    from first packet is completed
            if (sliceName != self.fv_cli.defaultSlice) and \
               (len(self.fv_cli.getFlowSpaceIDs(datapath.id, msg.in_port, src)) == 0):
                # ORDER OF INSTALLING RULES IS IMPORTANT! Install rules for other switches
                #   before installing rules for source switch. This avoids subsequent
                #   packets from reaching non-source switches before rules can be properly
                #   installed on them, which will trigger duplicate rules to be isntalled.
                # Need to install mac for all EXTERNAL ports throughout network
                for (dpid, port) in self.nw.list_ports(NW_ID_EXTERNAL):
                    if (dpid == datapath.id):
                        continue

                    ret = self.fv_cli.addFlowSpace(sliceName, dpid, port, haddr_to_str(src))
                    if (ret.find("success") == -1):
                        # Error, how to handle?
                        pass
                    else:
                        self.fv_cli.addFlowSpaceID(dpid, port, src, int(ret[9:]))

                # Now install rule on source switch
                ret = self.fv_cli.addFlowSpace(sliceName, datapath.id, msg.in_port, haddr_to_str(src))
                if (ret.find("success") == -1):
                    # Error, how to handle?
                    pass
                else:
                    self.fv_cli.addFlowSpaceID(datapath.id, msg.in_port, src, int(ret[9:]))

            self._drop_packet(msg)
            return

        # we handle multicast packet as same as broadcast
        broadcast = (dst == mac.BROADCAST) or mac.is_multicast(dst)
        out_port = self.mac2port.port_get(datapath.id, dst)

        #
        # there are several combinations:
        # in_port: known nw_id, external, unknown nw,
        # src mac: known nw_id, external, unknown nw,
        # dst mac: known nw_id, external, unknown nw, and broadcast/multicast
        # where known nw_id: is quantum network id
        #       external: means that these ports are connected to outside
        #       unknown nw: means that we don't know this port is bounded to
        #                   specific nw_id or external
        #       broadcast: the destination mac address is broadcast address
        #                  (or multicast address)
        #
        # Can the following logic be refined/shortened?
        #

        # When NW_ID_UNKNOWN is found, registering ports might be delayed.
        # So just drop only this packet and not install flow entry.
        # It is expected that when next packet arrives, the port is registers
        # with some network id

        if port_nw_id != NW_ID_EXTERNAL and port_nw_id != NW_ID_UNKNOWN:
            if broadcast:
                # flood to all ports of external or src_nw_id
                self._flood_to_nw_id(msg, src, dst, src_nw_id)
            elif src_nw_id == NW_ID_EXTERNAL:
                self._modflow_and_drop_packet(msg, src, dst)
                return
            elif src_nw_id == NW_ID_UNKNOWN:
                self._drop_packet(msg)
                return
            else:
                # src_nw_id != NW_ID_EXTERNAL and src_nw_id != NW_ID_UNKNOWN:
                #
                # try learned mac check if the port is net_id
                # or
                # flood to all ports of external or src_nw_id
                self._learned_mac_or_flood_to_nw_id(msg, src, dst,
                                                    src_nw_id, out_port)

        elif port_nw_id == NW_ID_EXTERNAL:
            if src_nw_id != NW_ID_EXTERNAL and src_nw_id != NW_ID_UNKNOWN:
                if broadcast:
                    # flood to all ports of external or src_nw_id
                    self._flood_to_nw_id(msg, src, dst, src_nw_id)
                elif (dst_nw_id != NW_ID_EXTERNAL and
                      dst_nw_id != NW_ID_UNKNOWN):
                    if src_nw_id == dst_nw_id:
                        # try learned mac
                        # check if the port is external or same net_id
                        # or
                        # flood to all ports of external or src_nw_id
                        self._learned_mac_or_flood_to_nw_id(msg, src, dst,
                                                            src_nw_id,
                                                            out_port)
                    else:
                        # should not occur?
                        LOG.debug("should this case happen?")
                        self._drop_packet(msg)
                elif dst_nw_id == NW_ID_EXTERNAL:
                    # try learned mac
                    # or
                    # flood to all ports of external or src_nw_id
                    self._learned_mac_or_flood_to_nw_id(msg, src, dst,
                                                        src_nw_id, out_port)
                else:
                    assert dst_nw_id == NW_ID_UNKNOWN
                    LOG.debug("Unknown dst_nw_id")
                    self._drop_packet(msg)
            elif src_nw_id == NW_ID_EXTERNAL:
                self._modflow_and_drop_packet(msg, src, dst)
            else:
                # should not occur?
                assert src_nw_id == NW_ID_UNKNOWN
                self._drop_packet(msg)
        else:
            # drop packets
            assert port_nw_id == NW_ID_UNKNOWN
            self._drop_packet(msg)
    def packet_in_handler(self, ev):
        
        def drop():
            LOG.error("\tImplement drop function")
            
        def flood():
            LOG.warn("\tFlooding packet")
            for (iDpid, switch) in self.G.nodes(data='switch'):

                #Initialize ports
                ports = []
                #Add local port if that is not the originating port
                #if (iDpid,ofp.OFPP_LOCAL) != (dpid, in_port):
                #    ports += [ofp.OFPP_LOCAL]

                #Exclude the inter-switch and possible other incoming ports from flooding
                ports += [p.port_no for p in switch.ports if (iDpid,p.port_no) != (dpid, in_port) and p.port_no not in [self.G.get_edge_data(iDpid, jDpid)['port'] for jDpid in self.G.neighbors(iDpid)]]
                
                
                actions = [parser.OFPActionOutput(port, 0) for port in ports]

                if iDpid == dpid and buffer_id != None:
                    LOG.warn("\t\tFlooding Originating Switch %d using Buffer ID"%(iDpid))
                    req = parser.OFPPacketOut(dp, buffer_id = buffer_id, in_port=in_port, actions=actions)
                    switch.dp.send_msg(req)
                    
                elif len(actions) > 0:
                    LOG.warn("\t\tFlooding Switch %d"%(iDpid))
                    req = parser.OFPPacketOut(dp, buffer_id = ofp.OFP_NO_BUFFER, in_port=ofp.OFPP_CONTROLLER, actions=actions, data=data)
                    switch.dp.send_msg(req)        
            
        def output(tDpid, port):
            LOG.warn("\tOutputting packet")

            action = parser.OFPActionOutput(port, 0)
            
            if buffer_id != None:
                #Drop the packet from the buffer on the incoming switch to prevent buffer overflows.
                if tDpid != dpid:
                    LOG.warn("\tDropping buffer_id on incoming switch %d"%(dpid))
                    actions = []
                #Or forward if that is also the destination switch.
                else:
                    LOG.warn("\tOutputting via buffer_id on switch %d"%(tDpid))
                    actions = [ action ]
                    
                req = parser.OFPPacketOut(dp, buffer_id = buffer_id, in_port=in_port, actions=actions)
                dp.send_msg(req)
                
            #Forward packet through data-field.
            if buffer_id == None or tDpid != dpid:
                LOG.warn("\tOutputting on outgoing switch %d"%(tDpid))
                switch = self.G.node[tDpid]['switch']
                actions = [ action ]
                req = parser.OFPPacketOut(dp, buffer_id = ofp.OFP_NO_BUFFER, in_port=ofp.OFPP_CONTROLLER, actions=actions, data=data)
                switch.dp.send_msg(req)
        
        msg = ev.msg
        dp = msg.datapath
        dpid = msg.datapath.id
        in_port = msg.match['in_port']
        buffer_id = msg.buffer_id

        ofp = msg.datapath.ofproto
        parser = msg.datapath.ofproto_parser        
        
        if msg.reason == ofp.OFPR_NO_MATCH:
            reason = 'NO MATCH'
        elif msg.reason == ofp.OFPR_ACTION:
            reason = 'ACTION'
        elif msg.reason == ofp.OFPR_INVALID_TTL:
            reason = 'INVALID TTL'
        else:
            reason = 'unknown'
        
        data = msg.data        
        pkt = packet.Packet(data)
        eth = pkt.get_protocol(ethernet.ethernet)
        
        
        #LOG.debug("OpenFlowBackupRules: New incoming packet from %s at switch %d, port %d, for reason %s"%(eth.src,dpid,in_port,reason))        
        
        if self.CONF.observe_links and eth.ethertype == ether_types.ETH_TYPE_LLDP:
            # ignore LLDP related messages IF topology module has been enabled.
            #LOG.debug("\tIgnored LLDP packet due to enabled topology module")
            return

        LOG.warn("OpenFlowBackupRules: Accepted incoming packet from %s at switch %d, port %d, for reason %s"%(eth.src,dpid,in_port,reason))                
        LOG.debug("\t%s"%(msg))        
        LOG.debug("\t%s"%(pkt))

        SwitchPort = namedtuple('SwitchPort', 'dpid port')        
        
        #if in_port not in [port for _,port  in self.G.neighbors(dpid, data="port")]:
        if in_port not in [self.G.get_edge_data(dpid, jDpid)['port'] for jDpid in self.G.neighbors(dpid)]:
            # only relearn locations if they arrived from non-interswitch links
            self.mac_learning[eth.src] = SwitchPort(dpid, in_port)	#relearn the location of the mac-address
            LOG.warn("\tLearned or updated MAC address")
        else:
            LOG.warn("\tIncoming packet from switch-to-switch link, this should NOT occur.")
            #DROP it
        
        
        if mac.is_multicast( mac.haddr_to_bin(eth.dst) ):
            #Maybe we should do something with preconfigured broadcast trees, but that is a different problem for now.
            flood()
            LOG.warn("\tFlooded multicast packet")
        elif eth.dst not in self.mac_learning:
            flood()
            LOG.warn("\tFlooded unicast packet, unknown MAC address location")
        
        #ARP messages are too infrequent and volatile of nature to create flows for, output immediately
        elif eth.ethertype == ether_types.ETH_TYPE_ARP:
            output(self.mac_learning[eth.dst].dpid, self.mac_learning[eth.dst].port)
            LOG.warn("\tProcessed packet, send to recipient at %s"%(self.mac_learning[eth.dst],))
        #Create flow and output or forward.
        else:

            self._install_path(dpid, in_port, pkt)
             
            #Output the first packet to its destination
            output(self.mac_learning[eth.dst].dpid, self.mac_learning[eth.dst].port)
            LOG.warn("\tProcessed packet, sent to recipient at %s"%(self.mac_learning[eth.dst],))
    def packet_in_handler(self, ev):
        msg = ev.msg               # Objeto que representa la estuctura de datos PacketIn.
        datapath = msg.datapath    # Identificador del datapath correspondiente al switch.
        ofproto = datapath.ofproto # Protocolo utilizado que se fija en una etapa 
                                   # de negociacion entre controlador y switch

        ofp_parser=datapath.ofproto_parser # Parser con la version OF
					   # correspondiente

        in_port = msg.match['in_port'] # Puerto de entrada.

        destination_ip = msg.match['arp_tpa']
        origen_ip = msg.match['arp_spa']

        # Ahora analizamos el paquete utilizando las clases de la libreria packet.
        pkt = packet.Packet(msg.data)
        eth = pkt.get_protocol(ethernet.ethernet)

        # Extraemos la MAC de destino

        dst = eth.dst
        
        #Extramos la MAC de origen
        
        src = eth.src

	if src not in self.mac_to_port.keys():
		self.mac_to_port[src]=in_port

	if haddr_to_bin(dst) == mac.BROADCAST or mac.is_multicast(haddr_to_bin(dst)):
		# Creamos el conjunto de acciones: FLOOD
		actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_FLOOD)]

		# Ahora creamos el match  
		# fijando los valores de los campos 
		# que queremos casar.
		match = ofp_parser.OFPMatch(eth_dst=dst)

		# Creamos el conjunto de instrucciones.
		inst = [ofp_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]

		# Creamos el mensaje OpenFlow 
		mod = ofp_parser.OFPFlowMod(datapath=datapath, priority=0, match=match, instructions=inst, idle_timeout=30, buffer_id=msg.buffer_id)

		# Enviamos el mensaje.
		datapath.send_msg(mod)

	elif dst not in self.mac_to_port.keys():
		actions = [ofp_parser.OFPPacketOut(outproto.OFPP_FLOOD)]
		req = ofp_parser.OFPPacketOut(datapath, buffer_id, in_port, actions, data=msg.data)
		datapath.send_msg(req)

	else: 
		actions = [ofp_parser.OFPActionOutput(self.mac_to_port[dst])]

		# Ahora creamos el match  
		# fijando los valores de los campos 
		# que queremos casar.
		match = ofp_parser.OFPMatch(eth_dst=dst)

		# Creamos el conjunto de instrucciones.
		inst = [ofp_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]

		# Creamos el mensaje OpenFlow 
		mod = ofp_parser.OFPFlowMod(datapath=datapath, priority=0, match=match, instructions=inst, idle_timeout=30, buffer_id=msg.buffer_id)

		# Enviamos el mensaje.
		datapath.send_msg(mod)
    def packet_in_handler(self, ev):
        msg = ev.msg               # Objeto que representa la estuctura de datos PacketIn.
        datapath = msg.datapath    # Identificador del datapath correspondiente al switch.
        ofproto = datapath.ofproto # Protocolo utilizado que se fija en una etapa 
                                   # de negociacion entre controlador y switch

        ofp_parser=datapath.ofproto_parser # Parser con la version OF
                       # correspondiente

        in_port = msg.match['in_port'] # Puerto de entrada.
        
        pkt = packet.Packet(msg.data)
        eth = pkt.get_protocol(ethernet.ethernet)

        # Extraemos la MAC de destino
        dst = eth.dst  
        
        #Extramos la MAC de origen
        src = eth.src
        
        if src not in self.mac_to_port.keys():
            self.mac_to_port[src]=in_port
    
        if haddr_to_bin(dst) == mac.BROADCAST or mac.is_multicast(haddr_to_bin(dst)):
            print("BROADCAST")
            # Creamos el conjunto de acciones: FLOOD
            actions = []
    
            for j in self.tabla_vlan.keys():
                print("Puerto? ", j)
                if self.tabla_vlan.get(j)==self.tabla_vlan.get(in_port) and j !=in_port :
                    actions.append(ofp_parser.OFPActionOutput(j))
                    print("Vlan ", self.tabla_vlan.get(j),"puerto de entrada", in_port, "otros puertos ", j)
            
            match = ofp_parser.OFPMatch(eth_dst=dst,eth_src=src)
    
            # Creamos el conjunto de instrucciones.
            inst = [ofp_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]
    
            # Creamos el mensaje OpenFlow 
            mod = ofp_parser.OFPFlowMod(datapath=datapath, priority=0, match=match, instructions=inst, idle_timeout=30, buffer_id=msg.buffer_id)
    
            # Enviamos el mensaje.
            datapath.send_msg(mod)
    
        elif dst not in self.mac_to_port.keys():
            #actions = [ofp_parser.OFPPacketOut(ofproto.OFPP_FLOOD)]
            actions = []
            print("NO CONOZCO LA MAC ", dst)
            
            for i in self.tabla_vlan.keys():
                if self.tabla_vlan.get(i)==self.tabla_vlan.get(in_port) and i !=in_port :
                    actions.append(ofp_parser.OFPActionOutput(i))
                    print i
            
            print("QUIEN DE LA VLAN ", self.tabla_vlan.get(in_port), " TIENE LA MAC ", dst,"?")
            
            req = ofp_parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, actions=actions, data=msg.data)
            datapath.send_msg(req)
            
        elif self.tabla_vlan.get(self.mac_to_port.get(src)) == self.tabla_vlan.get(self.mac_to_port.get(dst)) :
            actions = [ofp_parser.OFPActionOutput(self.mac_to_port[dst])]
            print("Pasando paquetes de la vlan ", self.tabla_vlan.get(self.mac_to_port.get(src)))
            # fijando los valores de los campos que queremos casar.
            match = ofp_parser.OFPMatch(eth_dst=dst,eth_src=src)
    
            # Creamos el conjunto de instrucciones.
            inst = [ofp_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]
    
            # Creamos el mensaje OpenFlow 
            mod = ofp_parser.OFPFlowMod(datapath=datapath, priority=0, match=match, instructions=inst, buffer_id=msg.buffer_id)
            #mod = ofp_parser.OFPFlowMod(datapath=datapath, priority=0, match=match, instructions=inst, idle_timeout=30, buffer_id=msg.buffer_id)
    
            # Enviamos el mensaje.
            datapath.send_msg(mod)
        else: #Si no son de la misma vlan, tira el paquete
            
            for INTERFACE in interfaces_virtuales.keys():
                if eth.ethertype==ether.ETH_TYPE_ARP and interfaces_virtuales.get(INTERFACE)[2]==pkt_arp.ipv4_dst:
                    pkt_arp=pkt.get_protocol(arp.arp)
                    self.ARPPacket(pkt_arp,in_port,datapath)
                
                elif(interfaces_virtuales.get(INTERFACE)[0]==dst):

                    match = ofp_parser.OFPMatch(eth_dst=interfaces_virtuales.get(INTERFACE)[0])
                    goto = ofp_parser.OFPInstructionGotoTable(1)
                    mod = ofp_parser.OFPFlowMod(datapath=datapath,priority=0, match=match,instructions=[goto],buffer_id)
                    datapath.send_msg(mod)
                    self.paquete_para_enrutar(ev)
                else:
                    print("Paquete fuera de red")
Beispiel #17
0
    def packet_in_handler(self, ev):
        # LOG.debug('packet in ev %s msg %s', ev, ev.msg)
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto

        dst, src, _eth_type = struct.unpack_from('!6s6sH', buffer(msg.data), 0)
        LOG.info("packet in from port %s of dpid %s", msg.in_port, hex(datapath.id))
        LOG.info("src mac %s, dst mac %s", haddr_to_str(src), haddr_to_str(dst))

        try:
            port_nw_id = self.nw.get_network(datapath.id, msg.in_port)
        except PortUnknown:
            port_nw_id = NW_ID_UNKNOWN

        if port_nw_id != NW_ID_UNKNOWN:
            # Here it is assumed that the
            # (port <-> network id)/(mac <-> network id) relationship
            # is stable once the port is created. The port will be destroyed
            # before assigning new network id to the given port.
            # This is correct nova-network/nova-compute.
            try:
                # allow external -> known nw id change
                self.mac2net.add_mac(src, port_nw_id, NW_ID_EXTERNAL)
                self.api_db.addMAC(port_nw_id, haddr_to_str(src))
            except MacAddressDuplicated:
                LOG.warn('mac address %s is already in use.'
                         ' So (dpid %s, port %s) can not use it',
                         haddr_to_str(src), datapath.id, msg.in_port)
                #
                # should we install drop action pro-actively for future?
                #
                self._drop_packet(msg)
                return

        old_port = self.mac2port.port_add(datapath.id, msg.in_port, src)
        if old_port is not None and old_port != msg.in_port:
            # We really overwrite already learned mac address.
            # So discard already installed stale flow entry which conflicts
            # new port.
            rule = nx_match.ClsRule()
            rule.set_dl_dst(src)
            datapath.send_flow_mod(rule=rule,
                                   cookie=0,
                                   command=ofproto.OFPFC_DELETE,
                                   idle_timeout=0,
                                   hard_timeout=0,
                                   priority=ofproto.OFP_DEFAULT_PRIORITY,
                                   out_port=old_port)

            # to make sure the old flow entries are purged.
            datapath.send_barrier()

        src_nw_id = self.mac2net.get_network(src, NW_ID_UNKNOWN)
        dst_nw_id = self.mac2net.get_network(dst, NW_ID_UNKNOWN)

        # If (input port belongs to a delegated network):
        #    Add FlowSpace for (dpid, port, src_mac)
        #    Drop current packet
        # Else if ((port is an external) AND (src_mac belongs to a delegated network)):
        #    Add FlowSpace for (dpid, port, src_mac)
        #    Drop current packet
        port_sliceName = self.fv_cli.getSliceName(port_nw_id)
        src_sliceName = self.fv_cli.getSliceName(src_nw_id)
        if port_sliceName or \
           ((port_nw_id == NW_ID_EXTERNAL) and src_sliceName):
            sliceName = port_sliceName or src_sliceName

            # Add FV rules if the target slice is not the default slice and if
            #    there currently exists no rules matching (dpid, port, mac).
            #    The second condition avoids installing duplicate rules if subsequent
            #    packets are queued in Ryu before rule installation triggered
            #    from first packet is completed
            if (sliceName != self.fv_cli.defaultSlice) and \
               (len(self.fv_cli.getFlowSpaceIDs(datapath.id, msg.in_port, src)) == 0):
                # ORDER OF INSTALLING RULES IS IMPORTANT! Install rules for other switches
                #   before installing rules for source switch. This avoids subsequent
                #   packets from reaching non-source switches before rules can be properly
                #   installed on them, which will trigger duplicate rules to be isntalled.
                # Need to install mac for all EXTERNAL ports throughout network
                for (dpid, port) in self.nw.list_ports(NW_ID_EXTERNAL):
                    if (dpid == datapath.id):
                        continue

                    ret = self.fv_cli.addFlowSpace(sliceName, dpid, port, haddr_to_str(src))
                    if (ret.find("success") == -1):
                        # Error, how to handle?
                        LOG.debug("Error while installing FlowSpace for slice %s: (%s, %s, %s)",\
                                    sliceName, dpid, str(port), haddr_to_str(src))
                    else:
                        self.fv_cli.addFlowSpaceID(dpid, port, src, int(ret[9:]))
                        self.api_db.addFlowSpaceID(hex(dpid), port, haddr_to_str(src), int(ret[9:]))

                # Now install rule on source switch
                ret = self.fv_cli.addFlowSpace(sliceName, datapath.id, msg.in_port, haddr_to_str(src))
                if (ret.find("success") == -1):
                    # Error, how to handle?
                    LOG.debug("Error while installing FlowSpace for slice %s: (%s, %s, %s)",\
                                sliceName, dpid, str(port), haddr_to_str(src))
                else:
                    self.fv_cli.addFlowSpaceID(datapath.id, msg.in_port, src, int(ret[9:]))
                    self.api_db.addFlowSpaceID(hex(datapath.id), msg.in_port, haddr_to_str(src), int(ret[9:]))

            self._drop_packet(msg)
            return

        # we handle multicast packet as same as broadcast
        broadcast = (dst == mac.BROADCAST) or mac.is_multicast(dst)
        out_port = self.mac2port.port_get(datapath.id, dst)

        if src_nw_id == NW_ID_PXE or src_nw_id == NW_ID_PXE_CTRL:
            self.pktHandling_PXE(msg, datapath, ofproto, dst, src, broadcast,
                                    port_nw_id, src_nw_id, dst_nw_id, out_port)
        elif src_nw_id == NW_ID_MGMT or src_nw_id == NW_ID_MGMT_CTRL:
            self.pktHandling_MGMT(msg, datapath, ofproto, dst, src, broadcast,
                                    port_nw_id, src_nw_id, dst_nw_id, out_port)
        else:
            self.pktHandling_BaseCase(msg, datapath, ofproto, dst, src, broadcast,
                                        port_nw_id, src_nw_id, dst_nw_id, out_port)
        LOG.info("\n")