diff options
| author | Naveen Thanikachalam <nthanikachal@vmware.com> | 2019-02-06 05:44:20 -0800 | 
|---|---|---|
| committer | Naveen Thanikachalam <nthanikachal@vmware.com> | 2019-02-28 20:22:30 -0800 | 
| commit | e00d800877ef7fc20b1887c2883e855dedcbb442 (patch) | |
| tree | f5aabaa5509eca6689dcf83e1b12fad1d5097cc2 /bgpd/bgp_aspath.c | |
| parent | 83c2a84d7cfe9b4132f15b04593869cee5f408e9 (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.c | 116 | 
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); +		} +	} +}  | 
