bgpd: atomic-aggregate is lost when we aggregate another aggregate that has atomic-aggregate
This patch ensures that we don't accidently loose the atomic-aggregate
when we aggregate another aggregate that also has atomic-aggregates.
Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com>
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index ac67c62..3b96bb2 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -724,7 +724,8 @@
struct attr *
bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
struct aspath *aspath,
- struct community *community, int as_set)
+ struct community *community, int as_set,
+ u_char atomic_aggregate)
{
struct attr attr;
struct attr *new;
@@ -757,7 +758,7 @@
attre.weight = BGP_ATTR_DEFAULT_WEIGHT;
attre.mp_nexthop_len = IPV6_MAX_BYTELEN;
- if (! as_set)
+ if (! as_set || atomic_aggregate)
attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index 0cd0b77..8457f40 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -168,7 +168,7 @@
extern struct attr *bgp_attr_default_intern (u_char);
extern struct attr *bgp_attr_aggregate_intern (struct bgp *, u_char,
struct aspath *,
- struct community *, int as_set);
+ struct community *, int as_set, u_char);
extern bgp_size_t bgp_packet_attribute (struct bgp *bgp, struct peer *,
struct stream *, struct attr *,
struct prefix *, afi_t, safi_t,
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 78cd53b..7f98f94 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -4753,6 +4753,7 @@
struct bgp_info *new;
int first = 1;
unsigned long match = 0;
+ u_char atomic_aggregate = 0;
/* ORIGIN attribute: If at least one route among routes that are
aggregated has ORIGIN with the value INCOMPLETE, then the
@@ -4797,6 +4798,9 @@
}
#endif /* AGGREGATE_NEXTHOP_CHECK */
+ if (ri->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
+ atomic_aggregate = 1;
+
if (ri->sub_type != BGP_ROUTE_AGGREGATE)
{
if (aggregate->summary_only)
@@ -4883,7 +4887,8 @@
rn = bgp_node_get (table, p);
new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, bgp->peer_self,
bgp_attr_aggregate_intern(bgp, origin, aspath, community,
- aggregate->as_set), rn);
+ aggregate->as_set,
+ atomic_aggregate), rn);
SET_FLAG (new->flags, BGP_INFO_VALID);
bgp_info_add (rn, new);
@@ -4989,6 +4994,7 @@
struct aspath *asmerge = NULL;
struct community *community = NULL;
struct community *commerge = NULL;
+ u_char atomic_aggregate = 0;
table = bgp->rib[afi][safi];
@@ -5010,6 +5016,9 @@
if (BGP_INFO_HOLDDOWN (ri))
continue;
+ if (ri->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
+ atomic_aggregate = 1;
+
if (ri->sub_type != BGP_ROUTE_AGGREGATE)
{
/* summary-only aggregate route suppress aggregated
@@ -5073,7 +5082,8 @@
rn = bgp_node_get (table, p);
new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, bgp->peer_self,
bgp_attr_aggregate_intern(bgp, origin, aspath, community,
- aggregate->as_set), rn);
+ aggregate->as_set,
+ atomic_aggregate), rn);
SET_FLAG (new->flags, BGP_INFO_VALID);
bgp_info_add (rn, new);