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 <sharpd@cumulusnetworks.com>
This commit is contained in:
Donald Sharp 2018-10-16 08:13:03 -04:00
parent d725199ad9
commit 3da2cc323f
3 changed files with 74 additions and 26 deletions

View file

@ -723,8 +723,9 @@ struct attr *bgp_attr_default_set(struct attr *attr, uint8_t origin)
/* Create the attributes for an aggregate */ /* Create the attributes for an aggregate */
struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin, struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin,
struct aspath *aspath, struct aspath *aspath,
struct community *community, int as_set, struct community *community,
uint8_t atomic_aggregate) struct ecommunity *ecommunity,
int as_set, uint8_t atomic_aggregate)
{ {
struct attr attr; struct attr attr;
struct attr *new; 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); 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)) { if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
bgp_attr_add_gshut_community(&attr); bgp_attr_add_gshut_community(&attr);
} }

View file

@ -272,10 +272,12 @@ extern void bgp_attr_unintern_sub(struct attr *);
extern void bgp_attr_unintern(struct attr **); extern void bgp_attr_unintern(struct attr **);
extern void bgp_attr_flush(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_default_set(struct attr *attr, uint8_t);
extern struct attr *bgp_attr_aggregate_intern(struct bgp *, uint8_t, extern struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin,
struct aspath *, struct aspath *aspath,
struct community *, int as_set, struct community *community,
uint8_t); struct ecommunity *ecommunity,
int as_set,
uint8_t atomic_aggregate);
extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *, extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *,
struct stream *, struct attr *, struct stream *, struct attr *,
struct bpacket_attr_vec_arr *vecarr, struct bpacket_attr_vec_arr *vecarr,

View file

@ -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, static int bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
struct aspath *aspath, struct aspath *aspath,
struct community *comm) struct community *comm,
struct ecommunity *ecomm)
{ {
static struct aspath *ae = NULL; 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)) if (!community_cmp(pi->attr->community, comm))
return 0; return 0;
if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
return 0;
if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)) if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
return 0; 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 prefix *p, uint8_t origin,
struct aspath *aspath, struct aspath *aspath,
struct community *community, struct community *community,
struct ecommunity *ecommunity,
uint8_t atomic_aggregate, uint8_t atomic_aggregate,
struct bgp_aggregate *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 * If the aggregate information has not changed
* no need to re-install it again. * no need to re-install it again.
*/ */
if (bgp_aggregate_info_same(rn->info, origin, aspath, if (bgp_aggregate_info_same(rn->info, origin, aspath, community,
community)) { ecommunity)) {
bgp_unlock_node(rn); bgp_unlock_node(rn);
if (aspath) if (aspath)
aspath_free(aspath); aspath_free(aspath);
if (community) if (community)
community_free(community); community_free(community);
if (ecommunity)
ecommunity_free(&ecommunity);
return; return;
} }
@ -5550,12 +5557,13 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi,
if (pi) if (pi)
bgp_path_info_delete(rn, pi); bgp_path_info_delete(rn, pi);
new = info_make( new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self, bgp->peer_self,
bgp_attr_aggregate_intern(bgp, origin, aspath, bgp_attr_aggregate_intern(bgp, origin, aspath,
community, aggregate->as_set, community, ecommunity,
atomic_aggregate), aggregate->as_set,
rn); atomic_aggregate),
rn);
SET_FLAG(new->flags, BGP_PATH_VALID); SET_FLAG(new->flags, BGP_PATH_VALID);
bgp_path_info_add(rn, new); 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 aspath *asmerge = NULL;
struct community *community = NULL; struct community *community = NULL;
struct community *commerge = NULL; struct community *commerge = NULL;
struct ecommunity *ecommunity = NULL;
struct ecommunity *ecommerge = NULL;
struct bgp_path_info *pi; struct bgp_path_info *pi;
unsigned long match = 0; unsigned long match = 0;
uint8_t atomic_aggregate = 0; uint8_t atomic_aggregate = 0;
@ -5670,16 +5680,30 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
} else } else
aspath = aspath_dup(pi->attr->aspath); aspath = aspath_dup(pi->attr->aspath);
if (!pi->attr->community) if (pi->attr->community) {
continue; 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) { if (pi->attr->ecommunity) {
commerge = community_merge(community, if (ecommunity) {
pi->attr->community); ecommerge = ecommunity_merge(
community = community_uniq_sort(commerge); ecommunity,
community_free(commerge); pi->attr->ecommunity);
} else ecommunity =
community = community_dup(pi->attr->community); ecommunity_uniq_sort(ecommerge);
ecommunity_free(&ecommerge);
} else
ecommunity = ecommunity_dup(
pi->attr->ecommunity);
}
} }
if (match) if (match)
bgp_process(bgp, rn, afi, safi); bgp_process(bgp, rn, afi, safi);
@ -5716,17 +5740,32 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
community = community_dup( community = community_dup(
pinew->attr->community); 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, bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
atomic_aggregate, aggregate); ecommunity, atomic_aggregate, aggregate);
if (aggregate->count == 0) { if (aggregate->count == 0) {
if (aspath) if (aspath)
aspath_free(aspath); aspath_free(aspath);
if (community) if (community)
community_free(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); aggregate = bgp_aggregate_get_node_info(rn);
bgp_aggregate_delete(bgp, &p, afi, safi, aggregate); 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. */ /* Unlock aggregate address configuration. */
bgp_aggregate_set_node_info(rn, NULL); bgp_aggregate_set_node_info(rn, NULL);