bgpd : route agg. with lcomm attribute is consuming lot of cycles.

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

Signed-off-by: vishaldhingra <vdhingra@vmware.com>
This commit is contained in:
vdhingra 2019-08-12 05:13:14 -07:00
parent d99d43bc4e
commit f1eb1f0526
3 changed files with 84 additions and 26 deletions

View File

@ -555,15 +555,13 @@ static void *bgp_aggr_lcommunty_hash_alloc(void *p)
static void bgp_aggr_lcommunity_prepare(struct hash_backet *hb, void *arg)
{
struct lcommunity *lcommerge = NULL;
struct lcommunity *hb_lcommunity = hb->data;
struct lcommunity **aggr_lcommunity = arg;
if (*aggr_lcommunity) {
lcommerge = lcommunity_merge(*aggr_lcommunity, hb_lcommunity);
*aggr_lcommunity = lcommunity_uniq_sort(lcommerge);
lcommunity_free(&lcommerge);
} else
if (*aggr_lcommunity)
*aggr_lcommunity = lcommunity_merge(*aggr_lcommunity,
hb_lcommunity);
else
*aggr_lcommunity = lcommunity_dup(hb_lcommunity);
}
@ -577,6 +575,15 @@ void bgp_aggr_lcommunity_remove(void *arg)
void bgp_compute_aggregate_lcommunity(struct bgp_aggregate *aggregate,
struct lcommunity *lcommunity)
{
bgp_compute_aggregate_lcommunity_hash(aggregate, lcommunity);
bgp_compute_aggregate_lcommunity_val(aggregate);
}
void bgp_compute_aggregate_lcommunity_hash(struct bgp_aggregate *aggregate,
struct lcommunity *lcommunity)
{
struct lcommunity *aggr_lcommunity = NULL;
if ((aggregate == NULL) || (lcommunity == NULL))
@ -596,20 +603,34 @@ void bgp_compute_aggregate_lcommunity(struct bgp_aggregate *aggregate,
aggr_lcommunity = hash_get(aggregate->lcommunity_hash,
lcommunity,
bgp_aggr_lcommunty_hash_alloc);
}
/* Re-compute aggregate's lcommunity.
*/
if (aggregate->lcommunity)
lcommunity_free(&aggregate->lcommunity);
/* Increment reference counter.
*/
aggr_lcommunity->refcnt++;
}
void bgp_compute_aggregate_lcommunity_val(struct bgp_aggregate *aggregate)
{
struct lcommunity *lcommerge = NULL;
if (aggregate == NULL)
return;
/* Re-compute aggregate's lcommunity.
*/
if (aggregate->lcommunity)
lcommunity_free(&aggregate->lcommunity);
if (aggregate->lcommunity_hash &&
aggregate->lcommunity_hash->count) {
hash_iterate(aggregate->lcommunity_hash,
bgp_aggr_lcommunity_prepare,
&aggregate->lcommunity);
lcommerge = aggregate->lcommunity;
aggregate->lcommunity = lcommunity_uniq_sort(lcommerge);
if (lcommerge)
lcommunity_free(&lcommerge);
}
/* Increment refernce counter.
*/
aggr_lcommunity->refcnt++;
}
void bgp_remove_lcommunity_from_aggregate(struct bgp_aggregate *aggregate,
@ -618,10 +639,9 @@ void bgp_remove_lcommunity_from_aggregate(struct bgp_aggregate *aggregate,
struct lcommunity *aggr_lcommunity = NULL;
struct lcommunity *ret_lcomm = NULL;
if ((aggregate == NULL) || (lcommunity == NULL))
return;
if (aggregate->lcommunity_hash == NULL)
if ((!aggregate)
|| (!aggregate->lcommunity_hash)
|| (!lcommunity))
return;
/* Look-up the lcommunity in the hash.
@ -635,13 +655,33 @@ void bgp_remove_lcommunity_from_aggregate(struct bgp_aggregate *aggregate,
aggr_lcommunity);
lcommunity_free(&ret_lcomm);
lcommunity_free(&aggregate->lcommunity);
bgp_compute_aggregate_lcommunity_val(aggregate);
/* Compute aggregate's lcommunity.
*/
hash_iterate(aggregate->lcommunity_hash,
bgp_aggr_lcommunity_prepare,
&aggregate->lcommunity);
}
}
}
void bgp_remove_lcomm_from_aggregate_hash(struct bgp_aggregate *aggregate,
struct lcommunity *lcommunity)
{
struct lcommunity *aggr_lcommunity = NULL;
struct lcommunity *ret_lcomm = NULL;
if ((!aggregate)
|| (!aggregate->lcommunity_hash)
|| (!lcommunity))
return;
/* Look-up the lcommunity in the hash.
*/
aggr_lcommunity = bgp_aggr_lcommunity_lookup(aggregate, lcommunity);
if (aggr_lcommunity) {
aggr_lcommunity->refcnt--;
if (aggr_lcommunity->refcnt == 0) {
ret_lcomm = hash_release(aggregate->lcommunity_hash,
aggr_lcommunity);
lcommunity_free(&ret_lcomm);
}
}
}

View File

@ -75,9 +75,19 @@ extern void lcommunity_del_val(struct lcommunity *lcom, uint8_t *ptr);
extern void bgp_compute_aggregate_lcommunity(
struct bgp_aggregate *aggregate,
struct lcommunity *lcommunity);
extern void bgp_compute_aggregate_lcommunity_hash(
struct bgp_aggregate *aggregate,
struct lcommunity *lcommunity);
extern void bgp_compute_aggregate_lcommunity_val(
struct bgp_aggregate *aggregate);
extern void bgp_remove_lcommunity_from_aggregate(
struct bgp_aggregate *aggregate,
struct lcommunity *lcommunity);
extern void bgp_remove_lcomm_from_aggregate_hash(
struct bgp_aggregate *aggregate,
struct lcommunity *lcommunity);
extern void bgp_aggr_lcommunity_remove(void *arg);
#endif /* _QUAGGA_BGP_LCOMMUNITY_H */

View File

@ -5947,13 +5947,16 @@ void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
/* Compute aggregate route's large community.
*/
if (pi->attr->lcommunity)
bgp_compute_aggregate_lcommunity(
bgp_compute_aggregate_lcommunity_hash(
aggregate,
pi->attr->lcommunity);
}
if (match)
bgp_process(bgp, rn, afi, safi);
}
if (aggregate->as_set)
bgp_compute_aggregate_lcommunity_val(aggregate);
bgp_unlock_node(top);
@ -6055,7 +6058,7 @@ void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
if (pi->attr->lcommunity)
/* Remove lcommunity from aggregate.
*/
bgp_remove_lcommunity_from_aggregate(
bgp_remove_lcomm_from_aggregate_hash(
aggregate,
pi->attr->lcommunity);
}
@ -6066,6 +6069,11 @@ void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
if (match)
bgp_process(bgp, rn, afi, safi);
}
if (aggregate->as_set) {
if (aggregate->lcommunity)
lcommunity_free(&aggregate->lcommunity);
}
bgp_unlock_node(top);
}