forked from Mirror/frr
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:
parent
d725199ad9
commit
3da2cc323f
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue