def test_6_same_nlri_same_attributes_order_multivalued(self):
        # Two routes with same NLRI but and same attributes should
        # hash to the same values and be equal, *even if* for a said
        # multivalued attributes, like extended community, the values
        # appear in a distinct order

        atts1 = exa.Attributes()
        ecoms1 = exa.ExtendedCommunities()
        ecoms1.communities.append(exa.RouteTarget(64512, 1))
        ecoms1.communities.append(
            exa.Encapsulation(exa.Encapsulation.Type.VXLAN))
        ecoms1.communities.append(exa.RouteTarget(64512, 2))
        atts1.add(ecoms1)

        atts2 = exa.Attributes()
        ecoms2 = exa.ExtendedCommunities()
        ecoms2.communities.append(exa.RouteTarget(64512, 2))
        ecoms2.communities.append(exa.RouteTarget(64512, 1))
        ecoms2.communities.append(
            exa.Encapsulation(exa.Encapsulation.Type.VXLAN))
        atts2.add(ecoms2)

        entry1 = engine.RouteEntry(base.NLRI1, None, atts1)
        entry2 = engine.RouteEntry(base.NLRI1, None, atts2)

        self.assertEqual(hash(entry1), hash(entry2))
        self.assertEqual(entry1, entry2)
    def test_4_same_nlri_distinct_attributes(self):
        # Two routes with same NLRI but distinct attributes should
        # not be equal

        atts1 = exa.Attributes()
        atts1.add(exa.LocalPreference(10))

        atts2 = exa.Attributes()
        atts2.add(exa.LocalPreference(20))

        entry1 = engine.RouteEntry(base.NLRI1, None, atts1)
        entry2 = engine.RouteEntry(base.NLRI1, None, atts2)

        self.assertNotEqual(entry1, entry2)
    def test_5_same_nlri_same_attributes(self):
        # Two routes with same NLRI but and same attributes should
        # hash to the same values and be equal.

        atts1 = exa.Attributes()
        atts1.add(exa.LocalPreference(10))

        atts2 = exa.Attributes()
        atts2.add(exa.LocalPreference(10))

        entry1 = engine.RouteEntry(base.NLRI1, None, atts1)
        entry2 = engine.RouteEntry(base.NLRI1, None, atts2)

        self.assertEqual(hash(entry1), hash(entry2))
        self.assertEqual(entry1, entry2)
    def __init__(self, nlri, rts=None, attributes=None, source=None):
        if attributes is None:
            attributes = exa.Attributes()
        assert isinstance(attributes, exa.Attributes)
        if rts is not None:
            assert isinstance(rts, list)
            assert len(rts) == 0 or isinstance(rts[0], exa.RouteTarget)

        self.source = source
        self.afi = nlri.afi
        self.safi = nlri.safi
        self.nlri = nlri
        self.attributes = attributes
        # a list of exa.bgp.message.update.attribute.community.
        #   extended.RouteTargetASN2Number
        self._route_targets = []
        if exa.Attribute.CODE.EXTENDED_COMMUNITY in self.attributes:
            ecoms = self.attributes[
                exa.Attribute.CODE.EXTENDED_COMMUNITY].communities
            # use type(..) because isinstance(rtrecord, RouteTarget) is True
            self._route_targets = [
                ecom for ecom in ecoms if type(ecom) == exa.RouteTarget
            ]
            if rts:
                ecoms += rts
                self._route_targets += rts
        else:
            if rts:
                self.attributes.add(exa.ExtendedCommunities(rts))
                self._route_targets += rts
Beispiel #5
0
    def _new_route_event(self, event_type, nlri, rts, source, nh, lp=0,
                         replaced_route_entry=None,
                         afi=exa.AFI(exa.AFI.ipv4),
                         safi=exa.SAFI(exa.SAFI.mpls_vpn),
                         **kwargs):
        attributes = exa.Attributes()
        attributes.add(exa.NextHop(nh))
        attributes.add(exa.LocalPreference(lp))

        if 'rtrecords' in kwargs:
            ecoms = exa.ExtendedCommunities()
            ecoms.communities += kwargs['rtrecords']
            attributes.add(ecoms)

        route_event = engine.RouteEvent(event_type,
                                        engine.RouteEntry(nlri, rts,
                                                          attributes, source),
                                        source)
        route_event.set_replaced_route(replaced_route_entry)

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

        self.event_target_worker._on_event(route_event)

        return route_event
Beispiel #6
0
    def __init__(self, *args, **kwargs):

        vpn_instance.VPNInstance.__init__(self, *args, **kwargs)

        self.gw_port = None

        # Advertise route to receive multi-destination traffic
        self.log.info("Generating BGP route for broadcast/multicast traffic")

        nlri = exa.EVPNMulticast(
            self.instance_rd,
            exa.EthernetTag(),
            exa.IP.create(self.bgp_manager.get_local_address()),
            None,
            exa.IP.create(self.bgp_manager.get_local_address()))

        attributes = exa.Attributes()

        attributes.add(self._gen_encap_extended_communities())

        # add PMSI Tunnel Attribute route
        attributes.add(
            exa.PMSIIngressReplication(self.dp_driver.get_local_address(),
                                       self.instance_label))

        self.multicast_route_entry = engine.RouteEntry(nlri, self.export_rts,
                                                       attributes)

        self._advertise_route(self.multicast_route_entry)
    def test_8_route_entry_set_rts(self):
        atts = exa.Attributes()
        ecoms = exa.ExtendedCommunities()
        ecoms.communities.append(exa.RouteTarget(64512, 1))
        ecoms.communities.append(exa.RouteTarget(64512, 2))
        ecoms.communities.append(
            exa.Encapsulation(exa.Encapsulation.Type.VXLAN))
        atts.add(exa.LocalPreference(20))
        atts.add(ecoms)

        entry = engine.RouteEntry(base.NLRI1, None, atts)

        # check that the route_entry object has the RTs we wanted
        self.assertIn(exa.RouteTarget(64512, 1), entry.route_targets)
        self.assertIn(exa.RouteTarget(64512, 2), entry.route_targets)

        # modify the route targets
        entry.set_route_targets(
            [exa.RouteTarget(64512, 3),
             exa.RouteTarget(64512, 1)])

        # check that the new RTs have replaced the old ones
        self.assertIn(exa.RouteTarget(64512, 1), entry.route_targets)
        self.assertIn(exa.RouteTarget(64512, 3), entry.route_targets)
        self.assertNotIn(exa.RouteTarget(64512, 2), entry.route_targets)

        # also need to check the RTs in the attributes
        ecoms = entry.attributes[
            exa.Attribute.CODE.EXTENDED_COMMUNITY].communities
        self.assertIn(exa.RouteTarget(64512, 1), ecoms)
        self.assertIn(exa.RouteTarget(64512, 3), ecoms)
        self.assertNotIn(exa.RouteTarget(64512, 2), ecoms)

        # check that other communities were preserved
        self.assertIn(exa.Encapsulation(exa.Encapsulation.Type.VXLAN), ecoms)
Beispiel #8
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
Beispiel #9
0
    def _route_for_readvertisement(self, route, label, rd,
                                   lb_consistent_hash_order,
                                   do_default=False):
        prefix = "0.0.0.0/0" if do_default else route.nlri.cidr.prefix()

        nlri = self._nlri_from(prefix, label, rd)

        attributes = exa.Attributes()

        # new RTRecord = original RTRecord (if any) + orig RTs converted into
        # RTRecord attributes
        orig_rtrecords = route.ecoms(exa.RTRecord)
        rts = route.ecoms(exa.RTExtCom)
        add_rtrecords = [exa.RTRecord.from_rt(rt) for rt in rts]

        final_rtrecords = list(set(orig_rtrecords) | set(add_rtrecords))

        ecoms = self._gen_encap_extended_communities()
        ecoms.communities += final_rtrecords
        ecoms.communities.append(
            exa.ConsistentHashSortOrder(lb_consistent_hash_order))
        attributes.add(ecoms)

        entry = engine.RouteEntry(nlri, self.readvertise_to_rts, attributes)
        self.log.debug("RouteEntry for (re-)advertisement: %s", entry)
        return entry
    def test_10_ecoms(self):
        ecoms1 = exa.ExtendedCommunities()
        ecoms1.communities.append(
            exa.Encapsulation(exa.Encapsulation.Type.VXLAN))
        atts1 = exa.Attributes()
        atts1.add(ecoms1)

        ecoms2 = exa.ExtendedCommunities()
        ecoms2.communities.append(
            exa.Encapsulation(exa.Encapsulation.Type.VXLAN))
        ecoms2.communities.append(exa.RouteTarget(64512, 1))
        atts2 = exa.Attributes()
        atts2.add(ecoms2)

        self.assertFalse(atts1.sameValuesAs(atts2))
        self.assertFalse(atts2.sameValuesAs(atts1))
    def __init__(self, re, keep_attributes=None):
        if keep_attributes is None:
            keep_attributes = keep_attributes_default

        attributes = exa.Attributes()
        for (attribute_id, attribute) in re.attributes.items():
            if attribute_id in keep_attributes:
                attributes.add(attribute)

        super(FilteredRoute, self).__init__(re.nlri, None, attributes)
    def __init__(self, re, keep_attributes=None):
        if keep_attributes is None:
            keep_attributes = keep_attributes_default

        attributes = exa.Attributes()
        for (attribute_id, attribute) in re.attributes.items():
            if attribute_id in keep_attributes:
                attributes.add(attribute)

        engine.RouteEntry.__init__(self, re.nlri, None, attributes)
    def _default_route_for_advertisement(self, endpoint):
        label, rd, lb_consistent_hash_order = (
            self._get_route_params_for_endpoint(endpoint))
        self.log.debug(
            "Default route (re-)advertisement with label %s and "
            "route distinguisher %s", label, rd)
        nlri = self._nlri_from(DEFAULT_ADDR_PREFIX, label, rd)

        attributes = exa.Attributes()

        ecoms = self._gen_encap_extended_communities()
        ecoms.communities.append(
            exa.ConsistentHashSortOrder(lb_consistent_hash_order))
        attributes.add(ecoms)

        entry = engine.RouteEntry(nlri, self.readvertise_to_rts, attributes)
        self.log.debug("RouteEntry for default prefix advertisement: %s",
                       entry)
        return entry
    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
    def _route_for_readvertisement(self, route, endpoint):
        label, rd, lb_consistent_hash_order = (
            self._get_route_params_for_endpoint(endpoint))
        self.log.debug(
            "Prefix %s (re-)advertisement with label %s and route "
            "distinguisher %s", route.nlri.cidr.prefix(), label, rd)
        nlri = self._nlri_from(route.nlri.cidr.prefix(), label, rd)

        attributes = exa.Attributes()

        ecoms = self._gen_encap_extended_communities()
        ecoms.communities += (self._gen_rtrecords_extended_community(
            route.ecoms))
        ecoms.communities.append(
            exa.ConsistentHashSortOrder(lb_consistent_hash_order))
        attributes.add(ecoms)

        entry = engine.RouteEntry(nlri, self.readvertise_to_rts, attributes)
        self.log.debug("RouteEntry for (re-)advertisement: %s", entry)
        return entry
    def test_9_route_entry_rts_as_init_param(self):
        atts = exa.Attributes()
        ecoms = exa.ExtendedCommunities()
        ecoms.communities.append(
            exa.Encapsulation(exa.Encapsulation.Type.VXLAN))
        atts.add(exa.LocalPreference(20))
        atts.add(ecoms)

        rts = [exa.RouteTarget(64512, 1), exa.RouteTarget(64512, 2)]

        entry = engine.RouteEntry(base.NLRI1, rts, atts)

        self.assertIn(exa.RouteTarget(64512, 1), entry.route_targets)
        self.assertIn(exa.RouteTarget(64512, 2), entry.route_targets)

        ecoms = entry.attributes[
            exa.Attribute.CODE.EXTENDED_COMMUNITY].communities
        self.assertIn(exa.RouteTarget(64512, 1), ecoms)
        self.assertIn(exa.RouteTarget(64512, 2), ecoms)
        self.assertIn(exa.Encapsulation(exa.Encapsulation.Type.VXLAN), ecoms)
Beispiel #17
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
Beispiel #18
0
    def __init__(self, *args, **kwargs):

        vpn_instance.VPNInstance.__init__(self, *args, **kwargs)

        self.gw_port = None

        encaps = self.dp_driver.supported_encaps()
        if (exa.Encapsulation(exa.Encapsulation.Type.VXLAN) in encaps
                and any([
                exa.Encapsulation(exa.Encapsulation.Type.MPLS) in encaps,
                exa.Encapsulation(exa.Encapsulation.Type.GRE) in encaps,
                exa.Encapsulation(exa.Encapsulation.Type.MPLS_UDP) in encaps
                ])):
            raise Exception("The dataplane can't support both an MPLS encap "
                            "and a VXLAN encapsulation")

        # Advertise route to receive multi-destination traffic
        self.log.info("Generating BGP route for broadcast/multicast traffic")

        nlri = exa.EVPNMulticast(
            self.instance_rd,
            exa.EthernetTag(),
            exa.IP.create(self.bgp_manager.get_local_address()),
            None,
            exa.IP.create(self.bgp_manager.get_local_address()))

        attributes = exa.Attributes()

        attributes.add(self._gen_encap_extended_communities())

        # add PMSI Tunnel Attribute route
        attributes.add(
            exa.PMSIIngressReplication(self.dp_driver.get_local_address(),
                                       raw_label=self.instance_label))

        self.multicast_route_entry = engine.RouteEntry(nlri, self.export_rts,
                                                       attributes)

        self._advertise_route(self.multicast_route_entry)
Beispiel #19
0
    def test_f1_test_empty_rt(self):
        # worker advertises a route with no RT

        w1 = self._new_worker("Worker1", worker.Worker)

        subscribe = engine.Subscription(exa.AFI(exa.AFI.ipv4),
                                        exa.SAFI(exa.SAFI.mpls_vpn), None, w1)
        self.rtm.enqueue(subscribe)

        w2 = self._new_worker("Worker2", worker.Worker)

        route_event = engine.RouteEvent(
            engine.RouteEvent.ADVERTISE,
            engine.RouteEntry(t.NLRI1, None, exa.Attributes()), w2)

        self.rtm.enqueue(route_event)

        self._wait()

        self.assertEqual(
            1, w1.enqueue.call_count,
            "1 route advertised should be synthesized to Worker1")