]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: Code to handle BGP aggregate's communities.
authorNaveen Thanikachalam <nthanikachal@vmware.com>
Wed, 6 Feb 2019 14:28:18 +0000 (06:28 -0800)
committerNaveen Thanikachalam <nthanikachal@vmware.com>
Fri, 1 Mar 2019 04:22:41 +0000 (20:22 -0800)
With this commit:
1) The code to manage the communities attribute of the routes that are
   aggregatable under a configured aggregate-address is introduced.
2) The code to compute the aggregate-route's communities attribute is
   introduced.

Signed-off-by: NaveenThanikachalam <nthanikachal@vmware.com>
bgpd/bgp_community.c
bgpd/bgp_community.h

index 614e24ca4f377c870f94ff74cf6f402f37f94c3f..2e28c30950b91ac96c36e3d882a42f4260aafee7 100644 (file)
@@ -910,3 +910,112 @@ void community_finish(void)
        hash_free(comhash);
        comhash = NULL;
 }
+
+static struct community *bgp_aggr_community_lookup(
+                                               struct bgp_aggregate *aggregate,
+                                               struct community *community)
+{
+       return hash_lookup(aggregate->community_hash, community);
+}
+
+static void *bgp_aggr_communty_hash_alloc(void *p)
+{
+       struct community *ref = (struct community *)p;
+       struct community *community = NULL;
+
+       community = community_dup(ref);
+       return community;
+}
+
+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
+               *aggr_community = community_dup(hb_community);
+}
+
+void bgp_aggr_community_remove(void *arg)
+{
+       struct community *community = arg;
+
+       community_free(&community);
+}
+
+void bgp_compute_aggregate_community(struct bgp_aggregate *aggregate,
+                                    struct community *community)
+{
+       struct community *aggr_community = NULL;
+
+       if ((aggregate == NULL) || (community == NULL))
+               return;
+
+       /* Create hash if not already created.
+        */
+       if (aggregate->community_hash == NULL)
+               aggregate->community_hash = hash_create(
+                       (unsigned int (*)(void *))community_hash_make,
+                       (bool (*)(const void *, const void *))community_cmp,
+                       "BGP Aggregator community hash");
+
+       aggr_community = bgp_aggr_community_lookup(aggregate, community);
+       if (aggr_community == NULL) {
+               /* Insert community into hash.
+                */
+               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);
+
+               hash_iterate(aggregate->community_hash,
+                            bgp_aggr_community_prepare,
+                            &aggregate->community);
+       }
+
+       /* 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)
+               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);
+
+                       community_free(&aggregate->community);
+
+                       /* Compute aggregate's community.
+                        */
+                       hash_iterate(aggregate->community_hash,
+                                    bgp_aggr_community_prepare,
+                                    &aggregate->community);
+               }
+       }
+}
index e1545249d73dee637e33bcaa7d69d9abb0d09a74..4ff4d214a5606e0de610c909cad11ccf5f492122 100644 (file)
@@ -22,6 +22,7 @@
 #define _QUAGGA_BGP_COMMUNITY_H
 
 #include "lib/json.h"
+#include "bgpd/bgp_route.h"
 
 /* Communities attribute.  */
 struct community {
@@ -89,5 +90,10 @@ extern void community_del_val(struct community *, uint32_t *);
 extern unsigned long community_count(void);
 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_remove_community_from_aggregate(struct bgp_aggregate *aggregate,
+                                               struct community *community);
+extern void bgp_aggr_community_remove(void *arg);
 
 #endif /* _QUAGGA_BGP_COMMUNITY_H */