def test_mac_is_multicast(self): addr = b'\x01\x23\x45\x67\x89\x0a' val = True res = mac.is_multicast(addr) eq_(val, res)
def test_mac_is_multicast(self): addr = b"\x01\x23\x45\x67\x89\x0a" val = True res = mac.is_multicast(addr) eq_(val, res)
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)
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)
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)
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): # 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)
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)
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")
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)
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)
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")
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")