diff options
Diffstat (limited to 'bgpd/bgp_ecommunity.c')
-rw-r--r-- | bgpd/bgp_ecommunity.c | 86 |
1 files changed, 62 insertions, 24 deletions
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index 850b85aa6..11f5a326d 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -1042,15 +1042,13 @@ static void *bgp_aggr_ecommunty_hash_alloc(void *p) static void bgp_aggr_ecommunity_prepare(struct hash_backet *hb, void *arg) { - struct ecommunity *ecommerge = NULL; struct ecommunity *hb_ecommunity = hb->data; struct ecommunity **aggr_ecommunity = arg; - if (*aggr_ecommunity) { - ecommerge = ecommunity_merge(*aggr_ecommunity, hb_ecommunity); - *aggr_ecommunity = ecommunity_uniq_sort(ecommerge); - ecommunity_free(&ecommerge); - } else + if (*aggr_ecommunity) + *aggr_ecommunity = ecommunity_merge(*aggr_ecommunity, + hb_ecommunity); + else *aggr_ecommunity = ecommunity_dup(hb_ecommunity); } @@ -1064,6 +1062,14 @@ void bgp_aggr_ecommunity_remove(void *arg) void bgp_compute_aggregate_ecommunity(struct bgp_aggregate *aggregate, struct ecommunity *ecommunity) { + bgp_compute_aggregate_ecommunity_hash(aggregate, ecommunity); + bgp_compute_aggregate_ecommunity_val(aggregate); +} + + +void bgp_compute_aggregate_ecommunity_hash(struct bgp_aggregate *aggregate, + struct ecommunity *ecommunity) +{ struct ecommunity *aggr_ecommunity = NULL; if ((aggregate == NULL) || (ecommunity == NULL)) @@ -1083,20 +1089,34 @@ void bgp_compute_aggregate_ecommunity(struct bgp_aggregate *aggregate, aggr_ecommunity = hash_get(aggregate->ecommunity_hash, ecommunity, bgp_aggr_ecommunty_hash_alloc); + } - /* Re-compute aggregate's ecommunity. - */ - if (aggregate->ecommunity) - ecommunity_free(&aggregate->ecommunity); + /* Increment reference counter. + */ + aggr_ecommunity->refcnt++; +} +void bgp_compute_aggregate_ecommunity_val(struct bgp_aggregate *aggregate) +{ + struct ecommunity *ecommerge = NULL; + + if (aggregate == NULL) + return; + + /* Re-compute aggregate's ecommunity. + */ + if (aggregate->ecommunity) + ecommunity_free(&aggregate->ecommunity); + if (aggregate->ecommunity_hash + && aggregate->ecommunity_hash->count) { hash_iterate(aggregate->ecommunity_hash, bgp_aggr_ecommunity_prepare, &aggregate->ecommunity); + ecommerge = aggregate->ecommunity; + aggregate->ecommunity = ecommunity_uniq_sort(ecommerge); + if (ecommerge) + ecommunity_free(&ecommerge); } - - /* Increment refernce counter. - */ - aggr_ecommunity->refcnt++; } void bgp_remove_ecommunity_from_aggregate(struct bgp_aggregate *aggregate, @@ -1105,10 +1125,9 @@ void bgp_remove_ecommunity_from_aggregate(struct bgp_aggregate *aggregate, struct ecommunity *aggr_ecommunity = NULL; struct ecommunity *ret_ecomm = NULL; - if ((aggregate == NULL) || (ecommunity == NULL)) - return; - - if (aggregate->ecommunity_hash == NULL) + if ((!aggregate) + || (!aggregate->ecommunity_hash) + || (!ecommunity)) return; /* Look-up the ecommunity in the hash. @@ -1121,14 +1140,33 @@ void bgp_remove_ecommunity_from_aggregate(struct bgp_aggregate *aggregate, ret_ecomm = hash_release(aggregate->ecommunity_hash, aggr_ecommunity); ecommunity_free(&ret_ecomm); + bgp_compute_aggregate_ecommunity_val(aggregate); + } + } +} + +void bgp_remove_ecomm_from_aggregate_hash(struct bgp_aggregate *aggregate, + struct ecommunity *ecommunity) +{ + + struct ecommunity *aggr_ecommunity = NULL; + struct ecommunity *ret_ecomm = NULL; - ecommunity_free(&aggregate->ecommunity); + if ((!aggregate) + || (!aggregate->ecommunity_hash) + || (!ecommunity)) + return; - /* Compute aggregate's ecommunity. - */ - hash_iterate(aggregate->ecommunity_hash, - bgp_aggr_ecommunity_prepare, - &aggregate->ecommunity); + /* Look-up the ecommunity in the hash. + */ + aggr_ecommunity = bgp_aggr_ecommunity_lookup(aggregate, ecommunity); + if (aggr_ecommunity) { + aggr_ecommunity->refcnt--; + + if (aggr_ecommunity->refcnt == 0) { + ret_ecomm = hash_release(aggregate->ecommunity_hash, + aggr_ecommunity); + ecommunity_free(&ret_ecomm); } } } |