summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_ecommunity.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_ecommunity.c')
-rw-r--r--bgpd/bgp_ecommunity.c86
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);
}
}
}