def connect(self): # allows to test the protocol code using modified StringIO with a extra 'pending' function if not self.connection: peer = self.neighbor.peer_address local = self.neighbor.local_address md5 = self.neighbor.md5 ttl = self.neighbor.ttl self.connection = Connection(peer, local, md5, ttl) message = 'neighbor %s connected\n' % self.peer.neighbor.peer_address try: proc = self.peer.supervisor.processes for name in proc.notify(self.neighbor.peer_address): proc.write(name, message) except ProcessError: raise Failure( 'Could not send message(s) to helper program(s) : %s' % message)
def _initiateConnection(self): self.log.debug("Initiate ExaBGP connection to %s from %s", self.peerAddress, self.localAddress) self.rtc_active = False neighbor = Neighbor() neighbor.router_id = RouterID(self.config['local_address']) neighbor.local_as = self.config['my_as'] neighbor.peer_as = self.config['peer_as'] neighbor.local_address = self.config['local_address'] neighbor.peer_address = self.peerAddress neighbor.parse_routes = True # create dummy objects to fake exabgp into talking with us peer = FakePeer(neighbor) local = FakeLocal(self.localAddress) try: self.connection = Connection(peer, local, None, None) except Failure as e: raise InitiateConnectionException(repr(e)) self.log.debug("Instantiate ExaBGP Protocol") self.protocol = MyBGPProtocol(peer, self.connection) self.protocol.connect() # this is highly similar to exabgp.network.peer._run o = self.protocol.new_open(False, False, self.config, ExaBGPPeerWorker.enabledFamilies) self.log.debug("Send open: [%s]", o) self.fsm.state = FSM.OpenSent count = 0 self.log.debug("Wait for open...") while not self.shouldStop: # FIXME: we should time-out here, at some point message = self.protocol.read_open(o, None) count += 1 if isinstance(message, NOP): # TODO(tmmorin): check compliance with BGP specs... if count > 20: self.connection.close() # FIXME: this should be moved to # BGPPeerWorker in a more generic way # (+ send Notify when needed) raise OpenWaitTimeout("%ds" % int(20 * 0.5)) sleep(0.5) continue self.log.debug("Read message: %s", message) if isinstance(message, Open): break else: self.log.error("Received unexpected message: %s", message) # FIXME if self.shouldStop: raise StoppedException() # An Open was received received_open = message self._setHoldTime(received_open.hold_time) # Hack to ease troubleshooting, have the real peer address appear in # the logs when fakerr is used if received_open.router_id.ip != self.peerAddress: self.log.info( "changing thread name from %s to BGP-x%s, based on" " the router-id advertized in Open (different from" " peerAddress == %s)", self.name, received_open.router_id.ip, self.peerAddress) self.name = "BGP-%s:%s" % (self.peerAddress, received_open.router_id.ip) try: mp_capabilities = received_open.capabilities[ Capabilities.MULTIPROTOCOL_EXTENSIONS] except Exception: mp_capabilities = [] # check that our peer advertized at least mpls_vpn and evpn # capabilities self._activeFamilies = [] for (afi, safi) in (ExaBGPPeerWorker.enabledFamilies + [(AFI(AFI.ipv4), SAFI(SAFI.rtc))]): if (afi, safi) not in mp_capabilities: self.log.warning("Peer does not advertise (%s,%s) capability", afi, safi) else: self.log.info( "Family (%s,%s) successfully negotiated with peer %s", afi, safi, self.peerAddress) self._activeFamilies.append((afi, safi)) if len(self._activeFamilies) == 0: self.log.error("No family was negotiated for VPN routes") # proceed BGP session self.connection.io.setblocking(1) self.enqueue(SendKeepAlive) self.fsm.state = FSM.OpenConfirm self.rtc_active = False if self.config['enable_rtc']: if (AFI(AFI.ipv4), SAFI(SAFI.rtc)) in mp_capabilities: self.log.info("RTC successfully enabled with peer %s", self.peerAddress) self.rtc_active = True else: self.log.warning( "enable_rtc True but peer not configured for RTC")