def launch(): """ core is able to register all the pox components core.openflow is the pox openflow component _handle_ConnectionUp subscribe to core.openflow's ConnectionUp event each Timer instance add a non-default parameter to show Timer capabilities. """ TIME_TO_WAKE = 2 args = ["ciao", "mare"] core.callDelayed(TIME_TO_WAKE, timeout_handler, args) t = Timer( TIME_TO_WAKE, timeout_handler, args='t1') t2 = Timer( TIME_TO_WAKE, timeout_handler, absoluteTime=True, # use False args='t2') tr = Timer( TIME_TO_WAKE, timeout_handler, absoluteTime=False, recurring=True, # recur infinitely overtime args='tr') tw = Timer( TIME_TO_WAKE, timeout_handler, absoluteTime=False, recurring=False, started=False, # not start automatically args='tw') time.sleep(TIME_TO_WAKE) tw.start() tk = Timer( TIME_TO_WAKE, timeout_handler_kill, # handler able to cancel the timer absoluteTime=False, recurring=True, started=False, selfStoppable=False, # timer can be cancelled by the handler args='tw')
def update(self): # let the controller start update the configuration log.warning("Updating Starts.") self.update_step = 0 self.config.read_config( INPUT_CONFIG_FILENAME ) # Initial update self.update_timer = Timer(self.config.next_time, self._update_step, started = False, recurring = True) self._update_step() self.update_timer.start()
def GetTopologyParams(): Timer(10, find_latency1, recurring = True) timeout = min(max(PATH_SETUP_TIME, 5) * 2, 15) Timer(timeout, WaitingPath.expire_waiting_paths, recurring=True) Timer(15, find_HostPorts, recurring = False)
def iniciarTimer(self): Timer(10, self.getflowstats, recurring=True)
def _handle_openflow_PacketIn (self, event): dpid = event.connection.dpid inport = event.port packet = event.parsed global set_Timer global defendDDOS global blockPort timerSet =False global diction def preventing(): global diction global set_Timer if not set_Timer: set_Timer =True #Timer(1, _timer_func(), recurring=True) #print"\n\n*********new packetIN************" if len(diction) == 0: print("Enpty diction ",str(event.connection.dpid), str(event.port)) diction[event.connection.dpid] = {} diction[event.connection.dpid][event.port] = 1 elif event.connection.dpid not in diction: diction[event.connection.dpid] = {} diction[event.connection.dpid][event.port] = 1 #print "ERROR" else: if event.connection.dpid in diction: # temp = diction[event.connection.dpid] #print(temp) #print "error check " , str(diction[event.connection.dpid][event.port]) if event.port in diction[event.connection.dpid]: temp_count=0 temp_count =diction[event.connection.dpid][event.port] temp_count = temp_count+1 diction[event.connection.dpid][event.port]=temp_count #print "printting dpid port number and its packet count: ", str(event.connection.dpid), str(diction[event.connection.dpid]), str(diction[event.connection.dpid][event.port]) else: diction[event.connection.dpid][event.port] = 1 print "\n",datetime.datetime.now(), ": printing diction ",str(diction),"\n" def _timer_func (): global diction global set_Timer if set_Timer==True: #print datetime.datetime.now(),": calling timer fucntion now!!!!!" for k,v in diction.iteritems(): for i,j in v.iteritems(): if j >=50: print "_____________________________________________________________________________________________" print "\n",datetime.datetime.now(),"******* DDOS DETECTED ********" print "\n",str(diction) print "\n",datetime.datetime.now(),": BLOCKED PORT NUMBER : ", str(i), " OF SWITCH ID: ", str(k) print "\n_____________________________________________________________________________________________" #self.dropDDOS () dpid = k msg = of.ofp_packet_out(in_port=i) #msg.priority=42 #msg.in_port = event.port #po = of.ofp_packet_out(buffer_id = buffer_id, in_port = in_port) core.openflow.sendToDPID(dpid,msg) diction={} if not packet.parsed: log.warning("%i %i ignoring unparsed packet", dpid, inport) return if dpid not in self.arpTable: # New switch -- create an empty table self.arpTable[dpid] = {} for fake in self.fakeways: self.arpTable[dpid][IPAddr(fake)] = Entry(of.OFPP_NONE, dpid_to_mac(dpid)) if packet.type == ethernet.LLDP_TYPE: # Ignore LLDP packets return #-------------------------------------------editing-------------------------------------------------- if isinstance(packet.next, ipv4): log.debug("%i %i IP %s => %s", dpid,inport, packet.next.srcip,packet.next.dstip) ent_obj.statcolect(event.parsed.next.dstip) print "\n***** Entropy Value = ",str(ent_obj.value),"*****\n" if ent_obj.value <0.5: preventing() if timerSet is not True: Timer(2, _timer_func, recurring=True) timerSet=False else: timerSet=False # Send any waiting packets... self._send_lost_buffers(dpid, packet.next.srcip, packet.src, inport) # Learn or update port/MAC info if packet.next.srcip in self.arpTable[dpid]: if self.arpTable[dpid][packet.next.srcip] != (inport, packet.src): log.info("%i %i RE-learned %s", dpid,inport,packet.next.srcip) if self.wide: # Make sure we don't have any entries with the old info... msg = of.ofp_flow_mod(command=of.OFPFC_DELETE) msg.match.nw_dst = packet.next.srcip msg.match.dl_type = ethernet.IP_TYPE event.connection.send(msg) else: log.debug("%i %i learned %s", dpid,inport,packet.next.srcip) self.arpTable[dpid][packet.next.srcip] = Entry(inport, packet.src) #nandan: getting source ip address from the packetIn #myPacketInSrcIP= packet.next.srcip #myPacketInSrcEth= packet.src #myPacketInDstIP= packet.next.dstip #myPacketInDstEth= packet.dst #print "switcID: "+str(dpid)+" ,Port: "+str(event.port)+" ,MAC address: "+str(myPacketInSrcEth)+" ,SrcIP: "+ str(myPacketInSrcIP)+", Dst Mac: "+str(myPacketInDstEth)+", Dst IP: "+str(myPacketInDstEth) # Try to forward dstaddr = packet.next.dstip if dstaddr in self.arpTable[dpid]: # We have info about what port to send it out on... prt = self.arpTable[dpid][dstaddr].port mac = self.arpTable[dpid][dstaddr].mac if prt == inport: log.warning("%i %i not sending packet for %s back out of the " "input port" % (dpid, inport, dstaddr)) else: log.debug("%i %i installing flow for %s => %s out port %i" % (dpid, inport, packet.next.srcip, dstaddr, prt)) actions = [] actions.append(of.ofp_action_dl_addr.set_dst(mac)) actions.append(of.ofp_action_output(port = prt)) if self.wide: match = of.ofp_match(dl_type = packet.type, nw_dst = dstaddr) else: match = of.ofp_match.from_packet(packet, inport) msg = of.ofp_flow_mod(command=of.OFPFC_ADD, idle_timeout=FLOW_IDLE_TIMEOUT, hard_timeout=of.OFP_FLOW_PERMANENT, buffer_id=event.ofp.buffer_id, actions=actions, match=match) event.connection.send(msg.pack()) elif self.arp_for_unknowns: # We don't know this destination. # First, we track this buffer so that we can try to resend it later # if we learn the destination, second we ARP for the destination, # which should ultimately result in it responding and us learning # where it is # Add to tracked buffers if (dpid,dstaddr) not in self.lost_buffers: self.lost_buffers[(dpid,dstaddr)] = [] bucket = self.lost_buffers[(dpid,dstaddr)] entry = (time.time() + MAX_BUFFER_TIME,event.ofp.buffer_id,inport) bucket.append(entry) while len(bucket) > MAX_BUFFERED_PER_IP: del bucket[0] # Expire things from our outstanding ARP list... self.outstanding_arps = {k:v for k,v in self.outstanding_arps.iteritems() if v > time.time()} # Check if we've already ARPed recently if (dpid,dstaddr) in self.outstanding_arps: # Oop, we've already done this one recently. return # And ARP... self.outstanding_arps[(dpid,dstaddr)] = time.time() + 4 r = arp() r.hwtype = r.HW_TYPE_ETHERNET r.prototype = r.PROTO_TYPE_IP r.hwlen = 6 r.protolen = r.protolen r.opcode = r.REQUEST r.hwdst = ETHER_BROADCAST r.protodst = dstaddr r.hwsrc = packet.src r.protosrc = packet.next.srcip e = ethernet(type=ethernet.ARP_TYPE, src=packet.src, dst=ETHER_BROADCAST) e.set_payload(r) log.debug("%i %i ARPing for %s on behalf of %s" % (dpid, inport, r.protodst, r.protosrc)) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD)) msg.in_port = inport event.connection.send(msg) elif isinstance(packet.next, arp): a = packet.next log.debug("%i %i ARP %s %s => %s", dpid, inport, {arp.REQUEST:"request",arp.REPLY:"reply"}.get(a.opcode, 'op:%i' % (a.opcode,)), a.protosrc, a.protodst) if a.prototype == arp.PROTO_TYPE_IP: if a.hwtype == arp.HW_TYPE_ETHERNET: if a.protosrc != 0: # Learn or update port/MAC info if a.protosrc in self.arpTable[dpid]: if self.arpTable[dpid][a.protosrc] != (inport, packet.src): log.info("%i %i RE-learned %s", dpid,inport,a.protosrc) if self.wide: # Make sure we don't have any entries with the old info... msg = of.ofp_flow_mod(command=of.OFPFC_DELETE) msg.match.dl_type = ethernet.IP_TYPE msg.match.nw_dst = a.protosrc event.connection.send(msg) else: log.debug("%i %i learned %s", dpid,inport,a.protosrc) self.arpTable[dpid][a.protosrc] = Entry(inport, packet.src) # Send any waiting packets... self._send_lost_buffers(dpid, a.protosrc, packet.src, inport) if a.opcode == arp.REQUEST: # Maybe we can answer if a.protodst in self.arpTable[dpid]: # We have an answer... if not self.arpTable[dpid][a.protodst].isExpired(): # .. and it's relatively current, so we'll reply ourselves r = arp() r.hwtype = a.hwtype r.prototype = a.prototype r.hwlen = a.hwlen r.protolen = a.protolen r.opcode = arp.REPLY r.hwdst = a.hwsrc r.protodst = a.protosrc r.protosrc = a.protodst r.hwsrc = self.arpTable[dpid][a.protodst].mac e = ethernet(type=packet.type, src=dpid_to_mac(dpid), dst=a.hwsrc) e.set_payload(r) log.debug("%i %i answering ARP for %s" % (dpid, inport, r.protosrc)) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.in_port = inport event.connection.send(msg) return # Didn't know how to answer or otherwise handle this ARP, so just flood it log.debug("%i %i flooding ARP %s %s => %s" % (dpid, inport, {arp.REQUEST:"request",arp.REPLY:"reply"}.get(a.opcode, 'op:%i' % (a.opcode,)), a.protosrc, a.protodst)) msg = of.ofp_packet_out(in_port = inport, data = event.ofp, action = of.ofp_action_output(port = of.OFPP_FLOOD)) event.connection.send(msg)
def __init__ (self): # This timer handles expiring stuff self._expire_timer = Timer(5, _handle_expiration, recurring=True) core.listen_to_dependencies(self) core.addListeners(self, priority = 2)
# JRF: Adding this for experimentation from pox.lib.recoco import Timer from pox.core import core import pox.openflow.libopenflow_01 as of from pox.lib.util import dpidToStr log = core.getLogger() def handle_timer_elapse(message): print "I was told to tell you:", message Timer(10, handle_timer_elapse, args=["Hello"]) def _handle_ConnectionUp(event): """ Be a proactive hub by telling every connected switch to flood all packets """ msg = of.ofp_flow_mod() msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD)) event.connection.send(msg) log.info("Hubifying %s", dpidToStr(event.dpid)) def _handle_PacketIn(event): """ Be a reactive hub by flooding every incoming packet
def _all_dependencies_met(self): self._startup("poxdesk_topo") # Periodically just send a topo self.timer = Timer(10, self.send_table, recurring=True) log.debug("Ready to rip.")
def launch(): core.registerNew(Multi_switches_load_balancing) core.openflow.addListenerByName("FlowStatsReceived", handle_flow_stats) Timer(0.5, handle_timer_elapse, recurring=True)
def _handle_PacketIn (self, event): dpid = event.connection.dpid inport = event.port packet = event.parsed #print "------------------------------------------------------------------------" #print "IPv4: ", event.parsed.find('ipv4') #print "ARP: ", event.parsed.find('arp') #print "Packet Type: " , packet.type #print datetime.datetime.now(), ":", packet #print "\n", packet.parsed #print "\n", event.ofp global call_Timer global set_Timer global diction timerSet =False def preventing(): global diction global set_Timer if not set_Timer: set_Timer =True if len(diction) == 0: diction[event.connection.dpid] = {} diction[event.connection.dpid][event.port] = 1 elif event.connection.dpid not in diction: diction[event.connection.dpid] = {} diction[event.connection.dpid][event.port] = 1 else: if event.connection.dpid in diction: if event.port in diction[event.connection.dpid]: temp_count=0 temp_count =diction[event.connection.dpid][event.port] temp_count = temp_count+1 diction[event.connection.dpid][event.port]=temp_count else: diction[event.connection.dpid][event.port] = 1 print "\n",datetime.datetime.now(), ": printing diction ",str(diction),"\n" def _timer_func (): global diction #print "Dictionary:", diction global set_Timer if not set_Timer: set_Timer =True if set_Timer==True: for k,v in diction.iteritems(): for i,j in v.iteritems(): if j >=20: print "\n",datetime.datetime.now(),"DDOS DETECTED" print "\n",str(diction) print "\n",datetime.datetime.now(),": BLOCKED PORT NUMBER : ", str(i), " OF SWITCH ID: ", str(k) #appending no actions to the out_msg the packets will be dropped from the current DPID-PORT pair dpid = k msg = of.ofp_packet_out(in_port=i) core.openflow.sendToDPID(dpid,msg) diction={} if not packet.parsed: log.warning("%i %i ignoring unparsed packet", dpid, inport) return if dpid not in self.arpTable: # New switch -- create an empty table self.arpTable[dpid] = {} for fake in self.fakeways: self.arpTable[dpid][IPAddr(fake)] = Entry(of.OFPP_NONE, dpid_to_mac(dpid)) #print "Arp table: ", str(self.arpTable) if packet.type == ethernet.LLDP_TYPE: # Ignore LLDP packets return if isinstance(packet.next, ipv4): log.debug("%i %i IP %s => %s", dpid,inport, packet.next.srcip,packet.next.dstip) #print "\n" chi_obj.stats(packet.next.srcip) #edit chi_obj.baseLine() #edit if chi_obj.y < 0.05 : print "DDoS might be there" preventing() Timer(10, _timer_func) # Send any waiting packets... self._send_lost_buffers(dpid, packet.next.srcip, packet.src, inport) #print "LOST BUFFERS: " , str(self.lost_buffers) #edited # Learn or update port/MAC info if packet.next.srcip in self.arpTable[dpid]: #print packet.next.srcip , "#editing" if self.arpTable[dpid][packet.next.srcip] != (inport, packet.src): log.info("%i %i RE-learned %s", dpid,inport,packet.next.srcip) else: log.debug("%i %i learned %s", dpid,inport,str(packet.next.srcip)) self.arpTable[dpid][packet.next.srcip] = Entry(inport, packet.src) #print "Arp table: ", str(self.arpTable) # Try to forward dstaddr = packet.next.dstip if dstaddr in self.arpTable[dpid]: # We have info about what port to send it out on... prt = self.arpTable[dpid][dstaddr].port mac = self.arpTable[dpid][dstaddr].mac if prt == inport: log.warning("%i %i not sending packet for %s back out of the " + "input port" % (dpid, inport, str(dstaddr))) else: log.debug("%i %i installing flow for %s => %s out port %i" % (dpid, inport, packet.next.srcip, dstaddr, prt)) actions = [] actions.append(of.ofp_action_dl_addr.set_dst(mac)) actions.append(of.ofp_action_output(port = prt)) match = of.ofp_match.from_packet(packet, inport) match.dl_src = None # Wildcard source MAC msg = of.ofp_flow_mod(command=of.OFPFC_ADD, idle_timeout=FLOW_IDLE_TIMEOUT, hard_timeout=of.OFP_FLOW_PERMANENT, buffer_id=event.ofp.buffer_id, actions=actions, match=of.ofp_match.from_packet(packet, inport)) event.connection.send(msg.pack()) elif self.arp_for_unknowns: # We don't know this destination. # First, we track this buffer so that we can try to resend it later # if we learn the destination, second we ARP for the destination, # which should ultimately result in it responding and us learning # where it is # Add to tracked buffers if (dpid,dstaddr) not in self.lost_buffers: self.lost_buffers[(dpid,dstaddr)] = [] bucket = self.lost_buffers[(dpid,dstaddr)] entry = (time.time() + MAX_BUFFER_TIME,event.ofp.buffer_id,inport) bucket.append(entry) while len(bucket) > MAX_BUFFERED_PER_IP: del bucket[0] # Expire things from our outstanding ARP list... self.outstanding_arps = {k:v for k,v in self.outstanding_arps.iteritems() if v > time.time()} # Check if we've already ARPed recently if (dpid,dstaddr) in self.outstanding_arps: # Oop, we've already done this one recently. return # And ARP... self.outstanding_arps[(dpid,dstaddr)] = time.time() + 4 r = arp() r.hwtype = r.HW_TYPE_ETHERNET r.prototype = r.PROTO_TYPE_IP r.hwlen = 6 r.protolen = r.protolen r.opcode = r.REQUEST r.hwdst = ETHER_BROADCAST r.protodst = dstaddr r.hwsrc = packet.src r.protosrc = packet.next.srcip e = ethernet(type=ethernet.ARP_TYPE, src=packet.src, dst=ETHER_BROADCAST) e.set_payload(r) log.debug("%i %i ARPing for %s on behalf of %s" % (dpid, inport, str(r.protodst), str(r.protosrc))) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD)) msg.in_port = inport event.connection.send(msg)
def __init__(self, timeout): self.debounce = {} self.timeout = int(timeout) core.listen_to_dependencies(self) Timer(self.timeout, self._handle_timer, recurring=True)
class MulticastPath(object): """Manages multicast route calculation and installation for a single pair of multicast group and multicast sender.""" def __init__(self, src_ip, src_router_dpid, ingress_port, dst_mcast_address, groupflow_manager, groupflow_trace_event = None): self.src_ip = src_ip self.ingress_port = ingress_port self.src_router_dpid = src_router_dpid self.dst_mcast_address = dst_mcast_address self.path_tree_map = defaultdict(lambda : None) # self.path_tree_map[router_dpid] = Complete path from receiver router_dpid to src self.weighted_topo_graph = [] self.node_list = [] # List of all managed router dpids self.installed_node_list = [] # List of all router dpids with rules currently installed self.receivers = [] # Tuples of (router_dpid, port) self.groupflow_manager = groupflow_manager self.flow_cookie = self.groupflow_manager.get_new_mcast_group_cookie() self.calc_path_tree_dijkstras(groupflow_trace_event) self._last_flow_replacement_time = None self._flow_replacement_timer = None def calc_path_tree_dijkstras(self, groupflow_trace_event = None): """Calculates a shortest path tree from the group sender to all network switches, and caches the resulting tree. Note that this function does not install any flow modifications.""" if not groupflow_trace_event is None: groupflow_trace_event.set_tree_calc_start_time(self.dst_mcast_address, self.src_ip) self._last_flow_replacement_time = time.time() self._calc_link_weights() nodes = set(self.node_list) edges = self.weighted_topo_graph graph = defaultdict(list) for src,dst,cost in edges: graph[src].append((cost, dst)) path_tree_map = defaultdict(lambda : None) queue, seen = [(0,self.src_router_dpid,())], set() while queue: (cost,node1,path) = heappop(queue) if node1 not in seen: seen.add(node1) path = (node1, path) path_tree_map[node1] = path for next_cost, node2 in graph.get(node1, ()): if node2 not in seen: new_path_cost = cost + next_cost heappush(queue, (new_path_cost, node2, path)) self.path_tree_map = path_tree_map log.debug('Calculated shortest path tree for source at router_dpid: ' + dpid_to_str(self.src_router_dpid)) for node in self.path_tree_map: log.debug('Path to Node ' + dpid_to_str(node) + ': ' + str(self.path_tree_map[node])) if not groupflow_trace_event is None: groupflow_trace_event.set_tree_calc_end_time() def _calc_link_weights(self): """Calculates link weights for all links in the network to be used by calc_path_tree_dijkstras(). The cost assigned to each link is based on the link's current utilization (as determined by the FlowTracker module), and the exact manner in which utilization is converted to a link wieght is determined by groupflow_manager.link_weight_type. Valid options are LINK_WEIGHT_LINEAR and LINK_WEIGHT_EXPONENTIAL. Both options include a static weight which is always assigned to all links (determined by groupflow_manager.static_link_weight), and a dynamic weight which is based on the current utilization (determined by groupflow_manager.utilization_link_weight). Setting groupflow_manager.utilization_link_weight to 0 will always results in shortest hop routing. """ curr_topo_graph = self.groupflow_manager.topology_graph self.node_list = list(self.groupflow_manager.node_set) weighted_topo_graph = [] current_util = core.openflow_flow_tracker.get_max_flow_utilization(self.flow_cookie) / core.openflow_flow_tracker.link_max_bw log.info('Current utilization of flow ' + str(self.flow_cookie) + ': ' + str(current_util * core.openflow_flow_tracker.link_max_bw) + ' Mbps') for edge in curr_topo_graph: output_port = self.groupflow_manager.adjacency[edge[0]][edge[1]] raw_link_util = core.openflow_flow_tracker.get_link_utilization_normalized(edge[0], output_port); link_util_mcast_flow = core.openflow_flow_tracker.get_flow_utilization_normalized(edge[0], output_port, self.flow_cookie) link_util = max(0, (raw_link_util * (1 - link_util_mcast_flow))) # link_util = raw_link_util # Uncommenting this line will cause flows to reroute around their own traffic, good for testing # Current utilization here is doubled as a simple attempt to handle variability in flow rates if link_util + (current_util * 2) > 1: link_util = 1 link_weight = 1 if self.groupflow_manager.util_link_weight == 0: link_weight = self.groupflow_manager.static_link_weight else: if self.groupflow_manager.link_weight_type == LINK_WEIGHT_LINEAR: if link_util >= 1: link_weight = sys.float_info.max / core.openflow_flow_tracker.get_num_tracked_links() else: link_weight = min(self.groupflow_manager.static_link_weight + (self.groupflow_manager.util_link_weight * link_util), sys.float_info.max / core.openflow_flow_tracker.get_num_tracked_links()) elif self.groupflow_manager.link_weight_type == LINK_WEIGHT_EXPONENTIAL: if link_util >= 1: link_weight = sys.float_info.max / core.openflow_flow_tracker.get_num_tracked_links() else: link_weight = min(self.groupflow_manager.static_link_weight + (self.groupflow_manager.util_link_weight * ((1 / (1 - link_util)) - 1)), sys.float_info.max / core.openflow_flow_tracker.get_num_tracked_links()) log.debug('Router DPID: ' + dpid_to_str(edge[0]) + ' Port: ' + str(output_port) + ' TotalUtil: ' + str(raw_link_util) + ' FlowUtil: ' + str(link_util_mcast_flow) + ' OtherFlowUtil: ' + str(link_util) + ' Weight: ' + str(link_weight)) weighted_topo_graph.append([edge[0], edge[1], link_weight]) self.weighted_topo_graph = weighted_topo_graph log.debug('Calculated link weights for source at router_dpid: ' + dpid_to_str(self.src_router_dpid)) for edge in self.weighted_topo_graph: log.debug(dpid_to_str(edge[0]) + ' -> ' + dpid_to_str(edge[1]) + ' W: ' + str(edge[2])) def install_openflow_rules(self, groupflow_trace_event = None): """Selects routes for active receivers from the cached shortest path tree, and installs/removes OpenFlow rules accordingly.""" reception_state = self.groupflow_manager.get_reception_state(self.dst_mcast_address, self.src_ip) log.debug('Reception state for ' + str(self.dst_mcast_address) + ': ' + str(reception_state)) outgoing_rules = defaultdict(lambda : None) if not groupflow_trace_event is None: groupflow_trace_event.set_route_processing_start_time(self.dst_mcast_address, self.src_ip) # Calculate the paths for the specific receivers that are currently active from the previously # calculated mst edges_to_install = [] calculated_path_router_dpids = [] for receiver in reception_state: if receiver[0] == self.src_router_dpid: continue if receiver[0] in calculated_path_router_dpids: continue # log.debug('Building path for receiver on router: ' + dpid_to_str(receiver[0])) receiver_path = self.path_tree_map[receiver[0]] log.debug('Receiver path for receiver ' + str(receiver[0]) + ': ' + str(receiver_path)) if receiver_path is None: log.warn('Path could not be determined for receiver ' + dpid_to_str(receiver[0]) + ' (network is not fully connected)') continue while receiver_path[1]: edges_to_install.append((receiver_path[1][0], receiver_path[0])) receiver_path = receiver_path[1] calculated_path_router_dpids.append(receiver[0]) # Get rid of duplicates in the edge list (must be a more efficient way to do this, find it eventually) edges_to_install = list(Set(edges_to_install)) if not edges_to_install is None: # log.info('Installing edges:') for edge in edges_to_install: log.debug('Installing: ' + str(edge[0]) + ' -> ' + str(edge[1])) if not groupflow_trace_event is None: groupflow_trace_event.set_route_processing_end_time() groupflow_trace_event.set_flow_installation_start_time() for edge in edges_to_install: if edge[0] in outgoing_rules: # Add the output action to an existing rule if it has already been generated output_port = self.groupflow_manager.adjacency[edge[0]][edge[1]] outgoing_rules[edge[0]].actions.append(of.ofp_action_output(port = output_port)) #log.debug('ER: Configured router ' + dpid_to_str(edge[0]) + ' to forward group ' + \ # str(self.dst_mcast_address) + ' to next router ' + \ # dpid_to_str(edge[1]) + ' over port: ' + str(output_port)) else: # Otherwise, generate a new flow mod msg = of.ofp_flow_mod() msg.hard_timeout = 0 msg.idle_timeout = 0 if edge[0] in self.installed_node_list: msg.command = of.OFPFC_MODIFY else: msg.command = of.OFPFC_ADD msg.match.dl_type = 0x800 # IPV4 msg.match.nw_dst = self.dst_mcast_address msg.match.nw_src = self.src_ip msg.cookie = self.flow_cookie output_port = self.groupflow_manager.adjacency[edge[0]][edge[1]] msg.actions.append(of.ofp_action_output(port = output_port)) outgoing_rules[edge[0]] = msg #log.debug('NR: Configured router ' + dpid_to_str(edge[0]) + ' to forward group ' + \ # str(self.dst_mcast_address) + ' to next router ' + \ # dpid_to_str(edge[1]) + ' over port: ' + str(output_port)) for receiver in reception_state: if receiver[0] in outgoing_rules: # Add the output action to an existing rule if it has already been generated output_port = receiver[1] outgoing_rules[receiver[0]].actions.append(of.ofp_action_output(port = output_port)) #log.debug('ER: Configured router ' + dpid_to_str(receiver[0]) + ' to forward group ' + \ # str(self.dst_mcast_address) + ' to network over port: ' + str(output_port)) else: # Otherwise, generate a new flow mod msg = of.ofp_flow_mod() msg.hard_timeout = 0 msg.idle_timeout = 0 if receiver[0] in self.installed_node_list: msg.command = of.OFPFC_MODIFY else: msg.command = of.OFPFC_ADD msg.cookie = self.flow_cookie msg.match.dl_type = 0x800 # IPV4 msg.match.nw_dst = self.dst_mcast_address msg.match.nw_src = self.src_ip output_port = receiver[1] msg.actions.append(of.ofp_action_output(port = output_port)) outgoing_rules[receiver[0]] = msg #log.debug('NR: Configured router ' + dpid_to_str(receiver[0]) + ' to forward group ' + \ # str(self.dst_mcast_address) + ' to network over port: ' + str(output_port)) # Setup empty rules for any router not involved in this path for router_dpid in self.node_list: if not router_dpid in outgoing_rules and router_dpid in self.installed_node_list: msg = of.ofp_flow_mod() msg.cookie = self.flow_cookie msg.match.dl_type = 0x800 # IPV4 msg.match.nw_dst = self.dst_mcast_address msg.match.nw_src = self.src_ip msg.command = of.OFPFC_DELETE outgoing_rules[router_dpid] = msg #log.debug('Removed rule on router ' + dpid_to_str(router_dpid) + ' for group ' + str(self.dst_mcast_address)) for router_dpid in outgoing_rules: connection = core.openflow.getConnection(router_dpid) if connection is not None: connection.send(outgoing_rules[router_dpid]) if not outgoing_rules[router_dpid].command == of.OFPFC_DELETE: self.installed_node_list.append(router_dpid) else: self.installed_node_list.remove(router_dpid) else: log.warn('Could not get connection for router: ' + dpid_to_str(router_dpid)) log.debug('New flows installed for Group: ' + str(self.dst_mcast_address) + ' Source: ' + str(self.src_ip) + ' FlowCookie: ' + str(self.flow_cookie)) if self.groupflow_manager.flow_replacement_mode == PERIODIC_FLOW_REPLACEMENT and self._flow_replacement_timer is None: log.debug('Starting flow replacement timer for Group: ' + str(self.dst_mcast_address) + ' Source: ' + str(self.src_ip) + ' FlowCookie: ' + str(self.flow_cookie)) self._flow_replacement_timer = Timer(self.groupflow_manager.flow_replacement_interval, self.update_flow_placement, recurring=True) if not groupflow_trace_event is None: groupflow_trace_event.set_flow_installation_end_time() core.groupflow_event_tracer.archive_trace_event(groupflow_trace_event) def remove_openflow_rules(self): """Removes all OpenFlow rules associated with this multicast group / sender pair. This should be used when the group has no active receivers.""" log.info('Removing rules on all routers for Group: ' + str(self.dst_mcast_address) + ' Source: ' + str(self.src_ip)) for router_dpid in self.node_list: msg = of.ofp_flow_mod() msg.cookie = self.flow_cookie msg.match.dl_type = 0x800 # IPV4 msg.match.nw_dst = self.dst_mcast_address msg.match.nw_src = self.src_ip msg.match.in_port = None msg.command = of.OFPFC_DELETE connection = core.openflow.getConnection(router_dpid) if connection is not None: connection.send(msg) else: log.warn('Could not get connection for router: ' + dpid_to_str(router_dpid)) self.installed_node_list = [] if self._flow_replacement_timer is not None: self._flow_replacement_timer.cancel() self._flow_replacement_timer = None def update_flow_placement(self, groupflow_trace_event = None): """Replaces the existing flows by recalculating the cached shortest path tree, and installing new OpenFlow rules.""" self.calc_path_tree_dijkstras(groupflow_trace_event) self.install_openflow_rules(groupflow_trace_event) log.info('Replaced flows for Group: ' + str(self.dst_mcast_address) + ' Source: ' + str(self.src_ip) + ' FlowCookie: ' + str(self.flow_cookie))
def install_openflow_rules(self, groupflow_trace_event = None): """Selects routes for active receivers from the cached shortest path tree, and installs/removes OpenFlow rules accordingly.""" reception_state = self.groupflow_manager.get_reception_state(self.dst_mcast_address, self.src_ip) log.debug('Reception state for ' + str(self.dst_mcast_address) + ': ' + str(reception_state)) outgoing_rules = defaultdict(lambda : None) if not groupflow_trace_event is None: groupflow_trace_event.set_route_processing_start_time(self.dst_mcast_address, self.src_ip) # Calculate the paths for the specific receivers that are currently active from the previously # calculated mst edges_to_install = [] calculated_path_router_dpids = [] for receiver in reception_state: if receiver[0] == self.src_router_dpid: continue if receiver[0] in calculated_path_router_dpids: continue # log.debug('Building path for receiver on router: ' + dpid_to_str(receiver[0])) receiver_path = self.path_tree_map[receiver[0]] log.debug('Receiver path for receiver ' + str(receiver[0]) + ': ' + str(receiver_path)) if receiver_path is None: log.warn('Path could not be determined for receiver ' + dpid_to_str(receiver[0]) + ' (network is not fully connected)') continue while receiver_path[1]: edges_to_install.append((receiver_path[1][0], receiver_path[0])) receiver_path = receiver_path[1] calculated_path_router_dpids.append(receiver[0]) # Get rid of duplicates in the edge list (must be a more efficient way to do this, find it eventually) edges_to_install = list(Set(edges_to_install)) if not edges_to_install is None: # log.info('Installing edges:') for edge in edges_to_install: log.debug('Installing: ' + str(edge[0]) + ' -> ' + str(edge[1])) if not groupflow_trace_event is None: groupflow_trace_event.set_route_processing_end_time() groupflow_trace_event.set_flow_installation_start_time() for edge in edges_to_install: if edge[0] in outgoing_rules: # Add the output action to an existing rule if it has already been generated output_port = self.groupflow_manager.adjacency[edge[0]][edge[1]] outgoing_rules[edge[0]].actions.append(of.ofp_action_output(port = output_port)) #log.debug('ER: Configured router ' + dpid_to_str(edge[0]) + ' to forward group ' + \ # str(self.dst_mcast_address) + ' to next router ' + \ # dpid_to_str(edge[1]) + ' over port: ' + str(output_port)) else: # Otherwise, generate a new flow mod msg = of.ofp_flow_mod() msg.hard_timeout = 0 msg.idle_timeout = 0 if edge[0] in self.installed_node_list: msg.command = of.OFPFC_MODIFY else: msg.command = of.OFPFC_ADD msg.match.dl_type = 0x800 # IPV4 msg.match.nw_dst = self.dst_mcast_address msg.match.nw_src = self.src_ip msg.cookie = self.flow_cookie output_port = self.groupflow_manager.adjacency[edge[0]][edge[1]] msg.actions.append(of.ofp_action_output(port = output_port)) outgoing_rules[edge[0]] = msg #log.debug('NR: Configured router ' + dpid_to_str(edge[0]) + ' to forward group ' + \ # str(self.dst_mcast_address) + ' to next router ' + \ # dpid_to_str(edge[1]) + ' over port: ' + str(output_port)) for receiver in reception_state: if receiver[0] in outgoing_rules: # Add the output action to an existing rule if it has already been generated output_port = receiver[1] outgoing_rules[receiver[0]].actions.append(of.ofp_action_output(port = output_port)) #log.debug('ER: Configured router ' + dpid_to_str(receiver[0]) + ' to forward group ' + \ # str(self.dst_mcast_address) + ' to network over port: ' + str(output_port)) else: # Otherwise, generate a new flow mod msg = of.ofp_flow_mod() msg.hard_timeout = 0 msg.idle_timeout = 0 if receiver[0] in self.installed_node_list: msg.command = of.OFPFC_MODIFY else: msg.command = of.OFPFC_ADD msg.cookie = self.flow_cookie msg.match.dl_type = 0x800 # IPV4 msg.match.nw_dst = self.dst_mcast_address msg.match.nw_src = self.src_ip output_port = receiver[1] msg.actions.append(of.ofp_action_output(port = output_port)) outgoing_rules[receiver[0]] = msg #log.debug('NR: Configured router ' + dpid_to_str(receiver[0]) + ' to forward group ' + \ # str(self.dst_mcast_address) + ' to network over port: ' + str(output_port)) # Setup empty rules for any router not involved in this path for router_dpid in self.node_list: if not router_dpid in outgoing_rules and router_dpid in self.installed_node_list: msg = of.ofp_flow_mod() msg.cookie = self.flow_cookie msg.match.dl_type = 0x800 # IPV4 msg.match.nw_dst = self.dst_mcast_address msg.match.nw_src = self.src_ip msg.command = of.OFPFC_DELETE outgoing_rules[router_dpid] = msg #log.debug('Removed rule on router ' + dpid_to_str(router_dpid) + ' for group ' + str(self.dst_mcast_address)) for router_dpid in outgoing_rules: connection = core.openflow.getConnection(router_dpid) if connection is not None: connection.send(outgoing_rules[router_dpid]) if not outgoing_rules[router_dpid].command == of.OFPFC_DELETE: self.installed_node_list.append(router_dpid) else: self.installed_node_list.remove(router_dpid) else: log.warn('Could not get connection for router: ' + dpid_to_str(router_dpid)) log.debug('New flows installed for Group: ' + str(self.dst_mcast_address) + ' Source: ' + str(self.src_ip) + ' FlowCookie: ' + str(self.flow_cookie)) if self.groupflow_manager.flow_replacement_mode == PERIODIC_FLOW_REPLACEMENT and self._flow_replacement_timer is None: log.debug('Starting flow replacement timer for Group: ' + str(self.dst_mcast_address) + ' Source: ' + str(self.src_ip) + ' FlowCookie: ' + str(self.flow_cookie)) self._flow_replacement_timer = Timer(self.groupflow_manager.flow_replacement_interval, self.update_flow_placement, recurring=True) if not groupflow_trace_event is None: groupflow_trace_event.set_flow_installation_end_time() core.groupflow_event_tracer.archive_trace_event(groupflow_trace_event)
def __init__(self, nexus=None): Transport.__init__(self, nexus) self._connections = {} self._t = Timer(SESSION_TIMEOUT, self._check_timeouts, recurring=True)
class AbstractRemoteDomainManager(AbstractDomainManager): """ Abstract class for different remote domain managers. Implement polling mechanism for remote domains. """ # Polling interval POLL_INTERVAL = 3 """Polling interval""" # Request formats DEFAULT_DIFF_VALUE = False """Request formats""" def __init__(self, domain_name=None, adapters=None, **kwargs): """ Init. :param domain_name: domain name :type domain_name: str :param adapters: config of adapters :type adapters: dict :param kwargs: optional params :type kwargs: dict :return: None """ super(AbstractRemoteDomainManager, self).__init__(domain_name=domain_name, adapters=adapters, **kwargs) # Timer for polling function self.__timer = None if 'poll' in kwargs: self._poll = bool(kwargs['poll']) else: self._poll = False if 'diff' in kwargs: self._diff = bool(kwargs['diff']) else: self._diff = self.DEFAULT_DIFF_VALUE self.log.debug("Enforced configuration for %s: poll: %s, diff: %s" % (self.__class__.__name__, self._poll, self._diff)) @property def detected(self): """ Return True if the Manager has detected the domain. :return: domain status :rtype: bool """ return self._detected def get_domain_url(self): if isinstance(self.topoAdapter, AbstractRESTAdapter): return self.topoAdapter.URL ############################################################################## # Abstract functions for component control ############################################################################## def init(self, configurator, **kwargs): """ Abstract function for component initialization. :param configurator: component configurator for configuring adapters :type configurator: :any:`ComponentConfigurator` :param kwargs: optional parameters :type kwargs: dict :return: None """ # Load and initiate adapters using the initiate_adapters() template func self._load_adapters(configurator=configurator, **kwargs) # Skip to start polling if it's set if not self._poll: # Try to request/parse/update Mininet topology if not self._detect_topology(): self.log.warning("%s domain not confirmed during init!" % self.domain_name) else: # Notify all components for topology change --> this event causes # the DoV updating self.raiseEventNoErrors( DomainChangedEvent, domain=self.domain_name, data=self.internal_topo, cause=DomainChangedEvent.TYPE.DOMAIN_UP) else: self.log.info("Start polling %s domain..." % self.domain_name) self.start_polling(self.POLL_INTERVAL) def initiate_adapters(self, configurator): """ Initiate Adapters for DomainManager. Must override in inherited classes. Follows the Factory Method design pattern. :param configurator: component configurator for configuring adapters :type configurator: :any:`ComponentConfigurator` :return: None """ raise NotImplementedError def finit(self): """ Abstract function for starting component. :return: None """ self.stop_polling() super(AbstractRemoteDomainManager, self).finit() ############################################################################## # Common functions for polling ############################################################################## def start_polling(self, interval=1): """ Initialize and start a Timer co-op task for polling. :param interval: polling period (default: 1) :type interval: int :return: None """ if self.__timer: # Already timing return self.__timer = Timer(interval, self.poll, recurring=True, started=True, selfStoppable=True) def restart_polling(self, interval=POLL_INTERVAL): """ Reinitialize and start a Timer co-op task for polling. :param interval: polling period (default: 3) :type interval: int :return: None """ if self.__timer: self.__timer.cancel() self.__timer = Timer(interval, self.poll, recurring=True, started=True, selfStoppable=True) def stop_polling(self): """ Stop timer. :return: None """ if self.__timer: self.__timer.cancel() self.__timer = None @property def polling(self): return self._poll def poll(self): """ Poll the defined domain agent. Handle different connection errors and go to slow/rapid poll. When an agent is (re)detected update the current resource information. :return: None """ # If domain is not detected if not self._detected: # Check the topology is reachable if self._detect_topology(): # Domain is detected and topology is updated -> restart domain polling self.restart_polling() # Notify all components for topology change --> this event causes # the DoV updating self.raiseEventNoErrors( DomainChangedEvent, domain=self.domain_name, data=self.internal_topo, cause=DomainChangedEvent.TYPE.DOMAIN_UP) return # If domain has already detected else: # Check the domain is still reachable changed = self.topoAdapter.check_topology_changed() # No changes if changed is False: # Nothing to do self.log.log( VERBOSE, "Remote domain: %s has not changed!" % self.domain_name) return # Domain has changed elif isinstance(changed, NFFG): self.log.info("Remote domain: %s has changed! " "Update global domain view..." % self.domain_name) self.log.debug("Save changed topology: %s" % changed) # Update the received new topo self.internal_topo = changed # Notify all components for topology change --> this event causes # the DoV updating self.raiseEventNoErrors( DomainChangedEvent, domain=self.domain_name, data=self.internal_topo, cause=DomainChangedEvent.TYPE.DOMAIN_CHANGED) return # If changed is None something went wrong, probably remote domain is not # reachable. Step to the other half of the function elif changed is None: self.log.warning("Lost connection with %s agent! " "Going to slow poll..." % self.domain_name) # Clear internal topology self.log.debug("Clear topology from domain: %s" % self.domain_name) self.internal_topo = None self.raiseEventNoErrors( DomainChangedEvent, domain=self.domain_name, cause=DomainChangedEvent.TYPE.DOMAIN_DOWN) else: self.log.warning( "Got unexpected return value from check_topology_changed(): %s" % type(changed)) return # If this is the first call of poll() if self._detected is None: self.log.warning("Local agent in domain: %s is not detected! " "Keep trying..." % self.domain_name) self._detected = False elif self._detected: # Detected before -> lost connection = big Problem self._detected = False self.restart_polling() else: # No success but not for the first try -> keep trying silently pass ############################################################################## # ESCAPE specific functions ############################################################################## def install_nffg(self, nffg_part): """ Install an :class:`NFFG` related to the specific domain. :raise: :any:`exceptions.NotImplementedError` :param nffg_part: NF-FG need to be deployed :type nffg_part: :class:`NFFG` :return: status if the install process was success :rtype: bool """ raise NotImplementedError def clear_domain(self): """ Clear the Domain according to the first received config. :raise: :any:`exceptions.NotImplementedError` :return: None """ raise NotImplementedError
def _ready(): if setup_time: #print '###############started coz of setup time' Timer(setup_time, _start) #time before the topology discovery starts
def launch(): core.openflow.addListenerByName("ConnectionUp", _handle_ConnectionUp) core.openflow.addListenerByName("PacketIn", _handle_PacketIn) core.openflow.addListenerByName("PortStatsReceived", _handle_portstats_received) Timer(5, _timer_func, recurring=True)
def launch(): from pox.lib.recoco import Timer core.registerNew(Phase1) global INTERVAL Timer(INTERVAL, _timer_func, recurring=True)
def launch(): core.openflow.addListenerByName("ConnectionUp",_handle_ConnectionUp) core.openflow.addListenerByName("PacketIn",_handle_PacketIn) core.openflow.addListenerByName("FlowStatsReceived",_handle_flowstats_received) # timer set to execute every five seconds Timer(5, _timer_func, recurring=True)
def send_table(self): if self.pending: return self.pending = True Timer(.2, self._do_send_table, recurring=False)
match.nw_dst = "100.100.100.0/24" #to all hosts #L4 protocol match.tp_src = src_port match.tp_dst = 80 msg.match = match msg.hard_timeout = 0 msg.idle_timeout = 0 connection.send(msg) #Helper function to print out blocked IP address and TCP source ports def print_blocked_ip(): print("Blocked IPs and TCP ports:") for ip, port in blocked_ip.items(): print("IP: %s Blocked Port: %s" % (ip, port)) #for i in range (len(blocked_ip)): #print blocked_ip[i], print("\n") #--------------Auto run Functions--------------------------------- #attach handlers to listenrs #Listens for the swithces' response to the flow_stats_request with the specific handler core.openflow.addListenerByName("FlowStatsReceived", _handle_flowstats_received) #Run _timer_func very 0.01 sec and refresh screen_output every 1 sec Timer(0.01, _timer_func, recurring=True) Timer(1, _screen_output, recurring=True)
def launch (): Timer(120, prune_tainted_list, recurring = True) Timer(300, delete_flows_for_watermark_detection, recurring = True) core.openflow.addListenerByName("ConnectionUp", _handle_ConnectionUp) core.openflow.addListenerByName("PacketIn",_handle_PacketIn)
def _handle_timer (self): self.t = Timer(1, self._handle_timer) for sw in self.switches.values(): sw._handle_timer()
def __init__(self): #Check port stats every 30 seconds Timer(30, self.check_use_of_ports, recurring = True)
def launch(): core.openflow.addListenerByName("PortStatsReceived", _handle_port_received) Timer(5,_timer_func, recurring=True)
def __init__(self): # This timer handles expiring stuff self._expire_timer = Timer(5, _handle_expiration, recurring=True) core.addListeners(self)
class ARPTable(object): MAX_ENTRIES = 1024 MAX_PENDING = 5 MAX_PENDING_TIME = 2 def __init__(self): self.by_ip = {} # ip -> entry self.pending = [] # Packets waiting to be sent (ip,(send_args)) self.timer = Timer(self.MAX_PENDING_TIME, self._timer_proc) def __str__(self): sending = set(x for x, y in self.pending) r = [] for ip, e in sorted(self.by_ip.items()): m = "%-15s %16s" % (ip, e.mac) if ip in sending: m += " p" r.append(m) return "\n".join(r) def add_entry(self, ip, mac=None): """ Add an entry The entry can't already exist. It will definitely exist after returning. """ assert ip not in self.by_ip if len(self.by_ip) >= self.MAX_ENTRIES: # Sloppy, but simple. # Get ones with lowest age entries = sorted(self.by_ip.values(), key=lambda entry: entry.age) del entries[self.MAX_ENTRIES:] self.by_ip = {e.mac: e for e in entries} new_entry = ARPEntry(ip=ip, mac=mac) self.by_ip[ip] = new_entry return new_entry def send(self, eth_packet, router_ip=None, src_eth=None, src_ip=None, send_function=None): """ Try to send a packet eth_packet is an ethernet object. src_eth is the source for any ARPs sent. src_ip is the source for any ARPs sent. If the above two are not specified, they are taken from eth_packet. send_function is a function which takes raw bytes to send. If send_function is unset, it is taken from a send_function attribute. """ if send_function is None: send_function = self.send_function ipp = eth_packet.find("ipv4") if not ipp and eth_packet.type == eth_packet.IP_TYPE: if isinstance(eth_packet.payload, bytes): # Hm! Try harder... ipp = pkt.ipv4(raw=eth_packet.payload) if not ipp or eth_packet.dst.is_multicast: send_function(eth_packet.pack()) return if ipp.dstip == pkt.IPV4.IP_BROADCAST: #ipp.dstip = router_ip # Not sure what this was about eth_packet.dst = pkt.ETHERNET.ETHER_BROADCAST send_function(eth_packet.pack()) return if ipp.dstip.is_multicast: eth_packet.dst = ipp.dstip.multicast_ethernet_address send_function(eth_packet.pack()) return if src_ip is None: src_ip = ipp.srcip if src_eth is None: src_eth = eth_packet.src if router_ip is not None: dstip = router_ip else: dstip = ipp.dstip if dstip not in self.by_ip: self.add_entry(dstip) e = self.by_ip[dstip] if e.maybe_refresh(): # Send ARP self._send_arp(dstip, src_eth, src_ip, send_function) if e.mac is not None: eth_packet.dst = e.mac send_function(eth_packet.pack()) else: if len(self.pending) < self.MAX_PENDING: self.pending.append((dstip, (eth_packet, router_ip, src_eth, src_ip, send_function))) def _timer_proc(self): # We just blow away all the entries every interval, so on average, they # live for half the interval. del self.pending[:] def __del__(self): if self.timer: self.timer.cancel() self.timer = None def _send_arp(self, dstip, src_eth, src_ip, send_function): r = pkt.arp() r.opcode = r.REQUEST r.hwdst = pkt.ETHERNET.ETHER_BROADCAST r.protodst = dstip r.hwsrc = src_eth r.protosrc = src_ip e = pkt.ethernet(type=pkt.ethernet.ARP_TYPE, src=r.hwsrc, dst=r.hwdst) e.payload = r log.debug("Sending ARP for %s", dstip) send_function(e.pack()) def rx_arp_reply(self, arp): assert arp.opcode == arp.REPLY self.rx_arp(arp) def rx_arp(self, arp): if arp.protosrc not in self.by_ip: self.add_entry(mac=arp.hwsrc, ip=arp.protosrc) else: self.by_ip[arp.protosrc].confirm(arp.hwsrc) # Send any pending packets for index, (ip, args) in reversed(list(enumerate(self.pending))): if ip == arp.protosrc: del self.pending[index] log.debug("ARP reply allows sending pending packet") self.send(*args)
def moveRegras(self): if (self.nome != "Switch HW"): return regrasInseridas = 0 Timer(1, self.moveRegras, recurring=False) global NUMPKTIN global LISTAEWMA LISTAEWMA.append(NUMPKTIN) NUMPKTIN = 0 #EWMA da quantidade de regras instaladas nos x ultimos segundos lst = pd.Series(LISTAEWMA) limite = int(pd.Series.ewm(lst, alpha=0.9).mean().values[-1]) log.info("%s: Movendo %d regra(s) para o switch SW.", self.nome, limite) for regra in self.tabela: #Movendo regra do switch HW para o switch SW if (regra.cookie == 55 or (regra.match.nw_proto != 6 and regra.match.nw_proto != 17)): continue #Ignora as regras fixas e regras de arp if (regrasInseridas < limite): #Adiciona regra no SW reg = of.ofp_flow_mod() reg.match = regra.match #Alterando in_port if (regra.match.in_port == 3): reg.match.in_port = 1 reg.actions.append(of.ofp_action_output(port=2)) else: reg.match.in_port = 2 reg.actions.append(of.ofp_action_output(port=1)) reg.priority = regra.priority reg.idle_timeout = regra.idle_timeout reg.hard_timeout = regra.hard_timeout #Adiciona regra depois de um delay t = Delay(TEMPOADD, sSW.addRegra, [reg]) t.start() if (regra.match.nw_dst == IPAddr('10.1.0.1')): #Alterando regra no UL regUL = of.ofp_match() regUL.nw_proto = regra.match.nw_proto regUL.dl_type = regra.match.dl_type regUL.nw_src = IPAddr('10.1.0.2') regUL.nw_dst = IPAddr('10.1.0.1') regUL.tp_dst = regra.match.tp_dst regUL.tp_src = regra.match.tp_src regUL.in_port = 2 mod = of.ofp_flow_mod( match=regUL, command=of.OFPFC_MODIFY, actions=[of.ofp_action_output(port=3)]) t1 = Delay(TEMPOMOD, sUL.addRegra, [mod]) t1.start() elif (regra.match.nw_dst == IPAddr('10.1.0.2')): #Alterando regra no DL regDL = of.ofp_match() regDL.nw_proto = regra.match.nw_proto regDL.dl_type = regra.match.dl_type regDL.nw_dst = IPAddr('10.1.0.2') regDL.nw_src = IPAddr('10.1.0.1') regDL.tp_dst = regra.match.tp_dst regDL.tp_src = regra.match.tp_src regDL.in_port = 2 mod = of.ofp_flow_mod( match=regDL, command=of.OFPFC_MODIFY, actions=[of.ofp_action_output(port=3)]) t2 = Delay(TEMPOMOD, sDL.addRegra, [mod]) t2.start() #Remove regra no HW dele = regra.match t3 = Delay(TEMPODEL, self.delRegra, [dele]) t3.start() #Remove a regra da tabela na memoria self.tabela.pop(0) #Aumenta o contador regrasInseridas += 1 else: log.info("%s: Regras movidas: %d", self.nome, regrasInseridas) return
def __init__(self): self.by_ip = {} # ip -> entry self.pending = [] # Packets waiting to be sent (ip,(send_args)) self.timer = Timer(self.MAX_PENDING_TIME, self._timer_proc)
def launch(): core.registerNew(GwSwOlsrdSwitch) Timer(5, _con_func, recurring=True) Timer(GW_FAILURE_CHECK_INTERVAL, gw_failure_monitoring, recurring=True)
def __init__(self, nexus=None): Transport.__init__(self, nexus) self._connections = {} #self._t = Timer(5, self._check_timeouts, recurring=True) self._t = Timer(60 * 2, self._check_timeouts, recurring=True)
def launch (): core.registerNew(l2_multi) timeout = min(max(PATH_SETUP_TIME, 5) * 2, 15) Timer(timeout, WaitingPath.expire_waiting_paths, recurring=True)
def handle_ip_complex(): """ Maneja paquetes tipo ip """ dst_mac_str = str(dst_mac) # obtengo el string de mac destino log.info("SWITCH_%s: Mac destino es %s", self.switch_id, dst_mac_str) # si el host destino es desconocido, entonces me falta conocer a mas hosts y manejo el paquete como un switch bobo if dst_mac_str not in hosts: return handle_all() host_switch_port = get_host_switch_port(dst_mac_str, self.switch_id) # si la mac destino es de un host y este switch esta directamente conectado al mismo, entonces instalo un flujo inmediatamente if host_switch_port is not None: log.info( 'SWITCH_%s: La Mac destino %s corresponde a un host conectado a MI puerto %d!', self.switch_id, dst_mac_str, host_switch_port) return install_flow(host_switch_port) # TODOOOOOOOOOO : VERIFICAR SI ACASO SE DEBE USAR install_flow EN VEZ DE install_path_flow # verifico si ya existe un path asignado a este flujo flow_key = build_flow_key() if flow_key in current_paths: path = current_paths[flow_key] log.info('SWITCH_%s: el path %s esta asignado al flow_key %s', self.switch_id, str(path), flow_key) # instalo un flujo para forwardear el paquete switch_switch_link = get_switch_switch_link( self.switch_id, path) if switch_switch_link is not None: out_port = switch_switch_link.port1 log.info( "SWITCH_%s: El paquete debe salir por mi puerto %d", self.switch_id, out_port) return install_flow(out_port) #return install_path_flow(out_port) else: log.warn( 'SWITCH_%s: encontre un path... pero yo no tengo enlace ALGO ESTA MAL', self.switch_id) return handle_all() # si llegue a este punto es porque no hay un path asignado al camino indicado... probablemente este switch es de borde # debo solicitar un camino libre y asignarlo host = get_host_by_mac(dst_mac) if host is not None: end_switch_id = host[ 'switch_id'] # obtengo el id del switch al cual esta conectado el host destino # busco o bien un camino libre o cualquier camino en caso de no existir ninguno libre log.info("SWITCH_%s: Busco un path hacia switch %s", self.switch_id, end_switch_id) path = find_non_taken_path(self.switch_id, end_switch_id) if path is None: path = find_any_path(self.switch_id, end_switch_id) path_str = str(path) log.info( "SWITCH_%s: Voy a usar el path %s y se lo asigno al flujo %s", self.switch_id, path_str, flow_key) # guardo la asociacion entre la clave del flujo y el path encontrado current_paths[flow_key] = path # marco al path encontrado como TOMADO taken_paths.add(path_str) # incremento la cantidad de veces que el camino esta siendo usado current_paths_load[path_str] += 1 # instalo un flujo para forwardear el paquete switch_switch_link = get_switch_switch_link( self.switch_id, path) if switch_switch_link is not None: out_port = switch_switch_link.port1 install_flow(out_port) #return install_path_flow(out_port) def remove_taken_path(): log.info("SWITCH_%s: ELIMINANDO PATH %s DE FLUJO %s", self.switch_id, path_str, flow_key) if path_str in taken_paths: taken_paths.remove(path_str) if flow_key in current_paths: current_paths.pop(flow_key) current_paths_load[path_str] -= 1 # despues de un tiempo elimino el path de flujo instalado Timer(FLOW_INSTALL_DURATION, remove_taken_path) return True else: log.warn( 'SWITCH_%s: encontre un path... pero yo no tengo enlace ALGO ESTA MAL', self.switch_id) return handle_all() # condicion fallback ... manejo el paquete como puedo handle_all()
def _check_handle_migration(event): '''returns 0 for no migration. returns 1 for migration''' eth_pkt = event.parsed arp_pkt = event.parsed.payload org_mac = eth_pkt.src.toStr( ) #actual mac of the current machine. same as old amac if vm mig. if vip, then diff. src_ip = arp_pkt.protosrc.toStr() old_pmac = arp_table[src_ip] old_amac = pmac_actual[old_pmac] # sw, port = pmac_pos(old_pmac) #print 'In migration check. IP:{0}, old pos - {1}:{2} new pos - {3}:{4}'.format(src_ip, sw, port, event.dpid, event.port) if (sw != event.dpid) or (port != event.port): ''' this host has migrated or virtual ip assign new pmac. add trans in new switch. add entry in old switch to frwrd to some agg switch replacing old pmac with new pmac remove prev trans tabbles from old switch. update our internal tables change the assigned mac string - not assign the old pmac for the timeout period of time ''' if org_mac == old_amac: log.info( 'VM migration detected. IP:{0}, old pos - {1}:{2} new pos - {3}:{4}' .format(src_ip, sw, port, event.dpid, event.port)) else: log.info( 'Virtual ip takeover detected. IP:{0}, old pos - {1}:{2} new pos - {3}:{4}' .format(src_ip, sw, port, event.dpid, event.port)) return move_host(src_ip, event.dpid, event.port, org_mac, event) new_pmac = _handle_new_host(org_mac, src_ip, event.dpid, event.port) barrier = of.ofp_barrier_request() event.connection.send(barrier) old_switch_con = core.openflow.connections[sw] msg = nx.nx_flow_mod(table_id=0) msg.priority = 8000 msg.hard_timeout = arp_cache_timeout msg.match.eth_dst = old_pmac rewrite_action = of.ofp_action_dl_addr.set_dst(adrs.EthAddr(new_pmac)) msg.actions.append(rewrite_action) #choose one up link by hashing up_ports = g[event.dpid].keys() num_routes = len(up_ports) #msg.actions.append(of.ofp_action_output(port = up_ports[ random.randint(0, num_routes - 1) ] ))#simple hashing. edge switch x sends to agg switch x #old_switch_con.send(msg) #if more than 2 up ports are there, then hashing is req. if 1 up port, then no hashing. if 2, then the other port other than inp port if num_routes == 1: #only one route msg.actions = [ rewrite_action, of.ofp_action_output(port=of.OFPP_IN_PORT) ] old_switch_con.send(msg) elif num_routes == 2: msg.match.NXM_OF_IN_PORT = up_ports[0] msg.actions = [ rewrite_action, of.ofp_action_output(port=up_ports[1]) ] old_switch_con.send(msg) msg.match.NXM_OF_IN_PORT = up_ports[1] msg.actions = [ rewrite_action, of.ofp_action_output(port=up_ports[0]) ] old_switch_con.send(msg) else: #3 or more ports. here need hahsing. based on src port num. also avoid the inp port. so match based on that also num_routes -= 1 #since we avoid each inp port num_bits = int(math.floor(math.log(num_routes, 2))) x = 2**num_bits #Assumption:one edge switch doesn't have more than 255 direct connections to agg switches mask = '00:00:00:' + eth_addr_format(x - 1, 2) + ':00:00' prefix = '00:00:00:' suffix = ':00:00' for ii in range(num_routes + 1): cand_ports = list(up_ports) msg.match.NXM_OF_IN_PORT = cand_ports.pop( ii) #remove the inp port from the list of op ports for i in range(num_routes): port = i % x msg.match.eth_src_with_mask = (prefix + eth_addr_format(port, 2) + suffix, mask) msg.actions = [ rewrite_action, of.ofp_action_output(port=cand_ports[i]) ] old_switch_con.send(msg) msg = nx.nx_flow_mod(table_id=0, command=of.OFPFC_DELETE) msg.priority = 5000 msg.match.NXM_OF_IN_PORT = port msg.match.eth_src = old_amac old_switch_con.send(msg) msg = nx.nx_flow_mod(table_id=1, command=of.OFPFC_DELETE) msg.priority = 5000 msg.match.eth_dst = old_pmac old_switch_con.send(msg) barrier = of.ofp_barrier_request() old_switch_con.send(barrier) arp_table[src_ip] = new_pmac actual_pmac.pop( pmac_actual.pop(old_pmac) ) #remove old pmac to actual and vice versa since they are not valid anymore actual_pmac[org_mac] = new_pmac pmac_actual[new_pmac] = org_mac #this nxt 2 lines should be in a fn called after the timeout. we dont want to assing old pmac to anyone until then def _remove_old_pmac(): vmid = int(old_pmac[-5:].replace(':', ''), 16) assigned_pmac[sw][port] = assigned_pmac[sw][ port][:vmid] + '0' + assigned_pmac[sw][port][vmid + 1:] Timer(arp_cache_timeout, _remove_old_pmac) return 1 return 0
class MyExplorer(object): def __init__ (self): log.warning("MyExplorer Constructed.") core.listen_to_dependencies(self) # Adjacency map. [sw1][sw2] -> port from sw1 to sw2 self.adj = defaultdict(lambda:defaultdict(lambda:int)) # Port map. [sw1][sw2] -> the output port from sw1 to sw2 self.ports = defaultdict(lambda:defaultdict(lambda:int)) # Switches we know of. [dpid] -> Switch self.switches = set() self.reset_hosts() # self.hosts: Hosts we know of. [macaddr (string)] -> Host # self.hadj: [h][sw] -> the ports where switchs connect to the hosts # self.sd_pair: [h1][h2] -> source-destination pair id self.reset_path_tables() # self.path_id_table: Path ID -> Path table # self.sd_path_table: [Source][Destination] -> Path ID list self.reset_srcport_tables() # self.sd_srcport_table: [Source][Destination] -> Srcport list self.reset_flowdist_tables() # self.flow_dist_table: [sd_pair_id][path_id-1] -> Srcport distribution # Latency test function self.adj_test = [] self.sw_test = [] self.sw_lat = [] self.lat_test_timer = [] # Does latency test Start? self.lat_test = False # Update step self.update_step = 0 self.update_timer = [] self.config = Configuration() random.seed(time.time()) """ Event Handlers """ def _handle_core_ComponentRegistered (self, event): log.warning(event.name) if event.name == "host_tracker": event.component.addListenerByName("HostEvent", self.__handle_host_tracker_HostEvent) def _handle_openflow_ConnectionUp (self, event): dp = event.connection.dpid self.switches.add(dp) event.connection.addListenerByName("PacketIn", self.__handle_PacketIn) log.warning("Switch %s is discovered.", dpid_to_str(dp)) def _handle_openflow_ConnectionDown (self, event): pass def _handle_openflow_discovery_LinkEvent (self, event): (dp1,p1),(dp2,p2) = event.link.end self.adj[dp1][dp2] = 1 self.ports[dp1][dp2] = p1 log.warning( "Link %s -> %s is discovered.", dpid_to_str(dp1), dpid_to_str(dp2) ) def __handle_host_tracker_HostEvent (self, event): h = event.entry.macaddr.toStr() s = event.entry.dpid if h == "ff:ff:ff:ff:ff:ff": # The address for broadcasting and testing return if event.leave: if h in self.hosts: if s in self.hadj[h]: self.hosts.remove(h) del s else: # event.join, event.move, ... if h not in self.hosts: self.hosts.add(h) else: for s1 in self.hadj[h]: del s1 self.hadj[h][s] = event.entry.port log.warning("Host %s is discovered.", h) def __handle_PacketIn(self, event): packet = event.parsed src = packet.src.toStr() dst = packet.dst.toStr() # Extract IP information ip = packet.find('ipv4') udpp = packet.find('udp') if ip: # it is not a good way to define a variable, anyway srcip = ip.srcip dstip = ip.dstip self.srcip_table[src] = srcip self.dstip_table[dst] = dstip if udpp: srcport = udpp.srcport # Each src-dst pair has several ports if srcport not in self.sd_srcport_table[src][dst]: # New port discovered self.sd_srcport_table[src][dst].append(srcport) # Latency test packets handling if self.lat_test: if packet.type != 0x5566: # not test packet, drop it return src = self._MAC_to_int(src) dst = self._MAC_to_int(dst) timeinit, = struct.unpack('!I', packet.find('ethernet').payload) timediff = time.time()*1000 - self.system_time - timeinit if src in self.adj_test: if dst in self.adj_test[src]: self.adj[src][dst] = timediff del self.adj_test[src][dst] if dst in self.sw_test: self.sw_lat[dst] = timediff self.sw_test.remove(dst) return # assign path id pid = 0 if src in self.hosts: for d in self.sd_path_table[src]: # FIXME: Pick one as default # Maybe we should apply flood function to broadcasting for sd_path_id in self.sd_path_table[src][d]: pid = sd_path_id # log.warning("Packet Vid = %i", pid) if dst in self.hosts: if self.config.config_set: if ip and udpp: # If the packet is an IP/UDP packet id_list = self.sd_path_table[src][dst] # last one, in case not found pid = self.get_pid_by_srcport(id_list, srcport) if pid is None: # Not existed port, choose the last one as default pid = id_list[len(id_list) - 1] for k in id_list: now_split = self.config.now_config real_split = self.config.real_config # log.warning("now %s real %s", now_split, real_split ) if now_split[k-1] > real_split[k-1] or now_split[k-1] == 1: pid = k break # update flow_dist_table and real_config_table self.flow_dist_table[pid-1].append(srcport) self.config.compute_real_config(id_list, self.flow_dist_table) else: id_list = self.sd_path_table[src][dst] # last one, in case not found pid = id_list[len(id_list) - 1] sum_of_all = 0 for x in id_list: sum_of_all += self.config.now_config[x-1] rand_num = sum_of_all * random.random() for x in id_list: rand_num -= self.config.now_config[x-1] # Since the path ID starts from 1, which is different from the index if rand_num < 0: # path_id should start from 1 pid = x break # log.warning("SD pair %i, pid %i", self.sd_pair[src][dst], pid) else: # FIXME: path selection for sd_path_id in self.sd_path_table[src][dst]: # There exists a path pid = sd_path_id # log.warning("Packet Vid = %i", pid) if ip and udpp: # FIXME: Do we need to modify the flow whenever the packet in? msg = of.ofp_flow_mod() msg.match.dl_type = 0x800 msg.match.nw_src = IPAddr(srcip) msg.match.nw_dst = IPAddr(dstip) msg.match.nw_proto = 17 msg.match.tp_src = srcport # slog.warning("Add rule for port %s", srcport) else: msg = of.ofp_packet_out(data = event.ofp) if pid != 0: # There exists a path path = self.path_id_table[pid] if len(path) > 3: # It is not the last sw, tag it and send into the network if USE_VLAN_TAG: msg.actions.append( of.ofp_action_vlan_vid( vlan_vid = pid ) ) if USE_ETHERNET_SRC_TAG: msg.actions.append( of.ofp_action_dl_addr.set_src( EthAddr( self._int_to_MAC( pid ) ) ) ) msg.actions.append( of.ofp_action_output( port = self.ports[path[1]][path[2]] ) ) elif len(path) == 3: # last sw, forward to the host #msg.actions.append( of.ofp_action_output( port = of.OFPP_FLOOD ) ) msg.actions.append( of.ofp_action_output( port = self.hadj[path[2]][path[1]] ) ) event.connection.send(msg) """ msg = of.ofp_packet_out( data = event.ofp ) if pid != 0: # There exists a path path = self.path_id_table[pid] if len(path) > 3: # It is not the last sw, tag it and send into the network if USE_VLAN_TAG: msg.actions.append( of.ofp_action_vlan_vid( vlan_vid = pid ) ) if USE_ETHERNET_SRC_TAG: msg.actions.append( of.ofp_action_dl_addr.set_src( EthAddr( self._int_to_MAC( pid ) ) ) ) msg.actions.append( of.ofp_action_output( port = self.ports[path[1]][path[2]] ) ) elif len(path) == 3: # last sw, forward to the host # msg.actions.append( of.ofp_action_output( port = of.OFPP_FLOOD ) ) msg.actions.append( of.ofp_action_output( port = self.hadj[path[2]][path[1]] ) ) """ def _handle_openflow_FlowStatsReceived (self, event): log.warning("Flow stats received.") for x in flow_stats_to_list(event.stats): log.warning( x ) def _handle_openflow_PortStatsReceived (self, event): log.warning("Port stats received.") log.warning(flow_stats_to_list(event.stats)) """ Tool Functions """ def _clear_all_paths_for_all_switches (self): msg = of.ofp_flow_mod(command=of.OFPFC_DELETE) # iterate over all connected switches and delete all their flows for sw in self.switches: # _connections.values() before betta core.openflow.sendToDPID(sw, msg) log.warning("Clearing all flows from %s.", dpidToStr(sw)) def _set_path_on_swtiches (self, pid, path): for k, sw in enumerate(path): msg = of.ofp_flow_mod() if USE_VLAN_TAG: msg.match.dl_vlan = pid if USE_ETHERNET_SRC_TAG: msg.match.dl_src = EthAddr( self._int_to_MAC( pid ) ) # match ethernet addr if k < 1: # First one, host continue if k > len(path)-2: # Last one, host continue if k == len(path) - 2: # sw -> host if USE_VLAN_TAG: # strip vlan tag then send to host msg.actions.append( of.ofp_action_strip_vlan() ) if USE_ETHERNET_SRC_TAG: # add back the real src msg.actions.append( of.ofp_action_dl_addr.set_src( EthAddr(path[0]) ) ) msg.actions.append( of.ofp_action_output( port = self.hadj[path[k+1]][sw] ) ) core.openflow.sendToDPID(sw, msg) log.warning( "Set rule: %s -> %s via port %i", dpid_to_str(sw), path[k+1], self.hadj[path[k+1]][sw] ) else: # sw -> sw msg.actions.append( of.ofp_action_output( port = self.ports[sw][path[k+1]] ) ) core.openflow.sendToDPID(sw, msg) log.warning( "Set rule: %s -> %s via port %i", dpid_to_str(sw), dpid_to_str(path[k+1]), self.ports[sw][path[k+1]] ) def _int_to_MAC(self, pid): tmp_pid = pid ma=[] for x in range(0, 6): ma.append( "%X" % (tmp_pid % 256) ) tmp_pid //= 256 return ma[5] + ":" + ma[4] + ":" + ma[3] + ":" + ma[2] + ":" + ma[1] + ":" + ma[0] def _MAC_to_int(self, mac): return int( "0x" + mac.replace(':', ''), 16) def _latency_ready(self): # Check if it has TIMEOUT or all the link latencies have been detected if time.time()*1000 - self.system_time < SYSTEM_TIMEOUT: for x in self.adj_test: for y in self.adj_test[x]: # Not yet log.warning("Waiting ...") return for x in self.sw_test: # Not yet log.warning("Waiting ...") return for sw in self.sw_test: self.sw_lat[sw] = LATENCY_MAX log.warning("sw %i timeout!", sw) for s1 in self.adj_test: for s2 in self.adj_test[s1]: self.adj[s1][s2] = LATENCY_MAX log.warning("link %i -> %i timeout!", s1, s2) for s1 in self.adj: for s2 in self.adj[s1]: self.adj[s1][s2] -= (self.sw_lat[s1] + self.sw_lat[s2])/2 self.lat_test_timer.cancel() self.lat_test = False log.warning("Latency test done.") def _update_step(self): if self.update_step > len(self.config.config) - 1: self.update_timer.cancel() log.warning("Updating Ends.") return self.config.change_step(self.update_step) self.update_timer._next = time.time() + self.config.next_time # redistribute flows based on new configuration self.config.reset_real_config() self.reset_flowdist_tables() # Compute for each port in all source destination pair for src in self.sd_path_table: for dst in self.sd_path_table[src]: id_list = self.sd_path_table[src][dst] for srcport in self.sd_srcport_table[src][dst]: pid = self.get_pid_by_srcport(id_list, srcport) # should be None if pid is None: # Not existed port, choose the last one as default pid = id_list[len(id_list) - 1] for k in id_list: now_split = self.config.now_config real_split = self.config.real_config if now_split[k-1] > real_split[k-1] or now_split[k-1] == 1: pid = k break # update flow_dist_table and real_config_table self.flow_dist_table[pid-1].append(srcport) self.config.compute_real_config(id_list, self.flow_dist_table) log.warning("pid %s", pid) srcip = self.srcip_table[src] dstip = self.dstip_table[dst] msg = of.ofp_flow_mod( command = of.OFPFC_MODIFY ) msg.match.dl_type = 0x800 msg.match.nw_src = IPAddr(srcip) msg.match.nw_dst = IPAddr(dstip) msg.match.nw_proto = 17 msg.match.tp_src = srcport path = self.path_id_table[pid] if len(path) > 3: # It is not the last sw, tag it and send into the network if USE_VLAN_TAG: msg.actions.append( of.ofp_action_vlan_vid( vlan_vid = pid ) ) if USE_ETHERNET_SRC_TAG: msg.actions.append( of.ofp_action_dl_addr.set_src( EthAddr( self._int_to_MAC( pid ) ) ) ) msg.actions.append( of.ofp_action_output( port = self.ports[path[1]][path[2]] ) ) elif len(path) == 3: # last sw, forward to the host # msg.actions.append( of.ofp_action_output( port = of.OFPP_FLOOD ) ) msg.actions.append( of.ofp_action_output( port = self.hadj[path[2]][path[1]] ) ) sw = path[1] core.openflow.sendToDPID(sw, msg) # print msg # log.warning("SD pair %i, pid %i", self.sd_pair[src][dst], pid) log.warning("Update Step %i ...", self.update_step) self.update_step += 1 """ The function starts with a small letter is for command line interface """ def reset_hosts (self): # Hosts we know of. [macaddr] -> Host self.hosts = set() # The ports where switches connect to the hosts self.hadj = defaultdict(lambda:defaultdict(lambda:int)) # self.sd_pair: [h1][h2] -> source-destination pair id self.sd_pair = defaultdict(lambda:defaultdict(lambda:int)) def reset_path_tables (self): # Path ID -> Path table self.path_id_table = defaultdict(lambda:[]) # [Source][Destination] -> Path ID list self.sd_path_table = defaultdict(lambda:defaultdict(lambda:[])) def reset_srcport_tables (self): # [Source][Destination] -> Srcport list self.sd_srcport_table = defaultdict(lambda:defaultdict(lambda:[])) # [Source] -> srcip self.srcip_table = defaultdict(lambda:[]) # [Destination] -> dstip self.dstip_table = defaultdict(lambda:[]) def reset_flowdist_tables (self): # [path_id-1] -> Srcports self.flow_dist_table = defaultdict(lambda:[]) def get_pid_by_srcport (self, id_list, srcport): # Match the srcport from cadidate path_id in id_list for path_id in id_list: if srcport in self.flow_dist_table[path_id - 1]: return path_id return None def port_stat (self, dpid): core.openflow.sendToDPID( dpid, of.ofp_stats_request(body=of.ofp_port_stats_request()) ) def sw_stat (self, dpid): core.openflow.sendToDPID( dpid, of.ofp_stats_request(body=of.ofp_flow_stats_request()) ) def latency(self): # Find link latencies and write into self.adj log.warning("Start latency test, please wait ...") self.lat_test = True self._clear_all_paths_for_all_switches() self.adj_test = copy.deepcopy(self.adj) self.sw_test = copy.copy(self.switches) self.sw_lat = defaultdict(lambda:int) # system reference self.system_time = time.time()*1000 for sw in self.sw_test: proto = ProbeProto() proto.timestamp = int(time.time()*1000 - self.system_time) e = pkt.ethernet() e.type = 0x5566 e.src = EthAddr( "ff:ff:ff:ff:ff:ff" ) e.dst = EthAddr( self._int_to_MAC(sw) ) e.payload = proto msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output( port = of.OFPP_CONTROLLER ) ) core.openflow.sendToDPID(sw, msg) for src in self.adj_test: for dst in self.adj_test[src]: proto = ProbeProto() proto.timestamp = int(time.time()*1000 - self.system_time) e = pkt.ethernet() e.type = 0x5566 e.src = EthAddr( self._int_to_MAC(src) ) e.dst = EthAddr( self._int_to_MAC(dst) ) e.payload = proto msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output( port = self.ports[src][dst] ) ) core.openflow.sendToDPID(src, msg) self.lat_test_timer = Timer(1, self._latency_ready, started = True, recurring = True) def k_path (self, k): # Find k-shortest path based on self.adj and self.hadj log.warning("Find %u path",k) alladj = copy.deepcopy(self.adj) for h in self.hadj: for s in self.hadj[h]: alladj[h][s] = 1 alladj[s][h] = 1 G = y_gra.DiGraph(alladj) log.warning("Graph constructed") self._clear_all_paths_for_all_switches() self.reset_path_tables() self.reset_flowdist_tables() self.reset_srcport_tables() # sd_pair_id, h1, h2, path_id ... output_table_1 = "" # path_id, path_id_table[path_id] output_table_2 = "" sd_pair_id = 0 path_id = 1 for h1 in self.hadj: for h2 in self.hadj: if h1 != h2: self.sd_pair[h1][h2] = sd_pair_id output_table_1 += str(sd_pair_id) + " ( " + h1 + " , " + h2 + " ) : " sd_pair_id += 1 items = y_alg.ksp_yen(G,h1,h2,k) for path in items: #print "Cost:%s\t%s" % (path['cost'], "->".join(path['path'])) self.path_id_table[path_id] = path['path'] self.sd_path_table[h1][h2].append(path_id) output_table_1 += str(path_id) + " " output_table_2 += str(path_id) + " " + "%s" % self.path_id_table[path_id] + "\n" path_id += 1 output_table_1 += "\n" for pid in self.path_id_table: self._set_path_on_swtiches (pid, self.path_id_table[pid]) output_file = open(OUTPUT_PATH_FILENAME, "w") output_file.write("SD pairs:\n%s" % output_table_1) output_file.write("\nPath IDs:\n%s" % output_table_2) output_file.close() def update(self): # let the controller start update the configuration log.warning("Updating Starts.") self.update_step = 0 self.config.read_config( INPUT_CONFIG_FILENAME ) # Initial update self.update_timer = Timer(self.config.next_time, self._update_step, started = False, recurring = True) self._update_step() self.update_timer.start()