示例#1
0
    def _new_flow_event(self, event_type, nlri, to_rts, attract_rts, source,
                        afi=exa.AFI(exa.AFI.ipv4),
                        safi=exa.SAFI(exa.SAFI.flow_vpn),
                        **kwargs):
        attributes = exa.Attributes()

        ecommunities = exa.ExtendedCommunities()
        ecommunities.communities.append(
            exa.TrafficRedirect(exa.ASN(int(to_rts[0].asn)),
                                int(to_rts[0].number))
        )

        attributes.add(ecommunities)

        flow_event = engine.RouteEvent(event_type,
                                       engine.RouteEntry(nlri, attract_rts,
                                                         attributes, source),
                                       source)

        self.event_target_worker.enqueue(flow_event)

        LOG.info("*** Emitting FlowSpec event to %s: %s",
                 self.event_target_worker, flow_event)

        self._wait()

        return flow_event
    def _redirect_route_for_readvertisement(self, route):
        # Create a FlowSpec NLRI with distinct RD and a copy of rules from
        # FlowSpec route to readvertise
        nlri = flowspec.FlowRouteFactory(self.afi, self.instance_rd)
        nlri.rules = route.nlri.rules

        attributes = exa.Attributes()

        ecoms = exa.ExtendedCommunities()
        ecoms.communities += (self._gen_rtrecords_extended_community(
            route.ecoms))
        assert len(self.attract_rts) == 1
        rt = self.attract_rts[0]
        ecoms.communities.append(
            exa.TrafficRedirect(exa.ASN(int(rt.asn)), int(rt.number)))
        attributes.add(ecoms)

        entry = engine.RouteEntry(nlri, self.readvertise_to_rts, attributes)
        self.log.debug("RouteEntry for redirect (re-)advertisement: %s", entry)
        return entry
示例#3
0
    def _new_flow_event(self, event_type, nlri, to_rts, attract_rts, source,
                        afi=exa.AFI(exa.AFI.ipv4),
                        safi=exa.SAFI(exa.SAFI.flow_vpn),
                        **kwargs):
        attributes = exa.Attributes()

        ecommunities = exa.ExtendedCommunities()
        ecommunities.communities.append(
            exa.TrafficRedirect(exa.ASN(int(to_rts[0].asn)),
                                int(to_rts[0].number))
        )

        attributes.add(ecommunities)

        flow_event = engine.RouteEvent(event_type,
                                       engine.RouteEntry(nlri, attract_rts,
                                                         attributes, source),
                                       source)

        self.event_target_worker._on_event(flow_event)

        return flow_event
示例#4
0
    def synthesize_redirect_bgp_route(self, rules):
        self.log.info("synthesize_redirect_bgp_route called for rules %s",
                      rules)
        nlri = flowspec.FlowRouteFactory(self.afi, self.instance_rd)
        for rule in rules:
            nlri.add(rule)

        route_entry = engine.RouteEntry(nlri)

        assert isinstance(route_entry, engine.RouteEntry)

        ecommunities = exa.ExtendedCommunities()

        # checked at __init__:
        assert len(self.readvertise_to_rts) == 1
        rt = self.readvertise_to_rts[0]
        ecommunities.communities.append(
            exa.TrafficRedirect(exa.ASN(int(rt.asn)), int(rt.number)))

        route_entry.attributes.add(ecommunities)
        route_entry.set_route_targets(self.attract_rts)

        self.log.debug("Synthesized redirect route entry: %s", route_entry)
        return route_entry
    def _initiate_connection(self):
        self.log.debug("Initiate ExaBGP connection to %s:%s from %s",
                       self.peer_address, cfg.CONF.BGP.bgp_port,
                       self.local_address)

        self.rtc_active = False

        neighbor = exa_neighbor.Neighbor()
        neighbor.make_rib()
        neighbor.router_id = exa_open.RouterID(self.local_address)
        neighbor.local_as = exa.ASN(cfg.CONF.BGP.my_as)
        # no support for eBGP yet:
        neighbor.peer_as = exa.ASN(cfg.CONF.BGP.my_as)
        neighbor.local_address = exa.IP.create(self.local_address)
        neighbor.md5_ip = exa.IP.create(self.local_address)
        neighbor.peer_address = exa.IP.create(self.peer_address)
        neighbor.hold_time = exa_open.HoldTime(
            bgp_peer_worker.DEFAULT_HOLDTIME)
        neighbor.connect = cfg.CONF.BGP.bgp_port
        neighbor.api = collections.defaultdict(list)

        for afi_safi in self.enabled_families:
            neighbor.add_family(afi_safi)

        if cfg.CONF.BGP.enable_rtc:
            neighbor.add_family(
                (exa.AFI(exa.AFI.ipv4), exa.SAFI(exa.SAFI.rtc)))

        self.log.debug("Instantiate ExaBGP Peer")
        self.peer = exa_peer.Peer(neighbor, None)

        try:
            for action in self.peer._connect():
                self.fsm.state = TRANSLATE_EXABGP_STATE[
                    self.peer._outgoing.fsm.state]

                if action == exa_peer.ACTION.LATER:
                    time.sleep(2)
                elif action == exa_peer.ACTION.NOW:
                    time.sleep(0.1)

                if self.should_stop:
                    self.log.debug("We're closing, raise StoppedException")
                    raise bgp_peer_worker.StoppedException()

                if action == exa_peer.ACTION.CLOSE:
                    self.log.debug("Socket status is CLOSE, "
                                   "raise InitiateConnectionException")
                    raise bgp_peer_worker.InitiateConnectionException(
                        "Socket is closed")
        except exa_peer.Interrupted:
            self.log.debug("Connect was interrupted, "
                           "raise InitiateConnectionException")
            raise bgp_peer_worker.InitiateConnectionException(
                "Connect was interrupted")
        except exa_message.Notify as e:
            self.log.debug("Notify: %s", e)
            if (e.code, e.subcode) == (1, 1):
                raise bgp_peer_worker.OpenWaitTimeout(str(e))
            else:
                raise Exception("Notify received: %s" % e)
        except exa_reactor.network.error.LostConnection as e:
            raise

        # check the capabilities of the session just established...

        self.protocol = self.peer._outgoing.proto

        received_open = self.protocol.negotiated.received_open

        self._set_hold_time(self.protocol.negotiated.holdtime)

        mp_capabilities = received_open.capabilities.get(
            exa_open.capability.Capability.CODE.MULTIPROTOCOL, [])

        # check that our peer advertized at least mpls_vpn and evpn
        # capabilities
        self._active_families = []
        for (afi, safi) in (self.__class__.enabled_families +
                            [(exa.AFI(exa.AFI.ipv4), exa.SAFI(exa.SAFI.rtc))]):
            if (afi, safi) not in mp_capabilities:
                if (((afi, safi) !=
                     (exa.AFI(exa.AFI.ipv4), exa.SAFI(exa.SAFI.rtc)))
                        or cfg.CONF.BGP.enable_rtc):
                    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.peer_address)
                self._active_families.append((afi, safi))

        if len(self._active_families) == 0:
            self.log.error("No family was negotiated for VPN routes")

        self.rtc_active = False

        if cfg.CONF.BGP.enable_rtc:
            if (exa.AFI(exa.AFI.ipv4),
                    exa.SAFI(exa.SAFI.rtc)) in mp_capabilities:
                self.log.info("RTC successfully enabled with peer %s",
                              self.peer_address)
                self.rtc_active = True
            else:
                self.log.warning(
                    "enable_rtc True but peer not configured for RTC")