def openReceived(self): """Should be called when a BGP Open message was received from the peer. (events 19, 20) """ if self.state in (ST_CONNECT, ST_ACTIVE): if self.delayOpenTimer.active(): # State Connect, event 20 self.connectRetryTimer.cancel() if self.bgpPeering: self.bgpPeering.completeInit(self.protocol) self.delayOpenTimer.cancel() self.protocol.sendOpen() self.protocol.sendKeepAlive() if self.holdTime != 0: self.keepAliveTimer.reset(self.keepAliveTime) self.holdTimer.reset(self.holdTime) else: # holdTime == 0 self.keepAliveTimer.cancel() self.holdTimer.cancel() self.state = ST_OPENCONFIRM else: # State Connect, event 19 self._errorClose() elif self.state == ST_OPENSENT: if not self.delayOpen: # State OpenSent, event 19 self.delayOpenTimer.cancel() self.connectRetryTimer.cancel() self.protocol.sendKeepAlive() if self.holdTime > 0: self.keepAliveTimer.reset(self.keepAliveTime) self.holdTimer.reset(self.holdTime) self.state = ST_OPENCONFIRM else: # State OpenSent, event 20 self.protocol.sendNotification(ERR_FSM, 0) self._errorClose() raise NotificationSent(self.protocol, ERR_FSM, 0) elif self.state == ST_OPENCONFIRM: if not self.delayOpen: # State OpenConfirm, events 19 self.log("Running collision detection") # Perform collision detection self.protocol.collisionDetect() else: # State OpenConfirm, event 20 self.protocol.sendNotification(ERR_FSM, 0) self._errorClose() raise NotificationSent(self.protocol, ERR_FSM, 0) elif self.state == ST_ESTABLISHED: # State Established, event 19 or 20 self.protocol.sendNotification(ERR_FSM, 0) self._errorClose() raise NotificationSent(self.protocol, ERR_FSM, 0)
def delayOpenEvent(self): """Called when the DelayOpenTimer expires. (event 12)""" assert (self.delayOpen) self.log("Delay Open event") if self.state == ST_CONNECT: # State Connect, event 12 self.protocol.sendOpen() self.holdTimer.reset(self.largeHoldTime) self.state = ST_OPENSENT elif self.state == ST_ACTIVE: # State Active, event 12 self.connectRetryTimer.cancel() self.delayOpenTimer.cancel() if self.bgpPeering: self.bgpPeering.completeInit(self.protocol) self.protocol.sendOpen() self.holdTimer.reset(self.largeHoldTime) self.state = ST_OPENSENT elif self.state != ST_IDLE: # State OpenSent, OpenConfirm, Established, event 12 self.protocol.sendNotification(ERR_FSM, 0) self._errorClose() raise NotificationSent(self.protocol, ERR_FSM, 0)
def updateError(self, suberror, data=''): """Called when an invalid BGP Update message was received. (event 28)""" if self.state == ST_ESTABLISHED: # State Established, event 28 self.protocol.sendNotification(ERR_MSG_UPDATE, suberror, data) self._errorClose() raise NotificationSent(self.protocol, ERR_MSG_UPDATE, suberror, data) elif self.state in (ST_ACTIVE, ST_CONNECT): # States Active, Connect, event 28 self._errorClose() elif self.state in (ST_OPENSENT, ST_OPENCONFIRM): # States OpenSent, OpenConfirm, event 28 self.protocol.sendNotification(ERR_FSM, 0) self._errorClose() raise NotificationSent(self.protocol, ERR_FSM, 0)
def openMessageError(self, suberror, data=''): """ Should be called when an invalid BGP Open message was received. (event 22) """ if self.state != ST_IDLE: self.protocol.sendNotification(ERR_MSG_OPEN, suberror, data) # Note: RFC4271 states that we should send ERR_FSM in the # Established state, which contradicts earlier statements. self._errorClose() raise NotificationSent(self.protocol, ERR_MSG_OPEN, suberror, data)
def idleHoldTimeEvent(self): """Called when the IdleHoldTimer expires. (event 13)""" if self.state == ST_IDLE: if self.bgpPeering: self.bgpPeering.automaticStart(idleHold=False) else: fsmError = False if self.state in (ST_OPENSENT, ST_OPENCONFIRM, ST_ESTABLISHED): fsmError = True self.protocol.sendNotification(ERR_FSM, 0) self._errorClose() if fsmError: raise NotificationSent(self.protocol, ERR_FSM, 0)
def keepAliveEvent(self): """Called when the KeepAliveTimer expires. (event 11)""" if self.state in (ST_OPENCONFIRM, ST_ESTABLISHED): # State OpenConfirm, Established, event 11 self.protocol.sendKeepAlive() if self.holdTime > 0: self.keepAliveTimer.reset(self.keepAliveTime) elif self.state in (ST_CONNECT, ST_ACTIVE): self._errorClose() elif self.state == ST_OPENSENT: self.protocol.sendNotification(ERR_FSM, 0) self._errorClose() raise NotificationSent(self.protocol, ERR_FSM, 0)
def openCollisionDump(self): """ Called when the collision detection algorithm determined that the associated connection should be dumped. (event 23) """ self.log("Collided, closing") if self.state == ST_IDLE: return elif self.state in (ST_OPENSENT, ST_OPENCONFIRM, ST_ESTABLISHED): self.protocol.sendNotification(ERR_CEASE, 0) self._errorClose() raise NotificationSent(self.protocol, ERR_CEASE, 0)
def manualStop(self): """Should be called when a BGP ManualStop event (event 2) is requested.""" if self.state != ST_IDLE: self.protocol.sendNotification(ERR_CEASE, 0) # Stop all timers for timer in (self.connectRetryTimer, self.holdTimer, self.keepAliveTimer, self.delayOpenTimer, self.idleHoldTimer): timer.cancel() if self.bgpPeering is not None: self.bgpPeering.releaseResources(self.protocol) self._closeConnection() self.connectRetryCounter = 0 self.state = ST_IDLE raise NotificationSent(self.protocol, ERR_CEASE, 0)
def updateReceived(self, update): """Called when a valid BGP Update message was received. (event 27)""" if self.state == ST_ESTABLISHED: # State Established, event 27 if self.holdTime != 0: self.holdTimer.reset(self.holdTime) self.bgpPeering.update(update) elif self.state in (ST_ACTIVE, ST_CONNECT): # States Active, Connect, event 27 self._errorClose() elif self.state in (ST_OPENSENT, ST_OPENCONFIRM): # States OpenSent, OpenConfirm, event 27 self.protocol.sendNotification(ERR_FSM, 0) self._errorClose() raise NotificationSent(self.protocol, ERR_FSM, 0)
def keepAliveReceived(self): """ Should be called when a BGP KeepAlive packet was received from the peer. (event 26) """ if self.state == ST_OPENCONFIRM: # State OpenSent, event 26 self.holdTimer.reset(self.holdTime) self.state = ST_ESTABLISHED self.protocol.deferred.callback(self.protocol) elif self.state == ST_ESTABLISHED: # State Established, event 26 self.holdTimer.reset(self.holdTime) elif self.state in (ST_CONNECT, ST_ACTIVE): # States Connect, Active, event 26 self._errorClose() elif self.state == ST_OPENSENT: # State OpenSent, event 26 self.protocol.sendNotification(ERR_FSM, 0) self._errorClose() raise NotificationSent(self.protocol, ERR_FSM, 0)
def connectRetryTimeEvent(self): """Called when the ConnectRetryTimer expires. (event 9)""" if self.state == ST_CONNECT: # State Connect, event 9 self._closeConnection() self.connectRetryTimer.reset(self.connectRetryTime) self.delayOpenTimer.cancel() # Initiate TCP connection if self.bgpPeering: self.bgpPeering.connectRetryEvent(self.protocol) elif self.state == ST_ACTIVE: # State Active, event 9 self.connectRetryTimer.reset(self.connectRetryTime) # Initiate TCP connection if self.bgpPeering: self.bgpPeering.connectRetryEvent(self.protocol) self.state = ST_CONNECT elif self.state != ST_IDLE: # State OpenSent, OpenConfirm, Established, event 12 self.protocol.sendNotification(ERR_FSM, 0) self._errorClose() raise NotificationSent(self.protocol, ERR_FSM, 0)