def _packet_in_handler(self, ev): msg = ev.msg pkt = packet.Packet(msg.data) pkt_ethernet = pkt.get_protocols(ethernet.ethernet)[0] datapath = msg.datapath port = msg.match['in_port'] # Checking if it's the probe packet for RTT estimation if pkt_ethernet.ethertype == self.PROBE_ETHERTYPE: self.probe_packet_handler(pkt) return # Ignoring LLDP Packets try: LLDPPacket.lldp_parse(msg.data) self.logger.debug('Received LLDP Packet') return except: pass self.logger.debug('EventOFPPacketIn %s' % pkt) # Handling ARP pkt_arp = pkt.get_protocol(arp.arp) if pkt_arp: self._handle_arp(msg, datapath, port, pkt, pkt_arp) return pkt_ipv4 = pkt.get_protocol(ipv4.ipv4) pkt_icmp = pkt.get_protocol(icmp.icmp) # Handling ICMPv4 if pkt_icmp: self._handle_icmpv4( msg, datapath, port, pkt_ethernet, pkt_ipv4, pkt_icmp) return # Handing IPv4 if pkt_ipv4: self._handle_ipv4(datapath, port, pkt_ethernet, pkt_ipv4) return pkt_ipv6 = pkt.get_protocol(ipv6.ipv6) pkt_icmp = pkt.get_protocol(icmpv6.icmpv6) # Handling ICMPv6 if pkt_icmp: self._handle_icmpv6( datapath, port, pkt_ethernet, pkt_ipv6, pkt_icmp) return # Handing IPv6 if pkt_ipv4: self._handle_ipv6(datapath, port, pkt_ethernet, pkt_ipv4) return # Unhandled self.logger.debug('Unknown packet %s' % str(pkt))
def _packet_in_handler(self, ev): msg = ev.msg pkt = packet.Packet(msg.data) pkt_ethernet = pkt.get_protocols(ethernet.ethernet)[0] datapath = msg.datapath port = msg.match['in_port'] # Checking if it's the probe packet for RTT estimation if pkt_ethernet.ethertype == self.PROBE_ETHERTYPE: self.probe_packet_handler(pkt) return # Ignoring LLDP Packets try: LLDPPacket.lldp_parse(msg.data) self.logger.debug('Received LLDP Packet') return except: pass self.logger.debug('EventOFPPacketIn %s' % pkt) # Handling ARP pkt_arp = pkt.get_protocol(arp.arp) if pkt_arp: self._handle_arp(msg, datapath, port, pkt, pkt_arp) return pkt_ipv4 = pkt.get_protocol(ipv4.ipv4) pkt_icmp = pkt.get_protocol(icmp.icmp) # Handling ICMPv4 if pkt_icmp: self._handle_icmpv4(msg, datapath, port, pkt_ethernet, pkt_ipv4, pkt_icmp) return # Handing IPv4 if pkt_ipv4: self._handle_ipv4(datapath, port, pkt_ethernet, pkt_ipv4) return pkt_ipv6 = pkt.get_protocol(ipv6.ipv6) pkt_icmp = pkt.get_protocol(icmpv6.icmpv6) # Handling ICMPv6 if pkt_icmp: self._handle_icmpv6(datapath, port, pkt_ethernet, pkt_ipv6, pkt_icmp) return # Handing IPv6 if pkt_ipv4: self._handle_ipv6(datapath, port, pkt_ethernet, pkt_ipv4) return # Unhandled self.logger.debug('Unknown packet %s' % str(pkt))
def _packet_in_handler(self, ev): # If you hit this you might want to increase # the "miss_send_length" of your switch if ev.msg.msg_len < ev.msg.total_len: self.logger.debug("packet truncated: only %s of %s bytes", ev.msg.msg_len, ev.msg.total_len) msg = ev.msg try: # ignore lldp packet LLDPPacket.lldp_parse(msg.data) return except LLDPPacket.LLDPUnknownFormat: pass datapath = msg.datapath ofproto = datapath.ofproto parser = datapath.ofproto_parser in_port = msg.match['in_port'] pkt = packet.Packet(msg.data) eth = pkt.get_protocols(ethernet.ethernet)[0] dst = eth.dst src = eth.src dpid = datapath.id self.mac_to_port.setdefault(dpid, {}) self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port) # learn a mac address to avoid FLOOD next time. self.mac_to_port[dpid][src] = in_port if dst in self.mac_to_port[dpid]: out_port = self.mac_to_port[dpid][dst] else: out_port = ofproto.OFPP_FLOOD actions = [parser.OFPActionOutput(out_port)] # install a flow to avoid packet_in next time if out_port != ofproto.OFPP_FLOOD: match = parser.OFPMatch(in_port=in_port, eth_dst=dst) # verify if we have a valid buffer_id, if yes avoid to send both # flow_mod & packet_out if msg.buffer_id != ofproto.OFP_NO_BUFFER: self.add_flow(datapath, 1, match, actions, msg.buffer_id) return else: self.add_flow(datapath, 1, match, actions) data = None if msg.buffer_id == ofproto.OFP_NO_BUFFER: data = msg.data out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, actions=actions, data=data) datapath.send_msg(out)
def packet_in_handler(self, ev): """ Parsing LLDP packet and get the delay of link. """ msg = ev.msg try: src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data) dpid = msg.datapath.id if self.sw_module is None: self.sw_module = lookup_service_brick('switches') for port in self.sw_module.ports.keys(): if src_dpid == port.dpid and src_port_no == port.port_no: delay = self.sw_module.ports[port].delay self._save_lldp_delay(src=src_dpid, dst=dpid, lldpdelay=delay) except LLDPPacket.LLDPUnknownFormat as e: return
def packet_in_handler(self, ev): msg = ev.msg datapath = msg.datapath try: #LLDP handler src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data) dst_dpid, dst_port_no = datapath.id, msg.match['in_port'] self.add_topo(src_dpid, dst_dpid, src_port_no, dst_port_no) link = api.get_link(self) print self.topo for i in link: src = i.src dst = i.dst self.topo[(src.dpid, dst.dpid)] = (src.port_no, dst.port_no) except LLDPPacket.LLDPUnknownFormat: ofproto = datapath.ofproto parser = datapath.ofproto_parser pkt = packet.Packet(msg.data) eth = pkt.get_protocols(ethernet.ethernet)[0] mac = eth.src dpid, port = datapath.id, msg.match['in_port'] actions = [parser.OFPActionOutput(ofproto.OFPP_FLOOD)] data = None if msg.buffer_id == ofproto.OFP_NO_BUFFER: data = msg.data out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=port, actions=actions, data=data) datapath.send_msg(out)
def packet_in_handler(self, ev): """ Controller | /|\ \|/ | Switch----->Switch """ msg = ev.msg try: src_dpid, src_outport = LLDPPacket.lldp_parse(msg.data) dst_dpid = msg.datapath.id dst_inport = msg.match['in_port'] if self.switches is None: self.switches = lookup_service_brick("switches") for port in self.switches.ports.keys(): if src_dpid == port.dpid and src_outport == port.port_no: port_data = self.switches.ports[port] timestamp = port_data.timestamp if timestamp: delay = time.time() - timestamp self._save_delay_data(src=src_dpid, dst=dst_dpid, src_port=src_outport, lldpdealy=delay) except: return
def _packet_in_handler(self, ev): msg = ev.msg try: # ignore lldp packet LLDPPacket.lldp_parse(msg.data) return except LLDPPacket.LLDPUnknownFormat: pass datapath = msg.datapath ofproto = datapath.ofproto parser = datapath.ofproto_parser in_port = msg.match["in_port"] pkt = packet.Packet(msg.data) eth = pkt.get_protocols(ethernet.ethernet)[0] dst = eth.dst src = eth.src dpid = datapath.id self.mac_to_port.setdefault(dpid, {}) self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port) # learn a mac address to avoid FLOOD next time. self.mac_to_port[dpid][src] = in_port if dst in self.mac_to_port[dpid]: out_port = self.mac_to_port[dpid][dst] else: out_port = ofproto.OFPP_FLOOD actions = [parser.OFPActionOutput(out_port)] # install a flow to avoid packet_in next time if out_port != ofproto.OFPP_FLOOD: match = parser.OFPMatch(in_port=in_port, eth_dst=dst) self.add_flow(datapath, 1, match, actions) data = None if msg.buffer_id == ofproto.OFP_NO_BUFFER: data = msg.data out = parser.OFPPacketOut( datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, actions=actions, data=data ) datapath.send_msg(out)
def _packet_in_handler(self, ev): """Handle packet_in events.""" if not self.link_discovery: return msg = ev.msg in_port = msg.match['in_port'] packet = Packet(msg.data) efm = packet.get_protocol(ethernet.ethernet) if efm.ethertype == ether.ETH_TYPE_ARP: self.send_event_to_observers(event.EventArpReceived(ev)) try: src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data) except LLDPPacket.LLDPUnknownFormat as e: # This handler can receive all the packtes which can be # not-LLDP packet. Ignore it silently return else: dst_dpid = msg.datapath.id dst_port_no = in_port src = self._get_port(src_dpid, src_port_no) if not src or src.dpid == dst_dpid: return dst = self._get_port(dst_dpid, dst_port_no) if not dst: return old_peer = self.links.get_peer(src) #LOG.debug("Packet-In") #LOG.debug(" src=%s", src) #LOG.debug(" dst=%s", dst) #LOG.debug(" old_peer=%s", old_peer) if old_peer and old_peer != dst: old_link = Link(src, old_peer) self.send_event_to_observers(event.EventLinkDelete(old_link)) link = Link(src, dst) if not link in self.links: self.send_event_to_observers(event.EventLinkAdd(link)) if not self.links.update_link(src, dst): # reverse link is not detected yet. # So schedule the check early because it's very likely it's up try: self.ports.lldp_received(dst) except KeyError as e: # There are races between EventOFPPacketIn and # EventDPPortAdd. So packet-in event can happend before # port add event. In that case key error can happend. # LOG.debug('lldp_received: KeyError %s', e) pass else: self.ports.move_front(dst) self.lldp_event.set()
def _packet_in_handler(self, ev): """Handle packet_in events.""" if not self.link_discovery: return msg = ev.msg in_port = msg.match['in_port'] packet = Packet(msg.data) efm = packet.next() if efm.ethertype == ether.ETH_TYPE_ARP: self.send_event_to_observers(event.EventArpReceived(ev)) try: src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data) except LLDPPacket.LLDPUnknownFormat as e: # This handler can receive all the packtes which can be # not-LLDP packet. Ignore it silently return else: dst_dpid = msg.datapath.id dst_port_no = in_port src = self._get_port(src_dpid, src_port_no) if not src or src.dpid == dst_dpid: return dst = self._get_port(dst_dpid, dst_port_no) if not dst: return old_peer = self.links.get_peer(src) #LOG.debug("Packet-In") #LOG.debug(" src=%s", src) #LOG.debug(" dst=%s", dst) #LOG.debug(" old_peer=%s", old_peer) if old_peer and old_peer != dst: old_link = Link(src, old_peer) self.send_event_to_observers(event.EventLinkDelete(old_link)) link = Link(src, dst) if not link in self.links: self.send_event_to_observers(event.EventLinkAdd(link)) if not self.links.update_link(src, dst): # reverse link is not detected yet. # So schedule the check early because it's very likely it's up try: self.ports.lldp_received(dst) except KeyError as e: # There are races between EventOFPPacketIn and # EventDPPortAdd. So packet-in event can happend before # port add event. In that case key error can happend. # LOG.debug('lldp_received: KeyError %s', e) pass else: self.ports.move_front(dst) self.lldp_event.set()
def _packet_in_handler(self, ev): try: msg = ev.msg LLDPPacket.lldp_parse(msg.data) return except LLDPPacket.LLDPUnknownFormat: # it's host dpid = msg.datapath.id port = -1 if msg.datapath.ofproto.OFP_VERSION == ofproto_v1_0.OFP_VERSION: port = msg.in_port elif msg.datapath.ofproto.OFP_VERSION >= ofproto_v1_2.OFP_VERSION: port = msg.match['in_port'] if port >= 1024: # hack: ignore some strange port return # ignore global host for link in self.cross_domain_links: if link['src']['dpid'] == dpid and \ link['src']['port'] == port: return # TODO, check again if host already in global port pkt = packet.Packet(msg.data) eth = pkt.get_protocols(ethernet.ethernet)[0] mac = eth.src if mac not in self.hosts and port != -1 and \ not self._host_exist_in_port(dpid, port) and \ not self._is_switch_port_to_port(dpid, port): LOG.debug('Add host %s to %d:%d', mac, dpid, port) self.hosts[mac] = (dpid, port) self.response_host(mac) ev = EventHostDiscovery(dpid, port, mac) self.send_event_to_observers(ev)
def _packet_in_handler(self, ev): msg = ev.msg datapath = msg.datapath ofproto = datapath.ofproto parser = datapath.ofproto_parser # get Datapath ID to identify OpenFlow switches. dpid = datapath.id self.mac_to_port.setdefault(dpid, {}) # analyse the received packets using the packet library. pkt = packet.Packet(msg.data) eth_pkt = pkt.get_protocol(ethernet.ethernet) dst = eth_pkt.dst src = eth_pkt.src # get the received port number from packet_in message. in_port = msg.match['in_port'] if eth_pkt.ethertype == ether_types.ETH_TYPE_LLDP: print LLDPPacket.lldp_parse(msg.data) self.logger.info("packet in %s %s %s %s %x", dpid, src, dst, in_port, eth_pkt.ethertype)
def handle_lldp_packet(self, ev): msg = ev.msg try: src_dpid, src_port_no, timestamp = LLDPPacket.lldp_parse(msg.data) dpid = msg.datapath.id if self.sw_module is None: self.sw_module = lookup_service_brick('switches') for port in self.sw_module.ports.keys(): if src_dpid == port.dpid and src_port_no == port.port_no: delay = self.sw_module.ports[port].delay self.graph[src_dpid][dpid]['lldpdelay'] = delay except LLDPPacket.LLDPUnknownFormat as e: return
def packet_in_hander(self, ev): msg = ev.msg dpid = msg.datapath.id try: src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data) if self.switches is None: self.switches = lookup_service_brick('switches') for port in self.switches.ports.keys(): if src_dpid == port.dpid and src_port_no == port.port_no: self.lldp_delay[(src_dpid, dpid)] = self.switches.ports[port].delay except: return
def packet_in_handler(self, ev): self._logger.debug('Packet in') msg = ev.msg ofp = msg.datapath.ofproto pkt = packet.Packet(msg.data) headers = dict((p.protocol_name, p) for p in pkt.protocols if type(p) != str) src_mac = headers[ETHERNET].src try: src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data) except LLDPPacket.LLDPUnknownFormat as e: self._logger.debug('LLDPUnknownFormat %s', e) return dst_port_no = self.ofctl.get_packet_in_inport(msg) dst = self._get_port(dst_port_no) self._logger.debug('LLDP from %d.%d -> %d', src_dpid, src_port_no, dst_port_no) if not dst: self._logger.warning('Dst not found.') return self.ports.lldp_received(dst) src = Port(PortData(src_dpid, port_no=src_port_no, hw_addr=src_mac)) old_peer = self.links.get_peer(dst) need_update = False if old_peer and old_peer != src: self._logger.info('Peer changed.') self._report_link_deleted(Link(old_peer, dst)) need_update = True link = Link(src, dst) if link not in self.links: need_update = True self._report_link_added(Link(src, dst)) self.lldp_event.set() # Always return false, since we don't have the reverse link information if need_update: self.links.update_link(src, dst) self._logger.info('Update link %d.%d -> %d.%d', src.dpid, src.port_no, dst.dpid, dst.port_no)
def packet_in_handler(self, ev): msg = ev.msg try: src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data) dpid = msg.datapath.id in_port = msg.match['in_port'] if self.sw_module is None: self.sw_module = lookup_service_brick('switches') for port in self.sw_module.ports.keys(): if src_dpid == port.dpid and src_port_no == port.port_no: port_data = self.sw_module.ports[port] timestamp = port_data.timestamp if timestamp: delay = time.time() - timestamp self._save_lldp_delay(src=src_dpid, dst=dpid, lldpdelay=delay) except LLDPPacket.LLDPUnknownFormat as e: return
def packet_in_handler(self, ev): msg = ev.msg dp = msg.datapath ofp = dp.ofproto ofp_parser = dp.ofproto_parser port = msg.match['in_port'] ## parses the packet pkt = packet.Packet(data=msg.data) # ethernet pkt_ethernet = pkt.get_protocol(ethernet.ethernet) if not pkt_ethernet: return # 當為LLDP packet時,把lldpdelay資料取出來 if pkt_ethernet.ethertype == 35020: try: src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data) dst_dpid = msg.datapath.id if self.switch_mod is None: self.switch_mod = lookup_service_brick('switches') for port in self.switch_mod.ports.keys(): if src_dpid == port.dpid and src_port_no == port.port_no: lldpdelay = self.switch_mod.ports[port].delay self.net[src_dpid][dst_dpid]["lldpdelay"] = lldpdelay except LLDPPacket.LLDPUnknownFormat as e: return if msg.buffer_id == ofp.OFP_NO_BUFFER: data = msg.data # arp封包处理 if pkt_ethernet.dst == 'ff:ff:ff:ff:ff:ff': if self.mac_learning(dp, pkt_ethernet.src, port) is False: #判断是否会造成广播风暴,False代表為是會造成 out_port = ofp.OFPPC_NO_RECV #将封包丢掉 else: out_port = ofp.OFPP_FLOOD #做flooding if not self.net.has_node( pkt_ethernet.src): #若arp封包源沒有包含在圖裡面,則將它加入進圖中 self.net.add_node(pkt_ethernet.src) self.net.add_edge(pkt_ethernet.src, dp.id, bw=0, delay=0, lldpdelay=0) #添加雙向的邊 self.net.add_edge(dp.id, pkt_ethernet.src, port=port, bw=0, delay=0, lldpdelay=0) self.idport_to_id.update({(dp.id, port): pkt_ethernet.src}) print(self.idport_to_id) print(self.net.nodes()) print(self.net.edges()) actions = [ofp_parser.OFPActionOutput(out_port)] #inst = [actions] out = ofp_parser.OFPPacketOut(datapath=dp, buffer_id=msg.buffer_id, in_port=port, actions=actions, data=data) dp.send_msg(out) return if pkt_ethernet.ethertype != 34525 and pkt_ethernet.ethertype != 35020: if not self.net.has_node(pkt_ethernet.src): #如果不在图里则新增 print("add %s in self.net" % pkt_ethernet.src) #print(pkt_ethernet.ethertype) self.net.add_node(pkt_ethernet.src) self.net.add_edge(pkt_ethernet.src, dp.id, bw=0, delay=0, lldpdelay=0) #self.net.add_edge(dp.id, pkt_ethernet.src, {'port':port}) self.net.add_edge(dp.id, pkt_ethernet.src, port=port, bw=0, delay=0, lldpdelay=0) self.idport_to_id.update({(dp.id, port): pkt_ethernet.src}) print(self.idport_to_id) print(self.net.nodes()) print(self.net.edges.data()) if self.net.has_node(pkt_ethernet.dst): print("%s in self.net" % pkt_ethernet.dst) path = nx.dijkstra_path(self.net, pkt_ethernet.src, pkt_ethernet.dst, weight='bw') #以当前bw作最短路徑轉發 next_match = ofp_parser.OFPMatch(eth_dst=pkt_ethernet.dst, eth_src=pkt_ethernet.src) back_match = ofp_parser.OFPMatch(eth_dst=pkt_ethernet.src, eth_src=pkt_ethernet.dst) print(path) #依照計算后算出的路徑下發流表 for on_path_switch in range(1, len(path) - 1): now_switch = path[on_path_switch] #这里需要知道現在,之前以及之後的switch next_switch = path[on_path_switch + 1] back_switch = path[on_path_switch - 1] next_port = self.net[now_switch][next_switch]['port'] back_port = self.net[now_switch][back_switch]['port'] action = ofp_parser.OFPInstructionActions( ofp.OFPIT_APPLY_ACTIONS, [ofp_parser.OFPActionOutput(next_port)]) inst = [action] self.add_flow(dp=self.switch_map[now_switch], match=next_match, inst=inst, table=0, idle_timeout=5) action = ofp_parser.OFPInstructionActions( ofp.OFPIT_APPLY_ACTIONS, [ofp_parser.OFPActionOutput(back_port)]) inst = [action] self.add_flow(dp=self.switch_map[now_switch], match=back_match, inst=inst, table=0, idle_timeout=5) print("now switch:%s" % now_switch) now_switch = path[1] next_switch = path[2] out_port = self.net[now_switch][next_switch]['port'] actions = [ofp_parser.OFPActionOutput(out_port)] out = ofp_parser.OFPPacketOut(datapath=dp, buffer_id=msg.buffer_id, in_port=port, actions=actions, data=data) dp.send_msg(out) else: return
def packet_in_handler(self, ev): msg = ev.msg dp = msg.datapath ofp = dp.ofproto parser = dp.ofproto_parser dpid = dp.id in_port = msg.match['in_port'] pkt = packet.Packet(msg.data) eth_pkt = pkt.get_protocols(ethernet.ethernet)[0] dst_mac = eth_pkt.dst src_mac = eth_pkt.src if eth_pkt.ethertype == ether_types.ETH_TYPE_LLDP: try: src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data) if self.switches is None: self.switches = lookup_service_brick('switches') for port in self.switches.ports.keys(): if src_dpid == port.dpid and src_port_no == port.port_no: self.lldp_delay[( src_dpid, dpid)] = self.switches.ports[port].delay except: return return if eth_pkt.ethertype == ether_types.ETH_TYPE_IPV6: return if src_mac not in self.graph: self.graph.add_node(src_mac) self.graph.add_edge(src_mac, dpid, weight=0) self.graph.add_edge(dpid, src_mac, weight=0, port=in_port) header_list = dict( (p.protocol_name, p) for p in pkt.protocols if type(p) != str) if dst_mac == ETHERNET_MULTICAST and ARP in header_list: arp_dst_ip = header_list[ARP].dst_ip if (dpid, src_mac, arp_dst_ip) in self.sw: if self.sw[(dpid, src_mac, arp_dst_ip)] != in_port: out = parser.OFPPacketOut(datapath=dp, buffer_id=ofp.OFP_NO_BUFFER, in_port=in_port, actions=[], data=None) dp.send_msg(out) return else: self.sw[(dpid, src_mac, arp_dst_ip)] = in_port # mac learning self.mac_to_port.setdefault(dpid, {}) self.paths.setdefault(src_mac, {}) out_port = ofp.OFPP_FLOOD if dst_mac in self.mac_to_port[dpid]: out_port = self.mac_to_port[dpid][dst_mac] else: if dst_mac in self.graph: if dst_mac not in self.paths[src_mac]: try: path = nx.shortest_path(self.graph, src_mac, dst_mac, weight="weight") self.paths[src_mac][dst_mac] = path except: return path = self.paths[src_mac][dst_mac] next_hop = path[path.index(dpid) + 1] out_port = self.graph[dpid][next_hop]['port'] self.mac_to_port[dpid][dst_mac] = out_port print path actions = [parser.OFPActionOutput(out_port)] if out_port != ofp.OFPP_FLOOD: match = parser.OFPMatch(in_port=in_port, eth_dst=dst_mac) self.add_flow(dp, 1, match, actions) data = None if msg.buffer_id == ofp.OFP_NO_BUFFER: data = msg.data out = parser.OFPPacketOut(datapath=dp, buffer_id=msg.buffer_id, in_port=in_port, actions=actions, data=data) dp.send_msg(out)
def packet_in_handler(self, ev): msg = ev.msg datapath = msg.datapath try: # src: from other switch src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data) # dst: this switch dst_dpid, dst_port_no = datapath.id, msg.match['in_port'] if src_dpid > 1024 or dst_dpid > 1024: # hack: ignote illegal switch return switch = api.get_switch(self, src_dpid) # not this topology switch if len(switch) != 0: return # send cross domain link add self.local_lib.send_cross_domain_link(dst_dpid, dst_port_no, src_dpid, src_port_no) # add global port self.global_port.setdefault(dst_dpid, []) self.global_port[dst_dpid].append(dst_port_no) return except LLDPPacket.LLDPUnknownFormat: # This handler can receive all the packtes which can be # not-LLDP packet. Ignore it silently pass # non-LLDP # local routing dpid = datapath.id pkt = packet.Packet(msg.data) eth = pkt.get_protocols(ethernet.ethernet)[0] src = eth.src dst = eth.dst if dst not in self.local_lib.hosts: # can't find host in local topology # ask global and let this msg queued if dst in mDNS or dst in multicast_list: return if dst == 'ff:ff:ff:ff:ff:ff': self._flood_packet(msg) return self.route_list.append((dst, msg)) self.local_lib.get_route(dst) return LOG.debug('Packet in, from %s, to %s', src, dst) # found in local, do local routing # two case: # 1. In same switch # 2. Not in same switch host = self.local_lib.hosts[dst] # host[0] -> dpid # host[1] -> port if host[0] == dpid: # same switch out_port = host[1] self._packet_out(msg, out_port) else: # not same switch # calculate path self._packet_out_to(msg, host[0], host[1])
def packet_in_handler(self, ev): AF3 = [104,112,120] EF = [184] msg= ev.msg dp = msg.datapath ofp = dp.ofproto ofp_parser = dp.ofproto_parser port = msg.match['in_port'] ## parses the packet pkt = packet.Packet(data=msg.data) # ethernet pkt_ethernet = pkt.get_protocol(ethernet.ethernet) if not pkt_ethernet: return # 當為LLDP packet時,把lldpdelay資料取出來 if pkt_ethernet.ethertype == 35020: try: src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data) dst_dpid = msg.datapath.id if self.switch_mod is None: self.switch_mod = lookup_service_brick('switches') for port in self.switch_mod.ports.keys(): if src_dpid == port.dpid and src_port_no == port.port_no: lldpdelay = self.switch_mod.ports[port].delay self.net[src_dpid][dst_dpid]["lldpdelay"] = lldpdelay except LLDPPacket.LLDPUnknownFormat as e: return if msg.buffer_id == ofp.OFP_NO_BUFFER: data = msg.data if pkt_ethernet.ethertype != 34525 and pkt_ethernet.ethertype != 35020: if not self.net.has_node(pkt_ethernet.src): #如果不在图里则新增 #print("add %s in self.net" % pkt_ethernet.src) #print(pkt_ethernet.ethertype) self.net.add_node(pkt_ethernet.src) self.net.add_edge(pkt_ethernet.src, dp.id, bw=0, delay=0, lldpdelay=0, load=0) self.net.add_edge(dp.id, pkt_ethernet.src, port=port, bw=0, delay=0, lldpdelay=0, load=0) self.idport_to_id.update({(dp.id,port):pkt_ethernet.src}) #print(self.idport_to_id) #print(self.net.nodes()) #print(self.net.edges.data()) # arp封包处理 arp_info = pkt.get_protocol(arp.arp) if arp_info != None: #代表是arp封包 if pkt_ethernet.dst == 'ff:ff:ff:ff:ff:ff': if self.mac_learning(dp,pkt_ethernet.src,port) is False: #判断是否会造成广播风暴,False代表為是會造成 out_port = ofp.OFPPC_NO_RECV #将封包丢掉 else: out_port = ofp.OFPP_FLOOD #做flooding #更新mac_to_port 表,之后要用来作arp封包的处理 self.mac_to_port.setdefault(dp.id, {}) self.mac_to_port[dp.id][pkt_ethernet.src] = port if not self.net.has_node(pkt_ethernet.src): #若arp封包源沒有包含在圖裡面,則將它加入進圖中 self.net.add_node(pkt_ethernet.src) self.net.add_edge(pkt_ethernet.src,dp.id,bw=0,delay=0, lldpdelay=0, load=0) #添加雙向的邊 self.net.add_edge(dp.id,pkt_ethernet.src,port=port,bw=0, delay=0, lldpdelay=0, load=0) self.idport_to_id.update({(dp.id,port):pkt_ethernet.src}) #print(self.idport_to_id) #print(self.net.nodes()) #print(self.net.edges()) actions = [ofp_parser.OFPActionOutput(out_port)] out = ofp_parser.OFPPacketOut(datapath=dp,buffer_id=msg.buffer_id,in_port=port,actions=actions,data=data) dp.send_msg(out) return else: if pkt_ethernet.dst in self.mac_to_port[dp.id]: out_port = self.mac_to_port[dp.id][pkt_ethernet.dst] actions = [ofp_parser.OFPActionOutput(out_port)] out = ofp_parser.OFPPacketOut(datapath=dp, buffer_id=msg.buffer_id, in_port=port, actions=actions, data=data) dp.send_msg(out) return if self.net.has_node(pkt_ethernet.dst): #print("%s in self.net" % pkt_ethernet.dst) ip_info = pkt.get_protocol(ipv4.ipv4) print(ip_info) if ip_info != None: path = [p for p in nx.all_shortest_paths(self.net, pkt_ethernet.src, pkt_ethernet.dst)] print("All shortest path") print(path) count = 0 meter_id = None print("finding avaliable shortest path...") for i in range(len(path)): for j in range(len(path[i])-1): if (path[i][j], path[i][j+1]) not in self.busy_link: count = count + 1 if count > 2: path = path[i] print("find shortest path!!") break count = 0 if i == len(path) - 1: print("cant find avaliable shortest path, finding other path...") if ip_info.tos in AF3: path = nx.dijkstra_path(self.net, pkt_ethernet.src, pkt_ethernet.dst, weight='bw') #以当前bw作最短路徑轉發 meter_id = 3 print("find min bandwidth path") elif ip_info.tos in EF: path = nx.dijkstra_path(self.net, pkt_ethernet.src, pkt_ethernet.dst, weight='delay') meter_id = 3 print("find min delay path") else: path = path[i] #ip_info.tos = 0 #强制其tos段等于0 meter_id = 3 print("dont change path, tos=0") print(path) next_match = ofp_parser.OFPMatch(eth_dst=pkt_ethernet.dst,eth_src=pkt_ethernet.src,eth_type=0x0800,ipv4_src=ip_info.src, ipv4_dst=ip_info.dst, ip_dscp=int(ip_info.tos/4)) back_match = ofp_parser.OFPMatch(eth_dst=pkt_ethernet.src,eth_src=pkt_ethernet.dst,eth_type=0x0800,ipv4_src=ip_info.src, ipv4_dst=ip_info.dst, ip_dscp=int(ip_info.tos/4)) #print(path) #依照計算后算出的路徑下發流表 for on_path_switch in range(1, len(path)-1): now_switch = path[on_path_switch] #这里需要知道現在,之前以及之後的switch next_switch = path[on_path_switch+1] back_switch = path[on_path_switch-1] next_port = self.net[now_switch][next_switch]['port'] back_port = self.net[now_switch][back_switch]['port'] action = ofp_parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [ofp_parser.OFPActionOutput(next_port)]) hard_timeout = 0 if meter_id == None: inst = [action] else: inst = [action, ofp_parser.OFPInstructionMeter(meter_id, ofp.OFPIT_METER)] hard_timeout = 10 self.add_flow(dp=self.switch_map[now_switch], match=next_match, inst=inst, table=0, idle_timeout=50, hard_timeout=hard_timeout) action = ofp_parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [ofp_parser.OFPActionOutput(back_port)]) self.add_flow(dp=self.switch_map[now_switch], match=back_match, inst=inst, table=0, idle_timeout=50, hard_timeout=hard_timeout) #print("now switch:%s" % now_switch) now_switch = path[1] next_switch = path[2] out_port = self.net[now_switch][next_switch]['port'] actions = [ofp_parser.OFPActionOutput(out_port)] out = ofp_parser.OFPPacketOut(datapath=dp,buffer_id=msg.buffer_id,in_port=port,actions=actions,data=data) dp.send_msg(out) else: return