def __init__(self, dpid): if not dpid: raise AssertionError("OpenFlowSwitch should have dpid") Switch.__init__(self, id=dpid) EventMixin.__init__(self) self.dpid = dpid self.ports = {} self.flow_table = NOMFlowTable(self) self.capabilities = 0 self._connection = None self._listeners = [] self._reconnectTimeout = None # Timer for reconnection self.xid_generator = xid_generator(((dpid & 0x7FFF) << 16) + 1)
def __init__ (self, dpid=None, **kw): Switch.__init__(self)#, id=dpid) EventMixin.__init__(self) self.dpid = dpid #self.ports = {} self.flow_table = NOMFlowTable(self) self.capabilities = 0 self._connection = None self._listeners = [] self._reconnectTimeout = None # Timer for reconnection self._xid_generator = xid_generator( ((self.dpid & 0x7FFF) << 16) + 1)
def __init__ (self, dpid): if not dpid: raise AssertionError("OpenFlowSwitch should have dpid") Switch.__init__(self, id=dpid) EventMixin.__init__(self) self.dpid = dpid self.ports = {} self.flow_table = NOMFlowTable(self) self.capabilities = 0 self._connection = None self._listeners = [] self._reconnectTimeout = None # Timer for reconnection self.xid_generator = xid_generator( ((dpid & 0x7FFF) << 16) + 1)
class OpenFlowSwitch (EventMixin, Switch): """ OpenFlowSwitches are Topology entities (inheriting from topology.Switch) OpenFlowSwitches are persistent; that is, if a switch reconnects, the Connection field of the original OpenFlowSwitch object will simply be reset to refer to the new connection. For now, OpenFlowSwitch is primarily a proxy to its underlying connection object. Later, we'll possibly add more explicit operations the client can perform. Note that for the purposes of the debugger, we can interpose on a switch entity by enumerating all listeners for the events listed below, and triggering mock events for those listeners. """ _eventMixin_events = set([ SwitchJoin, # Defined in pox.topology SwitchLeave, SwitchConnectionUp, SwitchConnectionDown, PortStatus, # Defined in libopenflow_01 FlowRemoved, PacketIn, BarrierIn, ]) def __init__ (self, dpid): if not dpid: raise AssertionError("OpenFlowSwitch should have dpid") Switch.__init__(self, id=dpid) EventMixin.__init__(self) self.dpid = dpid self.ports = {} self.flow_table = NOMFlowTable(self) self.capabilities = 0 self._connection = None self._listeners = [] self._reconnectTimeout = None # Timer for reconnection self.xid_generator = xid_generator( ((dpid & 0x7FFF) << 16) + 1) def _setConnection (self, connection, ofp=None): ''' ofp - a FeaturesReply message ''' if self._connection: self._connection.removeListeners(self._listeners) self._listeners = [] self._connection = connection if self._reconnectTimeout is not None: self._reconnectTimeout.cancel() self._reconnectTimeout = None if connection is None: self._reconnectTimeout = Timer(RECONNECT_TIMEOUT, self._timer_ReconnectTimeout) if ofp is not None: # update capabilities self.capabilities = ofp.capabilities # update all ports untouched = set(self.ports.keys()) for p in ofp.ports: if p.port_no in self.ports: self.ports[p.port_no]._update(p) untouched.remove(p.port_no) else: self.ports[p.port_no] = OpenFlowPort(p) for p in untouched: self.ports[p].exists = False del self.ports[p] if connection is not None: self._listeners = self.listenTo(connection, prefix="con") self.raiseEvent(SwitchConnectionUp(switch=self, connection = connection)) else: self.raiseEvent(SwitchConnectionDown(switch=self)) def _timer_ReconnectTimeout (self): """ Called if we've been disconnected for RECONNECT_TIMEOUT seconds """ self._reconnectTimeout = None core.topology.removeEntity(self) self.raiseEvent(SwitchLeave, self) def _handle_con_PortStatus (self, event): p = event.ofp.desc if event.ofp.reason == of.OFPPR_DELETE: if p.port_no in self.ports: self.ports[p.port_no].exists = False del self.ports[p.port_no] elif event.ofp.reason == of.OFPPR_MODIFY: self.ports[p.port_no]._update(p) else: assert event.ofp.reason == of.OFPPR_ADD assert p.port_no not in self.ports self.ports[p.port_no] = OpenFlowPort(p) self.raiseEvent(event) event.halt = False def _handle_con_ConnectionDown (self, event): self._setConnection(None) def _handle_con_PacketIn (self, event): self.raiseEvent(event) event.halt = False def _handle_con_BarrierIn (self, event): self.raiseEvent(event) event.halt = False def _handle_con_FlowRemoved (self, event): self.raiseEvent(event) self.flowTable.removeFlow(event) event.halt = False def findPortForEntity (self, entity): for p in self.ports.itervalues(): if entity in p: return p return None @property def connected(self): return self._connection != None def installFlow(self, **kw): """ install a flow in the local flow table as well as into the associated switch """ self.flow_table.install(TableEntry(**kw)) def serialize (self): # Skip over non-serializable data, e.g. sockets serializable = OpenFlowSwitch(self.dpid) return pickle.dumps(serializable, protocol = 0) def send(self, *args, **kw): return self._connection.send(*args, **kw) def read(self, *args, **kw): return self._connection.read(*args, **kw) def __repr__ (self): return "<%s %s>" % (self.__class__.__name__, dpidToStr(self.dpid)) @property def name(self): return repr(self)
class OpenFlowSwitch(EventMixin, Switch): """ OpenFlowSwitches are Topology entities (inheriting from topology.Switch) OpenFlowSwitches are persistent; that is, if a switch reconnects, the Connection field of the original OpenFlowSwitch object will simply be reset to refer to the new connection. For now, OpenFlowSwitch is primarily a proxy to its underlying connection object. Later, we'll possibly add more explicit operations the client can perform. Note that for the purposes of the debugger, we can interpose on a switch entity by enumerating all listeners for the events listed below, and triggering mock events for those listeners. """ _eventMixin_events = set([ SwitchJoin, # Defined in pox.topology SwitchLeave, SwitchConnectionUp, SwitchConnectionDown, PortStatus, # Defined in libopenflow_01 FlowRemoved, PacketIn, BarrierIn, ]) def __init__(self, dpid): if not dpid: raise AssertionError("OpenFlowSwitch should have dpid") Switch.__init__(self, id=dpid) EventMixin.__init__(self) self.dpid = dpid self.ports = {} self.flow_table = NOMFlowTable(self) self.capabilities = 0 self._connection = None self._listeners = [] self._reconnectTimeout = None # Timer for reconnection self.xid_generator = xid_generator(((dpid & 0x7FFF) << 16) + 1) def _setConnection(self, connection, ofp=None): ''' ofp - a FeaturesReply message ''' if self._connection: self._connection.removeListeners(self._listeners) self._listeners = [] self._connection = connection if self._reconnectTimeout is not None: self._reconnectTimeout.cancel() self._reconnectTimeout = None if connection is None: self._reconnectTimeout = Timer(RECONNECT_TIMEOUT, self._timer_ReconnectTimeout) if ofp is not None: # update capabilities self.capabilities = ofp.capabilities # update all ports untouched = set(self.ports.keys()) for p in ofp.ports: if p.port_no in self.ports: self.ports[p.port_no]._update(p) untouched.remove(p.port_no) else: self.ports[p.port_no] = OpenFlowPort(p) for p in untouched: self.ports[p].exists = False del self.ports[p] if connection is not None: self._listeners = self.listenTo(connection, prefix="con") self.raiseEvent( SwitchConnectionUp(switch=self, connection=connection)) else: self.raiseEvent(SwitchConnectionDown(switch=self)) def _timer_ReconnectTimeout(self): """ Called if we've been disconnected for RECONNECT_TIMEOUT seconds """ self._reconnectTimeout = None core.topology.removeEntity(self) self.raiseEvent(SwitchLeave, self) def _handle_con_PortStatus(self, event): p = event.ofp.desc if event.ofp.reason == of.OFPPR_DELETE: if p.port_no in self.ports: self.ports[p.port_no].exists = False del self.ports[p.port_no] elif event.ofp.reason == of.OFPPR_MODIFY: self.ports[p.port_no]._update(p) else: assert event.ofp.reason == of.OFPPR_ADD assert p.port_no not in self.ports self.ports[p.port_no] = OpenFlowPort(p) self.raiseEvent(event) event.halt = False def _handle_con_ConnectionDown(self, event): self._setConnection(None) def _handle_con_PacketIn(self, event): self.raiseEvent(event) event.halt = False def _handle_con_BarrierIn(self, event): self.raiseEvent(event) event.halt = False def _handle_con_FlowRemoved(self, event): self.raiseEvent(event) self.flowTable.removeFlow(event) event.halt = False def findPortForEntity(self, entity): for p in self.ports.itervalues(): if entity in p: return p return None @property def connected(self): return self._connection != None def installFlow(self, **kw): """ install a flow in the local flow table as well as into the associated switch """ self.flow_table.install(TableEntry(**kw)) def serialize(self): # Skip over non-serializable data, e.g. sockets serializable = OpenFlowSwitch(self.dpid) return pickle.dumps(serializable, protocol=0) def send(self, *args, **kw): return self._connection.send(*args, **kw) def read(self, *args, **kw): return self._connection.read(*args, **kw) def __repr__(self): return "<%s %s>" % (self.__class__.__name__, dpidToStr(self.dpid)) @property def name(self): return repr(self)