Esempio n. 1
0
    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")