diff options
-rw-r--r-- | bgpd/bgp_aspath.c | 116 | ||||
-rw-r--r-- | bgpd/bgp_aspath.h | 7 | ||||
-rw-r--r-- | bgpd/bgp_route.c | 27 | ||||
-rw-r--r-- | bgpd/bgp_route.h | 65 |
4 files changed, 186 insertions, 29 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index 9521a9e91..bf6f3f81f 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); + } + } +} diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h index 9c9c687a6..be5725c1a 100644 --- a/bgpd/bgp_aspath.h +++ b/bgpd/bgp_aspath.h @@ -22,6 +22,7 @@ #define _QUAGGA_BGP_ASPATH_H #include "lib/json.h" +#include "bgpd/bgp_route.h" /* AS path segment type. */ #define AS_SET 1 @@ -130,4 +131,10 @@ extern unsigned int aspath_has_as4(struct aspath *); /* For SNMP BGP4PATHATTRASPATHSEGMENT, might be useful for debug */ extern uint8_t *aspath_snmp_pathseg(struct aspath *, size_t *); +extern void bgp_compute_aggregate_aspath(struct bgp_aggregate *aggregate, + struct aspath *aspath); +extern void bgp_remove_aspath_from_aggregate(struct bgp_aggregate *aggregate, + struct aspath *aspath); +extern void bgp_aggr_aspath_remove(void *arg); + #endif /* _QUAGGA_BGP_ASPATH_H */ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 99dc9d812..7ac53b43f 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -5513,33 +5513,6 @@ DEFPY(ipv6_bgp_network, label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX); } -/* Aggreagete address: - - advertise-map Set condition to advertise attribute - as-set Generate AS set path information - attribute-map Set attributes of aggregate - route-map Set parameters of aggregate - summary-only Filter more specific routes from updates - suppress-map Conditionally filter more specific routes from updates - <cr> - */ -struct bgp_aggregate { - /* Summary-only flag. */ - uint8_t summary_only; - - /* AS set generation. */ - uint8_t as_set; - - /* Route-map for aggregated route. */ - struct route_map *map; - - /* Suppress-count. */ - unsigned long count; - - /* SAFI configuration. */ - safi_t safi; -}; - static struct bgp_aggregate *bgp_aggregate_new(void) { return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate)); diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 97d4aaeeb..a1287152c 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -272,6 +272,71 @@ struct bgp_static { struct prefix gatewayIp; }; +/* Aggreagete address: + * + * advertise-map Set condition to advertise attribute + * as-set Generate AS set path information + * attribute-map Set attributes of aggregate + * route-map Set parameters of aggregate + * summary-only Filter more specific routes from updates + * suppress-map Conditionally filter more specific routes from updates + * <cr> + */ +struct bgp_aggregate { + /* Summary-only flag. */ + uint8_t summary_only; + + /* AS set generation. */ + uint8_t as_set; + + /* Route-map for aggregated route. */ + struct route_map *map; + + /* Suppress-count. */ + unsigned long count; + + /* Count of routes of origin type incomplete under this aggregate. */ + unsigned long incomplete_origin_count; + + /* Count of routes of origin type egp under this aggregate. */ + unsigned long egp_origin_count; + + /* Hash containing the communities of all the + * routes under this aggregate. + */ + struct hash *community_hash; + + /* Hash containing the extended communities of all the + * routes under this aggregate. + */ + struct hash *ecommunity_hash; + + /* Hash containing the large communities of all the + * routes under this aggregate. + */ + struct hash *lcommunity_hash; + + /* Hash containing the AS-Path of all the + * routes under this aggregate. + */ + struct hash *aspath_hash; + + /* Aggregate route's community. */ + struct community *community; + + /* Aggregate route's extended community. */ + struct ecommunity *ecommunity; + + /* Aggregate route's large community. */ + struct lcommunity *lcommunity; + + /* Aggregate route's as-path. */ + struct aspath *aspath; + + /* SAFI configuration. */ + safi_t safi; +}; + #define BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen) \ ((nhlen) < IPV4_MAX_BYTELEN \ ? 0 \ |