bgpd : route agg. with comm attr is consuming lot of cycles.

While configuring aggregate route prepare the hash table
first, then prepare the aggregated standard comm value
and then do the unique sort once for standard community.

Signed-off-by: vishaldhingra<vdhingra@vmware.com>
This commit is contained in:
vdhingra 2019-08-19 00:47:50 -07:00
parent f1eb1f0526
commit 21fec67453
3 changed files with 84 additions and 30 deletions

View File

@ -910,15 +910,13 @@ static void *bgp_aggr_communty_hash_alloc(void *p)
static void bgp_aggr_community_prepare(struct hash_backet *hb, void *arg)
{
struct community *commerge = NULL;
struct community *hb_community = hb->data;
struct community **aggr_community = arg;
if (*aggr_community) {
commerge = community_merge(*aggr_community, hb_community);
*aggr_community = community_uniq_sort(commerge);
community_free(&commerge);
} else
if (*aggr_community)
*aggr_community = community_merge(*aggr_community,
hb_community);
else
*aggr_community = community_dup(hb_community);
}
@ -931,6 +929,14 @@ void bgp_aggr_community_remove(void *arg)
void bgp_compute_aggregate_community(struct bgp_aggregate *aggregate,
struct community *community)
{
bgp_compute_aggregate_community_hash(aggregate, community);
bgp_compute_aggregate_community_val(aggregate);
}
void bgp_compute_aggregate_community_hash(struct bgp_aggregate *aggregate,
struct community *community)
{
struct community *aggr_community = NULL;
@ -951,32 +957,47 @@ void bgp_compute_aggregate_community(struct bgp_aggregate *aggregate,
*/
aggr_community = hash_get(aggregate->community_hash, community,
bgp_aggr_communty_hash_alloc);
/* Re-compute aggregate's community.
*/
if (aggregate->community)
community_free(&aggregate->community);
hash_iterate(aggregate->community_hash,
bgp_aggr_community_prepare,
&aggregate->community);
}
/* Increment refernce counter.
/* Increment reference counter.
*/
aggr_community->refcnt++;
}
void bgp_compute_aggregate_community_val(struct bgp_aggregate *aggregate)
{
struct community *commerge = NULL;
if (aggregate == NULL)
return;
/* Re-compute aggregate's community.
*/
if (aggregate->community)
community_free(&aggregate->community);
if (aggregate->community_hash &&
aggregate->community_hash->count) {
hash_iterate(aggregate->community_hash,
bgp_aggr_community_prepare,
&aggregate->community);
commerge = aggregate->community;
aggregate->community = community_uniq_sort(commerge);
if (commerge)
community_free(&commerge);
}
}
void bgp_remove_community_from_aggregate(struct bgp_aggregate *aggregate,
struct community *community)
{
struct community *aggr_community = NULL;
struct community *ret_comm = NULL;
if ((aggregate == NULL) || (community == NULL))
return;
if (aggregate->community_hash == NULL)
if ((!aggregate)
|| (!aggregate->community_hash)
|| (!community))
return;
/* Look-up the community in the hash.
@ -990,13 +1011,33 @@ void bgp_remove_community_from_aggregate(struct bgp_aggregate *aggregate,
aggr_community);
community_free(&ret_comm);
community_free(&aggregate->community);
/* Compute aggregate's community.
*/
hash_iterate(aggregate->community_hash,
bgp_aggr_community_prepare,
&aggregate->community);
bgp_compute_aggregate_community_val(aggregate);
}
}
}
void bgp_remove_comm_from_aggregate_hash(struct bgp_aggregate *aggregate,
struct community *community)
{
struct community *aggr_community = NULL;
struct community *ret_comm = NULL;
if ((!aggregate)
|| (!aggregate->community_hash)
|| (!community))
return;
/* Look-up the community in the hash.
*/
aggr_community = bgp_aggr_community_lookup(aggregate, community);
if (aggr_community) {
aggr_community->refcnt--;
if (aggr_community->refcnt == 0) {
ret_comm = hash_release(aggregate->community_hash,
aggr_community);
community_free(&ret_comm);
}
}
}

View File

@ -92,8 +92,16 @@ extern struct hash *community_hash(void);
extern uint32_t community_val_get(struct community *com, int i);
extern void bgp_compute_aggregate_community(struct bgp_aggregate *aggregate,
struct community *community);
extern void bgp_compute_aggregate_community_val(
struct bgp_aggregate *aggregate);
extern void bgp_compute_aggregate_community_hash(
struct bgp_aggregate *aggregate,
struct community *community);
extern void bgp_remove_community_from_aggregate(struct bgp_aggregate *aggregate,
struct community *community);
extern void bgp_remove_comm_from_aggregate_hash(struct bgp_aggregate *aggregate,
struct community *community);
extern void bgp_aggr_community_remove(void *arg);
#endif /* _QUAGGA_BGP_COMMUNITY_H */

View File

@ -5933,7 +5933,7 @@ void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
/* Compute aggregate route's community.
*/
if (pi->attr->community)
bgp_compute_aggregate_community(
bgp_compute_aggregate_community_hash(
aggregate,
pi->attr->community);
@ -5954,8 +5954,11 @@ void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
if (match)
bgp_process(bgp, rn, afi, safi);
}
if (aggregate->as_set)
if (aggregate->as_set) {
bgp_compute_aggregate_community_val(aggregate);
bgp_compute_aggregate_lcommunity_val(aggregate);
}
bgp_unlock_node(top);
@ -6044,7 +6047,7 @@ void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
if (pi->attr->community)
/* Remove community from aggregate.
*/
bgp_remove_community_from_aggregate(
bgp_remove_comm_from_aggregate_hash(
aggregate,
pi->attr->community);
@ -6070,6 +6073,8 @@ void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
bgp_process(bgp, rn, afi, safi);
}
if (aggregate->as_set) {
if (aggregate->community)
community_free(&aggregate->community);
if (aggregate->lcommunity)
lcommunity_free(&aggregate->lcommunity);
}