From 3da2cc323f79db9e447a5834efd2206a5baf7b7f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 16 Oct 2018 08:13:03 -0400 Subject: [PATCH] bgpd: Add extended community to aggregates Add the ability to aggregate routes to handle extended communities. Make the actions similiar to what we do for normal communities. Signed-off-by: Donald Sharp --- bgpd/bgp_attr.c | 10 ++++-- bgpd/bgp_attr.h | 10 +++--- bgpd/bgp_route.c | 80 ++++++++++++++++++++++++++++++++++++------------ 3 files changed, 74 insertions(+), 26 deletions(-) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index c7d7c56a12..2360408283 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -723,8 +723,9 @@ struct attr *bgp_attr_default_set(struct attr *attr, uint8_t origin) /* Create the attributes for an aggregate */ struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin, struct aspath *aspath, - struct community *community, int as_set, - uint8_t atomic_aggregate) + struct community *community, + struct ecommunity *ecommunity, + int as_set, uint8_t atomic_aggregate) { struct attr attr; struct attr *new; @@ -760,6 +761,11 @@ struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin, attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES); } + if (ecommunity) { + attr.ecommunity = ecommunity; + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES); + } + if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) { bgp_attr_add_gshut_community(&attr); } diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 883b129136..daac86ba97 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -272,10 +272,12 @@ extern void bgp_attr_unintern_sub(struct attr *); extern void bgp_attr_unintern(struct attr **); extern void bgp_attr_flush(struct attr *); extern struct attr *bgp_attr_default_set(struct attr *attr, uint8_t); -extern struct attr *bgp_attr_aggregate_intern(struct bgp *, uint8_t, - struct aspath *, - struct community *, int as_set, - uint8_t); +extern struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin, + struct aspath *aspath, + struct community *community, + struct ecommunity *ecommunity, + int as_set, + uint8_t atomic_aggregate); extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *, struct stream *, struct attr *, struct bpacket_attr_vec_arr *vecarr, diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index c15ce7d9aa..8f2bdea179 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -5482,7 +5482,8 @@ static void bgp_aggregate_free(struct bgp_aggregate *aggregate) static int bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin, struct aspath *aspath, - struct community *comm) + struct community *comm, + struct ecommunity *ecomm) { static struct aspath *ae = NULL; @@ -5501,6 +5502,9 @@ static int bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin, if (!community_cmp(pi->attr->community, comm)) return 0; + if (!ecommunity_cmp(pi->attr->ecommunity, ecomm)) + return 0; + if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)) return 0; @@ -5511,6 +5515,7 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi, struct prefix *p, uint8_t origin, struct aspath *aspath, struct community *community, + struct ecommunity *ecommunity, uint8_t atomic_aggregate, struct bgp_aggregate *aggregate) { @@ -5532,14 +5537,16 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi, * If the aggregate information has not changed * no need to re-install it again. */ - if (bgp_aggregate_info_same(rn->info, origin, aspath, - community)) { + if (bgp_aggregate_info_same(rn->info, origin, aspath, community, + ecommunity)) { bgp_unlock_node(rn); if (aspath) aspath_free(aspath); if (community) community_free(community); + if (ecommunity) + ecommunity_free(&ecommunity); return; } @@ -5550,12 +5557,13 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi, if (pi) bgp_path_info_delete(rn, pi); - new = info_make( - ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self, - bgp_attr_aggregate_intern(bgp, origin, aspath, - community, aggregate->as_set, - atomic_aggregate), - rn); + new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, + bgp->peer_self, + bgp_attr_aggregate_intern(bgp, origin, aspath, + community, ecommunity, + aggregate->as_set, + atomic_aggregate), + rn); SET_FLAG(new->flags, BGP_PATH_VALID); bgp_path_info_add(rn, new); @@ -5591,6 +5599,8 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, struct aspath *asmerge = NULL; struct community *community = NULL; struct community *commerge = NULL; + struct ecommunity *ecommunity = NULL; + struct ecommunity *ecommerge = NULL; struct bgp_path_info *pi; unsigned long match = 0; uint8_t atomic_aggregate = 0; @@ -5670,16 +5680,30 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, } else aspath = aspath_dup(pi->attr->aspath); - if (!pi->attr->community) - continue; + if (pi->attr->community) { + if (community) { + commerge = community_merge( + community, pi->attr->community); + community = + community_uniq_sort(commerge); + community_free(commerge); + } else + community = community_dup( + pi->attr->community); + } - if (community) { - commerge = community_merge(community, - pi->attr->community); - community = community_uniq_sort(commerge); - community_free(commerge); - } else - community = community_dup(pi->attr->community); + if (pi->attr->ecommunity) { + if (ecommunity) { + ecommerge = ecommunity_merge( + ecommunity, + pi->attr->ecommunity); + ecommunity = + ecommunity_uniq_sort(ecommerge); + ecommunity_free(&ecommerge); + } else + ecommunity = ecommunity_dup( + pi->attr->ecommunity); + } } if (match) bgp_process(bgp, rn, afi, safi); @@ -5716,17 +5740,32 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, community = community_dup( pinew->attr->community); } + + if (pinew->attr->ecommunity) { + if (ecommunity) { + ecommerge = ecommunity_merge( + ecommunity, + pinew->attr->ecommunity); + ecommunity = + ecommunity_uniq_sort(ecommerge); + ecommunity_free(&ecommerge); + } else + ecommunity = ecommunity_dup( + pinew->attr->ecommunity); + } } } bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community, - atomic_aggregate, aggregate); + ecommunity, atomic_aggregate, aggregate); if (aggregate->count == 0) { if (aspath) aspath_free(aspath); if (community) community_free(community); + if (ecommunity) + ecommunity_free(&ecommunity); } } @@ -5871,7 +5910,8 @@ static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str, aggregate = bgp_aggregate_get_node_info(rn); bgp_aggregate_delete(bgp, &p, afi, safi, aggregate); - bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL, 0, aggregate); + bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL, NULL, 0, + aggregate); /* Unlock aggregate address configuration. */ bgp_aggregate_set_node_info(rn, NULL); -- 2.39.5