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): 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): """ 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): """ 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 main(): iface = get_if() print("iface: ", iface) pkt = LLDPPacket.lldp_packet(1, 0, get_if_hwaddr(iface), 10) p = Ether(_pkt=pkt) sendp(pkt, iface=iface, verbose=False)
def lldp_parse_new(data): pkt = packet.Packet(data) i = iter(pkt) eth_pkt = six.next(i) assert type(eth_pkt) == ethernet.ethernet lldp_pkt = six.next(i) if type(lldp_pkt) != lldp.lldp: raise LLDPPacket.LLDPUnknownFormat() return lldp_pkt
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 _execute_lldp(self, s, callback): time.sleep(s) for switch in self.networkMap.getAllSwitches(): parser = switch.dp.ofproto_parser ofproto = switch.dp.ofproto for port in self.networkMap.getAllSwitchPorts(switch): pkt = LLDPPacket.lldp_packet(switch.dp.id, 1, port.hw_addr, 1) actions = [parser.OFPActionOutput(port=port.port_no)] callback(switch.dp, actions, pkt, ofproto.OFPP_CONTROLLER) self.networkMap.report() self._execute_lldp(s, callback)
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 send_lldp_packet(self, datapath_id, port_no, dl_addr): datapath = self.dps.get(datapath_id, None) if datapath is None: #datapath was already deleted return ofproto = datapath.ofproto parser = datapath.ofproto_parser lldp_data = LLDPPacket.lldp_packet(datapath.id, port_no, dl_addr, self.DEFAULT_TTL) output_port = parser.OFPActionOutput(port_no, ofproto.OFPCML_NO_BUFFER) packet_out = parser.OFPPacketOut(datapath, ofproto.OFPP_ANY, ofproto.OFPP_CONTROLLER, [output_port], lldp_data) datapath.send_msg(packet_out)
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 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_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 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])
class L2Switch(RyuApp): _EVENTS = [ event.EventSwitchEnter, event.EventSwitchLeave, event.EventPortAdd, event.EventPortDelete, event.EventPortModify, event.EventLinkAdd, event.EventLinkDelete, event.EventArpReceived ] OFP_VERSIONS = [OFP_VERSION] DEFAULT_TTL = 120 # unused. ignored. LLDP_PACKET_LEN = len(LLDPPacket.lldp_packet(0, 0, DONTCARE_STR, 0)) LLDP_SEND_GUARD = .05 LLDP_SEND_PERIOD_PER_PORT = .9 TIMEOUT_CHECK_PERIOD = 15. LINK_TIMEOUT = TIMEOUT_CHECK_PERIOD * 2 LINK_LLDP_DROP = 5 def __init__(self, *args, **kwargs): super(L2Switch, self).__init__(*args, **kwargs) self.name = 'switches' self.dps = {} # datapath_id => Datapath class self.port_state = {} # datapath_id => ports self.ports = PortDataState() # Port class -> PortData class self.links = LinkState() # Link class -> timestamp self.is_active = True self.lldp_event = hub.Event() self.link_event = hub.Event() self.threads.append(hub.spawn(self.lldp_loop)) self.threads.append(hub.spawn(self.link_loop)) self.link_discovery = True def close(self): self.is_active = False if self.link_discovery: self.lldp_event.set() self.link_event.set() hub.joinall(self.threads) def lldp_loop(self): while self.is_active: self.lldp_event.clear() now = time.time() timeout = None ports_now = [] ports = [] for (key, data) in self.ports.items(): if data.timestamp is None: ports_now.append(key) continue expire = data.timestamp + self.LLDP_SEND_PERIOD_PER_PORT if expire <= now: ports.append(key) continue timeout = expire - now break for port in ports_now: self.send_lldp_packet(port.dpid, port.port_no, port.hw_addr) for port in ports: self.send_lldp_packet(port.dpid, port.port_no, port.hw_addr) hub.sleep(self.LLDP_SEND_GUARD) # don't burst if timeout is not None and ports: timeout = 0 # We have already slept self.lldp_event.wait(timeout=timeout) def link_loop(self): while self.is_active: self.link_event.clear() now = time.time() deleted = [] for (link, timestamp) in self.links.items(): if timestamp + self.LINK_TIMEOUT < now: src = link.src if src in self.ports: port_data = self.ports.get_port(src) if port_data.lldp_dropped() > self.LINK_LLDP_DROP: deleted.append(link) for link in deleted: self.links.link_down(link) self.send_event_to_observers(event.EventLinkDelete(link)) dst = link.dst rev_link = Link(dst, link.src) if rev_link not in deleted: # It is very likely that the reverse link is also # disconnected. Check it early. expire = now - self.LINK_TIMEOUT self.links.rev_link_set_timestamp(rev_link, expire) if dst in self.ports: self.ports.move_front(dst) self.lldp_event.set() self.link_event.wait(timeout=self.TIMEOUT_CHECK_PERIOD) def _get_switch(self, dpid): if dpid in self.dps: switch = Switch(self.dps[dpid]) for ofpport in self.port_state[dpid].itervalues(): switch.add_port(ofpport) return switch def _get_port(self, dpid, port_no): switch = self._get_switch(dpid) if switch: for p in switch.ports: if p.port_no == port_no: return p def _port_added(self, port): lldp_data = LLDPPacket.lldp_packet(port.dpid, port.port_no, port.hw_addr, self.DEFAULT_TTL) self.ports.add_port(port, lldp_data) LOG.debug('_port_added dpid=%s, port_no=%s, live=%s', port.dpid, port.port_no, port.is_live()) def _register(self, dp): assert dp.id is not None assert dp.id not in self.dps self.dps[dp.id] = dp self.port_state[dp.id] = PortState() for port in dp.ports.values(): self.port_state[dp.id].add(port.port_no, port) def _link_down(self, port): try: dst, rev_link_dst = self.links.port_deleted(port) except KeyError: # LOG.debug('key error. src=%s, dst=%s', # port, self.links.get_peer(port)) return link = Link(port, dst) self.send_event_to_observers(event.EventLinkDelete(link)) if rev_link_dst: rev_link = Link(dst, rev_link_dst) self.send_event_to_observers(event.EventLinkDelete(rev_link)) self.ports.move_front(dst) @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER) def port_status_handler(self, ev): msg = ev.msg reason = msg.reason dp = msg.datapath ofpport = msg.desc if reason == dp.ofproto.OFPPR_ADD: LOG.debug( 'A port was added.' + '(datapath id = %s, port number = %s)', dp.id, ofpport.port_no) self.port_state[dp.id].add(ofpport.port_no, ofpport) self.send_event_to_observers( event.EventPortAdd(Port(dp.id, dp.ofproto, ofpport))) if not self.link_discovery: return port = self._get_port(dp.id, ofpport.port_no) if port and not port.is_reserved(): self._port_added(port) self.lldp_event.set() elif reason == dp.ofproto.OFPPR_DELETE: LOG.debug( 'A port was deleted.' + '(datapath id = %s, port number = %s)', dp.id, ofpport.port_no) self.port_state[dp.id].remove(ofpport.port_no) self.send_event_to_observers( event.EventPortDelete(Port(dp.id, dp.ofproto, ofpport))) if not self.link_discovery: return port = self._get_port(dp.id, ofpport.port_no) if port and not port.is_reserved(): self.ports.del_port(port) self._link_down(port) self.lldp_event.set() else: assert reason == dp.ofproto.OFPPR_MODIFY LOG.debug( 'A port was modified.' + '(datapath id = %s, port number = %s)', dp.id, ofpport.port_no) self.port_state[dp.id].modify(ofpport.port_no, ofpport) self.send_event_to_observers( event.EventPortModify(Port(dp.id, dp.ofproto, ofpport))) if not self.link_discovery: return port = self._get_port(dp.id, ofpport.port_no) if port and not port.is_reserved(): if self.ports.set_down(port): self._link_down(port) self.lldp_event.set() @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER) def switch_features_handler(self, ev): """Handle switch features reply to install table miss flow entries.""" datapath = ev.msg.datapath self.install_table_miss(datapath, 0) def create_match(self, parser, fields): """Create OFP match struct from the list of fields.""" match = parser.OFPMatch() for a in fields: match.append_field(*a) return match def send_barrier_request(self, datapath): ofp_parser = datapath.ofproto_parser req = ofp_parser.OFPBarrierRequest(datapath) datapath.send_msg(req) def send_lldp_packet(self, datapath_id, port_no, dl_addr): datapath = self.dps.get(datapath_id, None) if datapath is None: #datapath was already deleted return ofproto = datapath.ofproto parser = datapath.ofproto_parser lldp_data = LLDPPacket.lldp_packet(datapath.id, port_no, dl_addr, self.DEFAULT_TTL) output_port = parser.OFPActionOutput(port_no, ofproto.OFPCML_NO_BUFFER) packet_out = parser.OFPPacketOut(datapath, ofproto.OFPP_ANY, ofproto.OFPP_CONTROLLER, [output_port], lldp_data) datapath.send_msg(packet_out) @set_ev_cls(ofp_event.EventOFPBarrierReply, MAIN_DISPATCHER) def barrier_reply_handler(self, ev): msg = ev.msg datapath = msg.datapath self._register(datapath) switch = self._get_switch(datapath.id) self.send_event_to_observers(event.EventSwitchEnter(switch)) for port in switch.ports: if not port.is_reserved(): self._port_added(port) self.lldp_event.set() def create_flow_mod(self, datapath, priority, table_id, match, instructions): """Create OFP flow mod message.""" ofproto = datapath.ofproto flow_mod = datapath.ofproto_parser.OFPFlowMod( datapath, 0, 0, table_id, ofproto.OFPFC_ADD, 0, 0, priority, ofproto.OFPCML_NO_BUFFER, ofproto.OFPP_ANY, OFPG_ANY, 0, match, instructions) return flow_mod def install_table_miss(self, datapath, table_id): """Create and install table miss flow entries.""" parser = datapath.ofproto_parser ofproto = datapath.ofproto match = parser.OFPMatch() match.set_dl_type(ETH_TYPE_LLDP) output = parser.OFPActionOutput(ofproto.OFPP_CONTROLLER, self.LLDP_PACKET_LEN) write = parser.OFPInstructionActions(ofproto.OFPIT_WRITE_ACTIONS, [output]) instructions = [write] flow_mod = self.create_flow_mod(datapath, 0, table_id, match, instructions) datapath.send_msg(flow_mod) self.send_barrier_request(datapath) @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER) def _packet_in_handler(self, ev): """Handle packet_in events.""" if not self.link_discovery: return msg = ev.msg in_port = msg.match['in_port'] packet = Packet(msg.data) efm = packet.get_protocol(ethernet.ethernet) if efm.ethertype == ether.ETH_TYPE_ARP: self.send_event_to_observers(event.EventArpReceived(ev)) try: src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data) except LLDPPacket.LLDPUnknownFormat as e: # This handler can receive all the packtes which can be # not-LLDP packet. Ignore it silently return else: dst_dpid = msg.datapath.id dst_port_no = in_port src = self._get_port(src_dpid, src_port_no) if not src or src.dpid == dst_dpid: return dst = self._get_port(dst_dpid, dst_port_no) if not dst: return old_peer = self.links.get_peer(src) #LOG.debug("Packet-In") #LOG.debug(" src=%s", src) #LOG.debug(" dst=%s", dst) #LOG.debug(" old_peer=%s", old_peer) if old_peer and old_peer != dst: old_link = Link(src, old_peer) self.send_event_to_observers(event.EventLinkDelete(old_link)) link = Link(src, dst) if not link in self.links: self.send_event_to_observers(event.EventLinkAdd(link)) if not self.links.update_link(src, dst): # reverse link is not detected yet. # So schedule the check early because it's very likely it's up try: self.ports.lldp_received(dst) except KeyError as e: # There are races between EventOFPPacketIn and # EventDPPortAdd. So packet-in event can happend before # port add event. In that case key error can happend. # LOG.debug('lldp_received: KeyError %s', e) pass else: self.ports.move_front(dst) self.lldp_event.set()
def _port_added(self, port): lldp_data = LLDPPacket.lldp_packet( port.dpid, port.port_no, port.hw_addr, self.DEFAULT_TTL) self.ports.add_port(port, lldp_data) LOG.debug('_port_added dpid=%s, port_no=%s, live=%s', port.dpid, port.port_no, port.is_live())
def _port_added(self, port): lldp_data = LLDPPacket.lldp_packet(port.dpid, port.port_no, port.hw_addr, self.DEFAULT_TTL) self.ports.add_port(port, lldp_data) LOG.debug('_port_added dpid=%s, port_no=%s, live=%s', port.dpid, port.port_no, port.is_live())
class Topology(LocalService): _EVENTS = {EventPortAdd, EventPortDelete, EventPortModify, EventLinkAdd, EventLinkDelete} """ Ryu topology module ported to Local Controller """ DEFAULT_TTL = 64 LLDP_PACKET_LEN = len(LLDPPacket.lldp_packet(0, 0, DONTCARE_STR, 0)) LLDP_SEND_GUARD = .05 LLDP_SEND_PERIOD_PER_PORT = .9 TIMEOUT_CHECK_PERIOD = 5. LINK_TIMEOUT = TIMEOUT_CHECK_PERIOD * 2 LINK_LLDP_DROP = 5 LLDP_PRIORITY = 0xFFFF def __init__(self, *args, **kwargs): super(Topology, self).__init__(*args, **kwargs) self.is_active = True self.explicit_drop = True self.ports = PortDataState() self.links = _LinkState() self.lldp_event = hub.Event() self.link_event = hub.Event() self.threads.append(hub.spawn(self.lldp_loop)) self.threads.append(hub.spawn(self.link_loop)) def _port_added(self, port): lldp_data = LLDPPacket.lldp_packet( port.dpid, port.port_no, port.hw_addr, self.DEFAULT_TTL) self.ports.add_port(port, lldp_data) def _switch_enter(self, dp): super(Topology, self)._switch_enter(dp) self._init_flows() ports = [Port(PortData(dp.id, port, dp.ofproto)) for port in dp.ports.values()] for port in ports: if not port.is_reserved(): self._port_added(port) self.ryuo.switch_enter(dp.id, [port.port_data for port in self.ports.keys()]) self.lldp_event.set() def _init_flows(self): self._logger.info('Init flow table.') self.ofctl.set_packet_in_flow(cookie=0, priority=self.LLDP_PRIORITY, eth_type=ETH_TYPE_LLDP, eth_dst=lldp.LLDP_MAC_NEAREST_BRIDGE) def _switch_leave(self): super(Topology, self)._switch_leave() self.links.clear() self.ports.clear() def _get_port(self, port_no): for port in self.ports.keys(): if port.port_no == port_no: return port def _report_port_added(self, port): self.send_event_to_observers(EventPortAdd(port)) self.ryuo.port_added(port.port_data) def _report_port_deleted(self, port): self.send_event_to_observers(EventPortDelete(port)) self.ryuo.port_deleted(port.port_data) def _report_port_modified(self, port): self.send_event_to_observers(EventPortModify(port)) self.ryuo.port_modified(port.port_data) @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER) def _port_status_change(self, ev): if self.dp is None: return msg = ev.msg reason = msg.reason dp = msg.datapath ofpport = msg.desc ofp = dp.ofproto if reason == ofp.OFPPR_ADD: self._logger.info('Port %d added.', ofpport.port_no) port = Port(PortData(self.dp.id, ofpport, ofp)) if not port.is_reserved(): self._port_added(port) self._report_port_added(port) self.lldp_event.set() elif reason == ofp.OFPPR_DELETE: self._logger.info('Port %d deleted.', ofpport.port_no) port = self._get_port(ofpport.port_no) if port and not port.is_reserved(): del self.ports[Port(PortData(self.dp.id, ofpport))] self._report_port_deleted(port) self._link_down(port) self.lldp_event.set() else: self._logger.info('Port %d modified.', ofpport.port_no) port = self._get_port(ofpport.port_no) port.lldp_reply = False if port and not port.is_reserved(): port.modify(ofpport) self._report_port_modified(port) if self.ports.set_down(port): self._link_down(port) self.lldp_event.set() def send_lldp_packet(self, port): try: port_data = self.ports.lldp_sent(port) except KeyError as e: # ports can be modified during our sleep in self.lldp_loop() self._logger.warning('Missing port %d, %s.', port.port_no, e) return if port_data.is_down: return dp = self.dp if dp is None: # datapath was already deleted self._logger.warning('Switch left.') return self.ofctl.send_packet_out(in_port=dp.ofproto.OFPP_CONTROLLER, output=port.port_no, data=port_data.lldp_data) def lldp_loop(self): while self.is_active: self._logger.debug('LLDP loop') self.lldp_event.clear() now = time.time() timeout = None ports_now = [] ports = [] for (key, data) in self.ports.items(): if data.timestamp is None: ports_now.append(key) continue expire = data.timestamp + self.LLDP_SEND_PERIOD_PER_PORT if expire <= now: ports.append(key) continue if timeout is None or timeout > expire - now: timeout = expire - now # break for port in ports_now: self.send_lldp_packet(port) self._logger.debug('Sending LLDP to %d.%d', port.dpid, port.port_no) for port in ports: self.send_lldp_packet(port) self._logger.debug('Sending LLDP to %d.%d', port.dpid, port.port_no) hub.sleep(self.LLDP_SEND_GUARD) # don't burst if timeout is not None and ports: timeout = 0 # We have already slept # LOG.debug('lldp sleep %s', timeout) self.lldp_event.wait(timeout=timeout) def _report_link_deleted(self, link): self.send_event_to_observers(EventLinkDelete(link)) self.ryuo.link_deleted(link.src.port_data, link.dst.port_data) def _report_link_added(self, link): self.send_event_to_observers(EventLinkAdd(link)) self.ryuo.link_added(link.src.port_data, link.dst.port_data) @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER) def packet_in_handler(self, ev): self._logger.debug('Packet in') msg = ev.msg ofp = msg.datapath.ofproto pkt = packet.Packet(msg.data) headers = dict((p.protocol_name, p) for p in pkt.protocols if type(p) != str) src_mac = headers[ETHERNET].src try: src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data) except LLDPPacket.LLDPUnknownFormat as e: self._logger.debug('LLDPUnknownFormat %s', e) return dst_port_no = self.ofctl.get_packet_in_inport(msg) dst = self._get_port(dst_port_no) self._logger.debug('LLDP from %d.%d -> %d', src_dpid, src_port_no, dst_port_no) if not dst: self._logger.warning('Dst not found.') return self.ports.lldp_received(dst) src = Port(PortData(src_dpid, port_no=src_port_no, hw_addr=src_mac)) old_peer = self.links.get_peer(dst) need_update = False if old_peer and old_peer != src: self._logger.info('Peer changed.') self._report_link_deleted(Link(old_peer, dst)) need_update = True link = Link(src, dst) if link not in self.links: need_update = True self._report_link_added(Link(src, dst)) self.lldp_event.set() # Always return false, since we don't have the reverse link information if need_update: self.links.update_link(src, dst) self._logger.info('Update link %d.%d -> %d.%d', src.dpid, src.port_no, dst.dpid, dst.port_no) def link_loop(self): while self.is_active: self.link_event.clear() now = time.time() deleted = [] for (link, timestamp) in self.links.items(): # LOG.debug('%s timestamp %d (now %d)', link, timestamp, now) if timestamp + self.LINK_TIMEOUT < now: src = link.src if src in self.ports: port_data = self.ports.get_port(src) # LOG.debug('port_data %s', port_data) if port_data.lldp_dropped() > self.LINK_LLDP_DROP: deleted.append(link) for link in deleted: self.links.link_down(link) # LOG.debug('delete %s', link) self._report_link_deleted(link) self.link_event.wait(timeout=self.TIMEOUT_CHECK_PERIOD) def _link_down(self, port): try: src, rev_link_dst = self.links.dst_port_deleted(port) self._logger.info('Link down: %d.%d -> %d.%d', src.dpid, src.port_no, port.dpid, port.port_no) except KeyError: self._logger.info('Cannot find peer of %d.%d', port.dpid, port.port_no) return self._report_link_deleted(Link(src, port)) def close(self): self.is_active = False self.lldp_event.set() self.link_event.set() super(Topology, self).close()
def _port_added(self, port): lldp_data = LLDPPacket.lldp_packet( port.dpid, port.port_no, port.hw_addr, self.DEFAULT_TTL) self.ports.add_port(port, lldp_data)
def 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): 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