Exemplo n.º 1
0
    def run(self):
        """Main loop
        """
        while self.running:
            if (len(self._events) == 0):
                #Sleep for some time if nothing to do
                time.sleep(self.sleep)
                continue
            else:
                while (self._events.has_event_ready()):
                    (t, event) = self._events.get_next()
                    if ((t-time.time()) > self.tolerance):
                        output.warn("Event "+event.name+" scheduled for "+str(t)+\
                                    " is being run at time "+str(time.time()),
                                    self.__class__.__name__)
                    else:
                        output.vvdbg("Event "+event.name+" scheduled for "+str(t)+\
                                     " is being run at time "+str(time.time()),
                                     self.__class__.__name__)
                    self._dispatch_event(event)

            ntime = self.sleep
            if (len(self._events) > 0):
                ntime = self._events.get_next_time() - time.time()
            time.sleep(min(ntime, self.sleep))
Exemplo n.º 2
0
Arquivo: nat.py Projeto: yapkke/yapc
    def _process_outbound(self, pktin, intfs, iport, lointf):
        """Event handler for outbound ARP packets

        @param pktin packet in event to handle
        @param intfs dictionary of interfaces (with ip range)
        @param iport port no of local interface
        @param lointf local interface address (ip, mac)
        @return false
        """
        for portno, ipr in intfs.items():
            if (ipr[0] & ipr[1]) == (pktin.match.nw_dst & ipr[1]):
                flow = flows.exact_entry(pktin.match)
                if flow.buffer_id != pktin.pktin.buffer_id:
                    output.warn("Buffered outbound ARP packet (cannot be rewritten properly)!", self.__class__.__name__)
                else:
                    flow.add_output(portno)
                    ofpkt.dl_rewrite(pktin.dpkt, True, ipr[2])
                    ofpkt.nw_rewrite(pktin.dpkt, True, ipr[0])
                    self.get_conn().send(flow.get_packet_out().pack() + pktin.dpkt.pack())
                    output.vdbg(
                        "ARP to " + pu.ip_val2string(pktin.match.nw_dst) + " sent to port " + str(portno),
                        self.__class__.__name__,
                    )
                return False
        output.warn("ARP for " + pu.ip_val2string(pktin.match.nw_dst) + " unknown subnet", self.__class__.__name__)
        return False
Exemplo n.º 3
0
    def dohandshake(self, msg):
        """Function to carry out handshake

        Switch (hello) => hello + feature request
        Switch (feature reply) => DONE
        """
        if (msg.header.type == pyopenflow.OFPT_HELLO):
            sendmsg = pyopenflow.ofp_hello()
            self.send(sendmsg.pack())
            sendmsg = pyopenflow.ofp_header()
            sendmsg.type = pyopenflow.OFPT_FEATURES_REQUEST
            self.send(sendmsg.pack())

        elif (msg.header.type == pyopenflow.OFPT_FEATURES_REPLY):
            switch_feature = pyopenflow.ofp_switch_features()
            switch_feature.unpack(msg.message)
            self.dpid = switch_feature.datapath_id
            output.info("Connected to switch %x" % self.dpid,
                        self.__class__.__name__)
            self.handshake = True
            
        else:
            output.warn("Handshake should not handle message type "+\
                            pyopenflow.ofp_type[msg.header.type],
                        self.__class__.__name__)
Exemplo n.º 4
0
    def __init__(self, sock, msg, stats_reply=None, reply=None):
        """Initialize

        @param sock reference to socket
        @param msg message
        """
        ofcomm.message.__init__(self, sock, msg)

        ##Stats reply header
        self.stats_reply = stats_reply
        
        remaining = reply
        if (self.stats_reply == None) or (remaining == None):
            self.stats_reply = pyof.ofp_stats_reply()
            remaining = self.stats_reply.unpack(msg)
        
        ##Flow stats of individual flows
        self.flows = []
        while (len(remaining) >= pyof.OFP_FLOW_STATS_BYTES):
            flow = pyof.ofp_flow_stats()
            flow.unpack(remaining)
            self.unpack_actions(remaining[pyof.OFP_FLOW_STATS_BYTES:flow.length], flow.actions)
            remaining = remaining[flow.length:]
            self.flows.append(flow)

        if (len(remaining) > 0):
            output.warn("Flow stats reply is of irregular length with "+\
                            str(len(remaining))+" bytes remaining.",
                        self.__class__.__name__)
        output.vdbg("Received "+str(len(self.flows))+" flow stats.",
                   self.__class__.__name__)
Exemplo n.º 5
0
Arquivo: nat.py Projeto: yapkke/yapc
    def _process_inbound(self, pktin, intfs, iport, lointf):
        """Event handler for inbound ARP packets

        @param pktin packet in event to handle
        @param intfs dictionary of interfaces (with ip range)
        @param iport port no of local interface
        @param lointf local interface address (ip, mac)
        @return false
        """
        try:
            ipr = intfs[pktin.match.in_port]
        except KeyError:
            output.vdbg("ARP packet received on unknown/uninitialized interface", self.__class__.__name__)
            return False

        flow = flows.exact_entry(pktin.match)
        if flow.buffer_id != pktin.pktin.buffer_id:
            output.warn("Buffered inbound ARP packet (cannot be rewritten properly)!", self.__class__.__name__)
        elif flow.match.nw_dst != ipr[0]:
            output.vdbg("Inbound ARP packet not destined for this host, ignored.", self.__class__.__name__)
        else:
            flow.add_output(iport)
            if pu.array2val(pktin.match.dl_dst) != 0xFFFFFFFFFFFF:
                ofpkt.dl_rewrite(pktin.dpkt, False, lointf[1])
            ofpkt.nw_rewrite(pktin.dpkt, False, lointf[0])
            self.get_conn().send(flow.get_packet_out().pack() + pktin.dpkt.pack())
        return False
Exemplo n.º 6
0
    def __init__(self, sock, msg):
        """Initialize

        @param sock reference to socket
        @param msg message
        """
        ofcomm.message.__init__(self, sock, msg)

        ##Features struct
        self.features = None
        
        if (self.header.type == pyof.OFPT_FEATURES_REPLY):
            self.features = pyof.ofp_switch_features()
            r = self.features.unpack(msg)
            while (len(r) >= pyof.OFP_PHY_PORT_BYTES):
                p = pyof.ofp_phy_port()
                r = p.unpack(r)
                self.features.ports.append(p)
            if (len(r) > 0):
                output.warn("Features reply is of irregular length with "+\
                                str(len(r))+" bytes remaining.",
                            self.__class__.__name__)
            output.dbg("Received switch features:\n"+\
                           self.features.show("\t"),
                       self.__class__.__name__)
Exemplo n.º 7
0
Arquivo: nat.py Projeto: yapkke/yapc
    def dns_select_intf(self, intfs):
        """Get which interface to send

        @return port no to send flow on and None if nothing to choose from
        """
        if len(intfs) == 0:
            return None

        if self.coin == None:
            output.warn(
                "No COIN server reference provided.  Default to random choice of interface", self.__class__.__name__
            )
            return self.select_nth_intf(intfs, 1)

        if self.coin.config["dns_select_interface"] == "random":
            return self.random_select_intf(intfs)
        elif self.coin.config["dns_select_interface"] == "round_robin":
            return self.round_robin_select_intf(intfs)
        elif self.coin.config["dns_select_interface"] == "bandwidth":
            return self.bandwidth_select_intf(intfs)
        elif isinstance(self.coin.config["dns_select_interface"], int):
            return self.select_nth_intf(intfs, self.coin.config["dns_select_interface"])
        else:
            value = 1
            try:
                value = int(self.coin.config["dns_select_interface"])
                self.coin.set_config("dns_select_interface", value)
            except ValueError:
                output.warn("Unknown selection configuration!", self.__class__.__name__)
            return self.select_nth_intf(intfs, value)
Exemplo n.º 8
0
    def processevent(self, event):
        """Process event

        @param event event to process
        @return True
        """
        if (isinstance(event, yapc.priv_callback)):
            lastr = self.lastresult
            r = self.get_stat()
            output.vdbg(r)

            if (lastr == None):
                self._server.post_event(yapc.priv_callback(self), self.interval)
                return True

            for k,v in r.items():
                for k2 in ["transmit", "receive"]:
                    try:
                        v[k2]["bps"] = (float(v[k2]["bytes"] - lastr[k][k2]["bytes"])*8.0/
                                        (v["timestamp"]-lastr[k]["timestamp"]))
                        v[k2]["pps"] = (float(v[k2]["packets"] - lastr[k][k2]["packets"])/
                                        (v["timestamp"]-lastr[k]["timestamp"]))
                    except KeyError:
                        output.warn("Interface "+str(k)+" is new or removed",
                                    self.__class__.__name__)

            self._server.post_event(yapc.priv_callback(self), self.interval)

        return True
Exemplo n.º 9
0
    def order_cleanup(self, earlier_handler, later_handler):
        """Order handler for cleanup

        Do so by moving earlier handler to be just before the later handler

        @param earlier_handler handler that should process event earlier
        @param later_handler handler that should process event later
        """
        eindex = -1
        if (earlier_handler in self.cleanups):
            eindex = self.cleanups.index(earlier_handler)
        else:
            output.warn(earlier_handler.__class__.__name__+\
                        " did not register for a cleanup".
                        self.__class__.__name__)
            return

        lindex = -1
        if (later_handler in self.cleanups):
            lindex = self.cleanups.index(later_handler)
        else:
            output.warn(laterr_handler.__class__.__name__+\
                        " did not register for a cleanup",
                        self.__class__.__name__)
            return

        #Reorder
        if (lindex < eindex):
            self.cleanups.insert(lindex, self.cleanups.pop(eindex))
Exemplo n.º 10
0
Arquivo: ovs.py Projeto: yapkke/yapc
    def __process_switch_json(self, event):
        """Process JSON messages for switch

        @param event JSON message event for switch
        """
        reply = {}
        reply["type"] = "coin"
        reply["subtype"] = "ovs"

        if event.message["command"] == "add_if":
            self.add_if(event.message["name"])
            reply["executed"] = True
        elif event.message["command"] == "del_if":
            self.datapaths[COIN_DP_NAME].del_if(event.message["name"])
            reply["executed"] = True
        elif event.message["command"] == "get_interfaces":
            dpidsl = mc.get(swstate.dp_features.DP_SOCK_LIST)
            if dpidsl != None:
                reply["interfaces"] = []
                if len(dpidsl) > 1:
                    output.warn(str(len(dpidsl)) + " datapaths connected to COIN", self.__class__.__name__)
                f = mc.get(dpidsl[0])
                output.dbg("Updated switch features:\n" + f.show("\t"), self.__class__.__name__)
                for p in f.ports:
                    reply["interfaces"].append(p.name)
            else:
                output.warn("No datapaths connected to COIN", self.__class__.__name__)
                reply["error"] = "No datapath connected"
        else:
            reply["error"] = "Unknown command"

        return reply
Exemplo n.º 11
0
 def eventname(self):
     """Provide name for event used to publish data
     
     @return event name
     """
     output.warn("eventname should overloaded",
                 self.__class__.__name__)
     return None
Exemplo n.º 12
0
 def send(self, sock, msg):
     """Send message on socket
     """
     try:
         self.db[sock].send(msg)
     except KeyError:
         output.warn("Message dropped because socket is already closed",
                     self.__class__.__name__)
Exemplo n.º 13
0
Arquivo: json.py Projeto: yapkke/yapc
 def send(self, msg):
     """Send dictionary as JSON message
     """
     try:
         self.sock.send(simplejson.dumps(msg))
         output.dbg("Send message " + simplejson.dumps(msg), self.__class__.__name__)
     except socket.error:
         output.warn(str(self.sock) + " is broken, message is dropped!", self.__class__.__name__)
Exemplo n.º 14
0
    def processevent(self, event):
        """Process OpenFlow message for switch status
        
        @param event OpenFlow message event to process
        @return True
        """
        if isinstance(event, ofevents.features_reply):
            # Maintain list of datapath socket
            key = self.get_key(event.sock)
            dpidsl = mc.get(dp_features.DP_SOCK_LIST)
            if dpidsl == None:
                dpidsl = []
            if key not in dpidsl:
                dpidsl.append(key)
            mc.set(dp_features.DP_SOCK_LIST, dpidsl)

            # Maintain dp features in memcache
            mc.set(key, event.features)

        elif isinstance(event, ofevents.port_status):
            # Port status
            if event.header.type == pyof.OFPT_PORT_STATUS:
                key = self.get_key(event.sock)
                sw = mc.get(key)
                if sw == None:
                    output.warn("Port status from unknown datapath", self.__class__.__name__)
                else:
                    output.dbg("Received port status:\n" + event.port.show("\t"), self.__class__.__name__)
                    if event.port.reason == pyof.OFPPR_DELETE or event.port.reason == pyof.OFPPR_MODIFY:
                        for p in sw.ports:
                            if p.port_no == event.port.desc.port_no:
                                sw.ports.remove(p)
                    if event.port.reason == pyof.OFPPR_ADD or event.port.reason == pyof.OFPPR_MODIFY:
                        sw.ports.append(event.port.desc)
                    output.dbg("Updated switch features:\n" + sw.show("\t"), self.__class__.__name__)
                    mc.set(key, sw)

        elif isinstance(event, comm.event):
            # Socket close
            if event.event == comm.event.SOCK_CLOSE:
                key = self.get_key(event.sock)
                sw = mc.get(key)
                if sw != None:
                    output.info("Datapath %x leaves" % sw.datapath_id, self.__class__.__name__)
                    # Maintain list of datapath socket
                    dpidsl = mc.get(dp_features.DP_SOCK_LIST)
                    if dpidsl != None:
                        if key in dpidsl:
                            dpidsl.remove(key)
                        mc.set(dp_features.DP_SOCK_LIST, dpidsl)

                    # Remove features
                    mc.delete(key)

        return True
Exemplo n.º 15
0
 def parse(self, entry_line):
     """Parse line
     """
     i = entry_line.split()
     if (len(i) == 3):
         pass #Incomplete entry
     elif (len(i) != 5):
         output.warn("ARP entry line should have 5 items but "+str(len(i))+" found",
                     self.__class__.__name__)
     else:
         self.ip = i[0]
         self.mac = i[2]
         self.iface = i[4]
Exemplo n.º 16
0
    def get_conn(self):
        """Get connection

        @return the one and only connection to send messages (None otherwise)
        """
        if (len(self.conn.db) > 1):
            output.warn("More than one connection to COIN!",
                        self.__class__.__name__)

        for s,c in self.conn.db.items():
            return c

        return None
Exemplo n.º 17
0
    def del_if(self, intf):
        """Remove interface to datapath

        @param intf name of interface
        @return command's exit status
        """
        if (intf in self.interfaces):
            self.interfaces.remove(intf)
            return cmd.run_cmd(DPCTL+" del-if "+self.name+" "+intf,
                               self.__class__.__name__)
        else:
            output.warn("Interface "+intf+" do not exist for deletion",
                        self.__class__.__name__)
Exemplo n.º 18
0
Arquivo: ovs.py Projeto: yapkke/yapc
 def get_sw_feature(self):
     """Get switch description
     
     @return switch features else None
     """
     dpidsl = mc.get(swstate.dp_features.DP_SOCK_LIST)
     if dpidsl != None:
         if len(dpidsl) > 1:
             output.warn(str(len(dpidsl)) + " datapaths connected to COIN", self.__class__.__name__)
         f = mc.get(dpidsl[0])
         return f
     else:
         return None
Exemplo n.º 19
0
    def add_row(self, row):
        """Add data to the table

        @param row  is a tuple of data
        """
        if (len(row) == len(self.columns)):
            output.vdbg("Add row :"+str(row))
            self.data_cache.append(row)
            if (len(self.data_cache) >= self.cache_size):
                self.flush_cache()
        else:
            output.warn("Adding row "+str(row)+" with "+len(row)+" items"+\
                            " when there is "+len(self.columns)+" columns",
                        self.__class__.__name__)
Exemplo n.º 20
0
def set(name, value, timeout=0):
    """Set key and value

    @param name key name
    @param value value to set key to
    @param timeout timeout to expire data
    """
    global memcache_mode
    if memcache_mode == MEMCACHE_MODE["OFF"]:
        return None

    if name.find(" ") != -1:
        output.warn("Memcache key cannot contain spaces", "memcache util")
    return memcache_client.set(name, value, timeout)
Exemplo n.º 21
0
    def flush_cache(self, close=True):
        """Flush data in cache in database
        """
        if (self.db == None):
            output.warn("No database to flush data into",
                        self.__class__.__name__)
            return

        output.vdbg("Flush cache of "+str(len(self.data_cache))+" items",
                    self.__class__.__name__)
        stmt = "?,"*len(self.columns)
        self.db.executemany("INSERT INTO "+self.name+\
                                " VALUES ("+stmt[:-1]+")",
                            self.data_cache, close)
        self.data_cache = []
Exemplo n.º 22
0
 def registereventhandler(self, eventname, handler):
     """Register handler for event
     
     Event should be registered in order of calling
     @param eventname name of event
     @param handler handler function
     """
     if (not isinstance(eventname, str)):
         output.warn("Event name "+str(eventname)+" is not  a string",
                     self.__class__.__name__)
         return
     #Register handler
     if (eventname not in self._processors):
         self._processors[eventname] = []
     self._processors[eventname].append(handler)
Exemplo n.º 23
0
 def send(self, msg):
     """Send OpenFlow message
     """
     header = pyopenflow.ofp_header()
     if (len(msg) < len(header)):
         output.warn("Cannot send OpenFlow of length "+str(len(msg)))
     else:
         remain = header.unpack(msg)
         header.length = len(msg)
         output.vdbg("Send message "+header.show().strip().replace("\n",";"),
                     self.__class__.__name__)
         try:
             self.sock.send(header.pack()+remain)
         except socket.error:
             output.warn("Broken pipe, message not sent",
                         self.__class__.__name__)
Exemplo n.º 24
0
    def update_sw_feature(self):
        """Update switch feature in memcache
        """
        sf = self.switch.get_sw_feature()
        if sf == None:
            output.warn("No switch features!!!", self.__class__.__name__)
        else:
            output.dbg("Set switch feature as " + sf.show(), self.__class__.__name__)
            mc.set(bridge.SW_FEATURE, sf)

        iport = self.switch.if_name2dpid_port_mac(self.loif.switch_intf)[1]
        if iport == None:
            output.warn("No inner port!!!", self.__class__.__name__)
        else:
            output.dbg("Set inner port as " + str(iport), self.__class__.__name__)
            mc.set(bridge.SW_INNER_PORT, iport)
Exemplo n.º 25
0
    def processevent(self, event):
        """Process OpenFlow and JSON messages

        @param event event to handle
        @return True
        """
        if isinstance(event, ofevents.error):
            #OpenFlow error
            output.warn("Error of type "+str(event.error.type)+\
                            " code "+str(event.error.code),
                        self.__class__.__name__)
        elif isinstance(event, jsoncomm.message):
            #JSON messages
            self.__processjson(event)
            
        return True
Exemplo n.º 26
0
    def post_event(self, event, timedelta = 0):
        """Post event

        @param event event to post
        @param timedelta to wait before posting event
        @return if successful
        """
        #Check event is an event
        if (not isinstance(event, yapc.event)):
            output.warn(str(event)+"is not an event",
                        self.__class__.__name__)

        if (timedelta == 0):
            return self.__scheduler.post_event(event)
        else:
            return self.__timedscheduler.post_event(event,
                                                    timedelta+time.time())
Exemplo n.º 27
0
 def parse(self, entry_line):
     """Parse line
     """
     i = entry_line.split()
     if (len(i) != 8):
         output.warn("Route entry line should have 8 items but "+str(len(i))+" found",
                     self.__class__.__name__)
         return
     else:
         self.destination = i[0]
         self.gateway = i[1]
         self.mask = i[2]
         self.flags.parse(i[3])
         self.metric = int(i[4])
         self.ref = int(i[5])
         self.use = int(i[6])
         self.iface = i[7]
Exemplo n.º 28
0
Arquivo: flows.py Projeto: yapkke/yapc
    def set_priority(self, priority):
        """Set priority of flow entry

        Priority can be expressed as number or 
        one of the following string expressed in yapc.openflowutil
       
        @param priority expression of priority
        @return success
        """
        if isinstance(priority, int):
            self.priority = priority
        elif priority in ofutil.PRIORITY:
            self.priority = ofutil.PRIORITY[priority]
        else:
            output.warn("Unknown expression of priority " + str(priority), self.__class__.__name__)
            return False

        return True
Exemplo n.º 29
0
    def post_event(self, event, clock):
        """Post event

        @param event event to post
        @param clock time to post event
        @return success status
        """
        if (clock > (time.time()+self.sleep)):
            self._events.add(event, clock)
            output.vvdbg("Added event "+event.name+" for time "+str(clock),
                         self.__class__.__name__)
            return True
        else:
            output.warn("Cannot add event "+event.name+\
                        " shorter than "+str(self.sleep)+\
                        " before execution time",
                        self.__class__.__name__)
            return False
Exemplo n.º 30
0
    def unpack_actions(self, string, actions=None):
        """Unpack actions

        @param string string with actions encoded
        @param actions list to add actions into
        @return list of actions
        """
        remaining = string
        if (actions == None):
            actions = []

        while (len(remaining) >= pyof.OFP_ACTION_HEADER_BYTES):
            (action, remaining) = self.unpack_action(remaining)
            actions.append(action)
        
        if (len(remaining) > 0):
            output.warn("Action array is of irregular length with "+\
                            str(len(remaining))+" bytes remaining.",
                        self.__class__.__name__)
            
        return actions