]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd : route agg. with comm attr is consuming lot of cycles.
authorvdhingra <vdhingra@vmware.com>
Mon, 19 Aug 2019 07:47:50 +0000 (00:47 -0700)
committervdhingra <vdhingra@vmware.com>
Tue, 24 Sep 2019 09:54:19 +0000 (02:54 -0700)
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>
bgpd/bgp_community.c
bgpd/bgp_community.h
bgpd/bgp_route.c

index 22d61f702d7c0c55dacbe76164766638202dd9b2..432c922ea56dd537c8849a06b146a01e1930adc8 100644 (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);
+       /* 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);
        }
-
-       /* Increment refernce counter.
-        */
-       aggr_community->refcnt++;
 }
 
+
+
 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);
+                       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;
 
-                       /* Compute aggregate's community.
-                        */
-                       hash_iterate(aggregate->community_hash,
-                                    bgp_aggr_community_prepare,
-                                    &aggregate->community);
+       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);
                }
        }
 }
index f761a8f5e0f6b4d56200e8593c6d0e1788a9e1d5..74a3a6b50715be06cf8a3e1c6d1fa9e56f04d28b 100644 (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 */
index be13d3bcadc87bf047a50b12110dba5e53b96322..4236c6158e8f2d468e9104aeb3a0a56308daee25 100644 (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);
        }