]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd : route agg. with lcomm attribute is consuming lot of cycles.
authorvdhingra <vdhingra@vmware.com>
Mon, 12 Aug 2019 12:13:14 +0000 (05:13 -0700)
committervdhingra <vdhingra@vmware.com>
Tue, 24 Sep 2019 09:53:51 +0000 (02:53 -0700)
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>
bgpd/bgp_lcommunity.c
bgpd/bgp_lcommunity.h
bgpd/bgp_route.c

index aeb290719a5c60e79d8c7ac148b19b7f107f118e..3243ce96b5a306cd81fc61f27b39fa19fa58df71 100644 (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);
+
+               }
+       }
+}
+
+void bgp_remove_lcomm_from_aggregate_hash(struct bgp_aggregate *aggregate,
+                                         struct lcommunity *lcommunity)
+{
+       struct lcommunity *aggr_lcommunity = NULL;
+       struct lcommunity *ret_lcomm = NULL;
 
-                       /* Compute aggregate's lcommunity.
-                        */
-                       hash_iterate(aggregate->lcommunity_hash,
-                                    bgp_aggr_lcommunity_prepare,
-                                    &aggregate->lcommunity);
+       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);
                }
        }
 }
index a512395492f9788e92a39273012845b4a71f66d6..7d63f4d26add91cad1f7bb008c0ab0901d7ee199 100644 (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 */
index 05974bb2bac2ea140dbc243d0388d17008a44b3b..be13d3bcadc87bf047a50b12110dba5e53b96322 100644 (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);
 }