}
/*
+ * Compare buckets by linear ordering on pointers
*/
static int
aggregator_bucket_compare(const struct aggregator_bucket *a, const struct aggregator_bucket *b)
for (int i = 0; i < input_count; i++)
{
+ /*
+ * Don't copy element if it's the same as the last inserted element
+ * to avoid duplicates
+ */
if (output_count != 0 && output_buckets[output_count - 1] == input_buckets[i])
continue;
for (int j = i + 1; j < right->potential_buckets_count; j++)
assert(right->potential_buckets[i] != right->potential_buckets[j]);
+ /*
+ * If there are no common buckets among children's buckets, parent's
+ * buckets are computed as union of its children's buckets.
+ * Otherwise, parent's buckets are computed as intersection of its
+ * children's buckets.
+ */
if (bucket_sets_are_disjoint(left, right))
compute_buckets_union(node, left, right);
else
return;
}
+ /* Internal node with assigned bucket */
if (node->bucket)
{
create_route_ip4(p, node->bucket, addr);
return;
}
+ /* Internal node with assigned bucket */
if (node->bucket)
{
create_route_ip6(p, node->bucket, addr);
}
/*
- * Create and export new merged route.
- * @old: first route in a sequence of equivalent routes that are to be merged
- * @rte_val: first element in a sequence of equivalent rte_val_list entries
- * @length: number of equivalent routes that are to be merged (at least 1)
- * @ail: aggregation list
+ * Create and export new merged route
*/
static void
aggregator_bucket_update(struct aggregator_proto *p, struct aggregator_bucket *bucket, struct network *net)
rta_free(old_route->rte.attrs);
}
+ /* Aggregation within nets allows incremental updates */
if (NET_AGGR == p->aggr_mode)
{
/* Announce changes */
return P;
}
+/*
+ * Initialize hash table and create default route
+ */
static void
trie_init(struct aggregator_proto *p)
{