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_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 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)
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
def synthesize_vif_bgp_route(self, mac_address, ip_prefix, plen, label, lb_consistent_hash_order, route_distinguisher=None, local_pref=None): rd = route_distinguisher if route_distinguisher else self.instance_rd route_entry = self.generate_vif_bgp_route(mac_address, ip_prefix, plen, label, rd) assert isinstance(route_entry, engine.RouteEntry) route_entry.attributes.add(self._gen_encap_extended_communities()) route_entry.set_route_targets(self.export_rts) ecommunities = exa.ExtendedCommunities() ecommunities.communities.append( exa.ConsistentHashSortOrder(lb_consistent_hash_order)) route_entry.attributes.add(ecommunities) route_entry.attributes.add( exa.LocalPreference(local_pref or DEFAULT_LOCAL_PREF)) self.log.debug("Synthesized Vif route entry: %s", route_entry) return route_entry
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
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 set_route_targets(self, route_targets): # first build a list of ecoms without any RT ecoms = self.ecoms(lambda ecom: not isinstance(ecom, exa.RouteTarget)) # then add the right RTs new_ecoms = exa.ExtendedCommunities() new_ecoms.communities += ecoms new_ecoms.communities += route_targets # update self._route_targets = route_targets self.attributes.remove(new_ecoms.ID) self.attributes.add(new_ecoms)
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)
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 _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
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