summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_aspath.c116
-rw-r--r--bgpd/bgp_aspath.h7
-rw-r--r--bgpd/bgp_route.c27
-rw-r--r--bgpd/bgp_route.h65
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 \