def __init__ (self, sock): self._previous_stats = [] self.ofnexus = _dummyOFNexus self.sock = sock self._sock_lock = threading.Lock() self._delayed_action = DelayedAction() self.buf = '' Connection.ID += 1 self.ID = Connection.ID # TODO: dpid and features don't belong here; they should be eventually # be in topology.switch self.dpid = None self.features = None self.disconnected = False self.connect_time = None self.send(of.ofp_hello())
class Connection (EventMixin): """ A Connection object represents a single TCP session with an openflow-enabled switch. If the switch reconnects, a new connection object is instantiated. """ _eventMixin_events = set([ ConnectionUp, ConnectionDown, PortStatus, FlowRemoved, PacketIn, ErrorIn, BarrierIn, RawStatsReply, SwitchDescReceived, FlowStatsReceived, AggregateFlowStatsReceived, TableStatsReceived, PortStatsReceived, QueueStatsReceived, FlowRemoved, ]) # Globally unique identifier for the Connection instance ID = 0 def msg (self, m): #print str(self), m log.debug(str(self) + " " + str(m)) def err (self, m): #print str(self), m log.error(str(self) + " " + str(m)) def info (self, m): pass #print str(self), m log.info(str(self) + " " + str(m)) def __init__ (self, sock): self._previous_stats = [] self.ofnexus = _dummyOFNexus self.sock = sock self._sock_lock = threading.Lock() self._delayed_action = DelayedAction() self.buf = '' Connection.ID += 1 self.ID = Connection.ID # TODO: dpid and features don't belong here; they should be eventually # be in topology.switch self.dpid = None self.features = None self.disconnected = False self.connect_time = None self.send(of.ofp_hello()) #TODO: set a time that makes sure we actually establish a connection by # some timeout def fileno (self): return self.sock.fileno() def close (self): if not self.disconnected: self.info("closing connection") else: #self.msg("closing connection") pass try: with self._sock_lock: self.sock.shutdown(socket.SHUT_RDWR) except: pass try: with self._sock_lock: self.sock.close() except: pass def disconnect (self): """ disconnect this Connection (usually not invoked manually). """ if self.disconnected: self.err("already disconnected!") self.msg("disconnecting") self.disconnected = True try: self.ofnexus._disconnect(self.dpid) except: pass """ try: if self.dpid != None: self.ofnexus.raiseEvent(ConnectionDown(self)) except: self.err("ConnectionDown event caused exception") """ if self.dpid != None: self.ofnexus.raiseEventNoErrors(ConnectionDown(self)) try: #deferredSender.kill(self) pass except: pass try: with self._sock_lock: self.sock.shutdown(socket.SHUT_RDWR) except: pass try: pass #TODO disconnect notification except: pass def send (self, data): """ Send raw data to the switch. Generally, data is a bytes object. If not, we check if it has a pack() method and call it (hoping the result will be a bytes object). This way, you can just pass one of the OpenFlow objects from the OpenFlow library to it and get the expected result, for example. """ if self.disconnected: return data_bytes = data if type(data) is not bytes: if hasattr(data, 'pack'): data_bytes = data.pack() self._delayed_action.add_job(data, self._delayed_send, data_bytes) def _delayed_send(self, data): if deferredSender.sending: log.debug("deferred sender is sending!") deferredSender.send(self, data) return try: with self._sock_lock: l = self.sock.send(data) if l != len(data): self.msg("Didn't send complete buffer.") data = data[l:] deferredSender.send(self, data) except socket.error as (errno, strerror): if errno == EAGAIN: self.msg("Out of send buffer space. " + "Consider increasing SO_SNDBUF.") deferredSender.send(self, data) else: self.msg("Socket error: " + strerror) self.disconnect()