def _handle_LinkEvent(self, event): l = event.link sw1 = switches[l.dpid1] sw2 = switches[l.dpid2] clear = of.ofp_flow_mod(command=of.OFPFC_DELETE) for sw in switches.itervalues(): if sw.connection is None: continue sw.connection.send(clear) if event.removed: if sw2 in adjacency[sw1]: del adjacency[sw1][sw2] if sw1 in adjacency[sw2]: del adjacency[sw2][sw1] for ll in core.openflow_discovery.adjacency: if ll.dpid1 == l.dpid1 and ll.dpid2 == l.dpid2: if Discovery.Link( ll[2], ll[3], ll[0], ll[1]) in core.openflow_discovery.adjacency: adjacency[sw1][sw2] = ll.port1 adjacency[sw2][sw1] = ll.port2 break else: if adjacency[sw1][sw2] is None: if Discovery.Link(l[2], l[3], l[0], l[1]) in core.openflow_discovery.adjacency: adjacency[sw1][sw2] = l.port1 adjacency[sw2][sw1] = l.port2 bad_macs = set() for mac, (sw, port) in mac_map.iteritems(): if (sw is sw1 and port == l.port1) or (sw is sw2 and port == l.port2): bad_macs.add(mac)
def flip(link): """ . :param link: Lista de links :return: Instância de objeto Link. """ return Discovery.Link(link[2], link[3], link[0], link[1])
def flip (link): return Discovery.Link(link[2], link[3],link[0],link[1])
def handle_lldp(self, packet, event): import pox.lib.packet as pkt from pox.openflow.discovery import Discovery, LinkEvent import time lldph = packet.find(pkt.lldp) if lldph is None or not lldph.parsed: return if len(lldph.tlvs) < 3: return if lldph.tlvs[0].tlv_type != pkt.lldp.CHASSIS_ID_TLV: return if lldph.tlvs[1].tlv_type != pkt.lldp.PORT_ID_TLV: return if lldph.tlvs[2].tlv_type != pkt.lldp.TTL_TLV: return def lookInSysDesc(): r = None for t in lldph.tlvs[3:]: if t.tlv_type == pkt.lldp.SYSTEM_DESC_TLV: # This is our favored way... for line in t.payload.split('\n'): if line.startswith('dpid:'): try: return int(line[5:], 16) except: pass if len(t.payload) == 8: # Maybe it's a FlowVisor LLDP... # Do these still exist? try: return struct.unpack("!Q", t.payload)[0] except: pass return None originatorDPID = lookInSysDesc() if originatorDPID == None: # We'll look in the CHASSIS ID if lldph.tlvs[0].subtype == pkt.chassis_id.SUB_LOCAL: if lldph.tlvs[0].id.startswith('dpid:'): # This is how NOX does it at the time of writing try: originatorDPID = int(lldph.tlvs[0].id[5:], 16) except: pass if originatorDPID == None: if lldph.tlvs[0].subtype == pkt.chassis_id.SUB_MAC: # Last ditch effort -- we'll hope the DPID was small enough # to fit into an ethernet address if len(lldph.tlvs[0].id) == 6: try: s = lldph.tlvs[0].id originatorDPID = struct.unpack( "!Q", '\x00\x00' + s)[0] except: pass if originatorDPID == None: return if originatorDPID not in core.openflow.connections: return # Get port number from port TLV if lldph.tlvs[1].subtype != pkt.port_id.SUB_PORT: return originatorPort = None if lldph.tlvs[1].id.isdigit(): # We expect it to be a decimal value originatorPort = int(lldph.tlvs[1].id) elif len(lldph.tlvs[1].id) == 2: # Maybe it's a 16 bit port number... try: originatorPort = struct.unpack("!H", lldph.tlvs[1].id)[0] except: pass if originatorPort is None: return if (event.dpid, event.port) == (originatorDPID, originatorPort): return link = Discovery.Link(originatorDPID, originatorPort, event.dpid, event.port) if link not in self.adjacency: self.adjacency[link] = time.time() self.raiseEventNoErrors(LinkEvent, True, link) else: # Just update timestamp self.adjacency[link] = time.time() self.send_to_pyretic( ['link', originatorDPID, originatorPort, event.dpid, event.port]) return # Probably nobody else needs this event
def flip (link): return Discovery.Link(link[2],link[3], link[0],link[1]) l = event.link sw1 = switches[l.dpid1] sw2 = switches[l.dpid2] # Invalidate all flows and path info. # For link adds, this makes sure that if a new link leads to an # improved path, we use it. # For link removals, this makes sure that we don't use a # path that may have been broken. #NOTE: This could be radically improved! (e.g., not *ALL* paths break) clear = of.ofp_flow_mod(command=of.OFPFC_DELETE) for sw in switches.itervalues(): if sw.connection is None: continue sw.connection.send(clear) path_map.clear() if event.removed: # This link no longer okay if sw2 in adjacency[sw1]: del adjacency[sw1][sw2] if sw1 in adjacency[sw2]: del adjacency[sw2][sw1] # But maybe there's another way to connect these... for ll in core.openflow_discovery.adjacency: if ll.dpid1 == l.dpid1 and ll.dpid2 == l.dpid2: if flip(ll) in core.openflow_discovery.adjacency: # Yup, link goes both ways adjacency[sw1][sw2] = ll.port1 adjacency[sw2][sw1] = ll.port2 # Fixed -- new link chosen to connect these break else: # If we already consider these nodes connected, we can # ignore this link up. # Otherwise, we might be interested... if adjacency[sw1][sw2] is None: # These previously weren't connected. If the link # exists in both directions, we consider them connected now. if flip(l) in core.openflow_discovery.adjacency: # Yup, link goes both ways -- connected! adjacency[sw1][sw2] = l.port1 adjacency[sw2][sw1] = l.port2 # If we have learned a MAC on this port which we now know to # be connected to a switch, unlearn it. bad_macs = set() for mac,(sw,port) in mac_map.iteritems(): #print sw,sw1,port,l.port1 if sw is sw1 and port == l.port1: if mac not in bad_macs: log.debug("Unlearned %s", mac) bad_macs.add(mac) if sw is sw2 and port == l.port2: if mac not in bad_macs: log.debug("Unlearned %s", mac) bad_macs.add(mac) for mac in bad_macs: del mac_map[mac] def _handle_ConnectionUp (self, event): sw = switches.get(event.dpid) if sw is None: # New switch sw = Switch() switches[event.dpid] = sw sw.connect(event.connection) else: sw.connect(event.connection) def _handle_BarrierIn (self, event): wp = waiting_paths.pop((event.dpid,event.xid), None) if not wp: #log.info("No waiting packet %s,%s", event.dpid, event.xid) return #log.debug("Notify waiting packet %s,%s", event.dpid,event.xid) wp.notify(event) def launch (): core.registerNew(l2_multi) core.registerNew(Cleanswitch) core.Cleanswitch._do_sleep() timeout = min(max(PATH_SETUP_TIME, 5) * 2, 15) Timer(timeout, WaitingPath.expire_waiting_paths, recurring=True) print "will go to execute the timer for sent_sw" #we will call the cleaning_sent_sw function in the switch class to erase the list of the switches that have been already polled for statistics. As long as the switches are in the sent_sw list no statistics request will be sent to them. Timer(10, Switch.cleaning_sent_sw, recurring=True) core.openflow.addListenerByName("FlowStatsReceived", Switch()._handle_flowstats_received)