summaryrefslogtreecommitdiff
path: root/bgpd/bgp_aspath.c
diff options
context:
space:
mode:
authorNaveen Thanikachalam <nthanikachal@vmware.com>2019-02-06 05:44:20 -0800
committerNaveen Thanikachalam <nthanikachal@vmware.com>2019-02-28 20:22:30 -0800
commite00d800877ef7fc20b1887c2883e855dedcbb442 (patch)
treef5aabaa5509eca6689dcf83e1b12fad1d5097cc2 /bgpd/bgp_aspath.c
parent83c2a84d7cfe9b4132f15b04593869cee5f408e9 (diff)
bgpd: Code to handle BGP aggregate's as-path.
With this commit: 1) 'struct bgp_aggregate' is moved to bgp_route.h from bgp_route.c 2) Hashes to accommodate the as-path, communities, extended-communities and large-communities attributes of all the routes aggregated by an aggregate route is introduced in 'struct bgp_aggregate'. 3) Place-holders for the aggregate route's as-path, communities, extended-communities and large-communities attributes are introduced in 'struct bgp_aggregate'. 4) The code to manage the as-path of the routes that are aggregatable under a configured aggregate-address is introduced. 5) The code to compute the aggregate-route's as-path is introduced. Signed-off-by: NaveenThanikachalam <nthanikachal@vmware.com>
Diffstat (limited to 'bgpd/bgp_aspath.c')
-rw-r--r--bgpd/bgp_aspath.c116
1 files changed, 114 insertions, 2 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index 9521a9e912..bf6f3f81f6 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -212,6 +212,9 @@ static struct assegment *assegment_append_asns(struct assegment *seg,
{
as_t *newas;
+ if (!seg)
+ return seg;
+
newas = XREALLOC(MTYPE_AS_SEG_DATA, seg->as,
ASSEGMENT_DATA_SIZE(seg->length + num, 1));
@@ -1372,7 +1375,8 @@ static struct aspath *aspath_merge(struct aspath *as1, struct aspath *as2)
while (last && last->next)
last = last->next;
- last->next = as2->segments;
+ if (last)
+ last->next = as2->segments;
as2->segments = new;
aspath_str_update(as2, false);
return as2;
@@ -1447,7 +1451,8 @@ struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2)
* bypass the merged seg2, and attach any chain after it
* to chain descending from as2's head
*/
- as2segtail->next = as2seghead->next;
+ if (as2segtail)
+ as2segtail->next = as2seghead->next;
/* as2->segments is now referenceless and useless */
assegment_free(as2seghead);
@@ -2096,3 +2101,110 @@ void aspath_print_all_vty(struct vty *vty)
void *))aspath_show_all_iterator,
vty);
}
+
+static struct aspath *bgp_aggr_aspath_lookup(struct bgp_aggregate *aggregate,
+ struct aspath *aspath)
+{
+ return hash_lookup(aggregate->aspath_hash, aspath);
+}
+
+static void *bgp_aggr_aspath_hash_alloc(void *p)
+{
+ struct aspath *ref = (struct aspath *)p;
+ struct aspath *aspath = NULL;
+
+ aspath = aspath_dup(ref);
+ return aspath;
+}
+
+static void bgp_aggr_aspath_prepare(struct hash_backet *hb, void *arg)
+{
+ struct aspath *asmerge = NULL;
+ struct aspath *hb_aspath = hb->data;
+ struct aspath **aggr_aspath = arg;
+
+ if (*aggr_aspath) {
+ asmerge = aspath_aggregate(*aggr_aspath, hb_aspath);
+ aspath_free(*aggr_aspath);
+ *aggr_aspath = asmerge;
+ } else
+ *aggr_aspath = aspath_dup(hb_aspath);
+}
+
+void bgp_aggr_aspath_remove(void *arg)
+{
+ struct aspath *aspath = arg;
+
+ aspath_free(aspath);
+}
+
+void bgp_compute_aggregate_aspath(struct bgp_aggregate *aggregate,
+ struct aspath *aspath)
+{
+ struct aspath *aggr_aspath = NULL;
+
+ if ((aggregate == NULL) || (aspath == NULL))
+ return;
+
+ /* Create hash if not already created.
+ */
+ if (aggregate->aspath_hash == NULL)
+ aggregate->aspath_hash = hash_create(
+ aspath_key_make, aspath_cmp,
+ "BGP Aggregator as-path hash");
+
+ aggr_aspath = bgp_aggr_aspath_lookup(aggregate, aspath);
+ if (aggr_aspath == NULL) {
+ /* Insert as-path into hash.
+ */
+ aggr_aspath = hash_get(aggregate->aspath_hash, aspath,
+ bgp_aggr_aspath_hash_alloc);
+
+ /* Compute aggregate's as-path.
+ */
+ hash_iterate(aggregate->aspath_hash,
+ bgp_aggr_aspath_prepare,
+ &aggregate->aspath);
+ }
+
+ /* Increment refernce counter.
+ */
+ aggr_aspath->refcnt++;
+}
+
+void bgp_remove_aspath_from_aggregate(struct bgp_aggregate *aggregate,
+ struct aspath *aspath)
+{
+ struct aspath *aggr_aspath = NULL;
+ struct aspath *ret_aspath = NULL;
+
+ if ((aggregate == NULL) || (aspath == NULL))
+ return;
+
+ if (aggregate->aspath_hash == NULL)
+ return;
+
+ /* Look-up the aspath in the hash.
+ */
+ aggr_aspath = bgp_aggr_aspath_lookup(aggregate, aspath);
+ if (aggr_aspath) {
+ aggr_aspath->refcnt--;
+
+ if (aggr_aspath->refcnt == 0) {
+ ret_aspath = hash_release(aggregate->aspath_hash,
+ aggr_aspath);
+ aspath_free(ret_aspath);
+
+ /* Remove aggregate's old as-path.
+ */
+ aspath_free(aggregate->aspath);
+ aggregate->aspath = NULL;
+
+ /* Compute aggregate's as-path.
+ */
+ hash_iterate(aggregate->aspath_hash,
+ bgp_aggr_aspath_prepare,
+ &aggregate->aspath);
+ }
+ }
+}