const struct trie_node *node = target;
const struct trie_node *parent = node->parent;
+ /* Go from the target node to the root node and save the path taken */
while (parent)
{
if (node == parent->child[0])
assert(node->parent == NULL);
+ /* Descend from the root node to the target node */
for (int i = pos - 1; i >= 0; i--)
{
if (path[i] == 0)
const struct aggregator_bucket * const inherited_bucket = node->parent->ancestor->selected_bucket;
/*
- * If bucket inherited from ancestor is one of potential buckets of this node,
- * then this node doesn't need a bucket because it inherits one.
+ * If the bucket inherited from the ancestor is one of the potential buckets
+ * of this node, then this node doesn't need a bucket because it inherits
+ * one, and is not needed in FIB.
*/
if (is_bucket_potential(node, inherited_bucket))
{
node->selected_bucket = NULL;
node->status = NON_FIB;
- /* Original prefix stays original */
+ /*
+ * We have to keep information whether this prefix was original to enable
+ * processing of incremental updates. If it's not original, then it is
+ * a filler because it's not going to FIB.
+ */
node->px_origin = ORIGINAL == node->px_origin ? ORIGINAL : FILLER;
}
else
node->selected_bucket = choose_lowest_id_bucket(p, node);
node->status = IN_FIB;
- /* Original prefix stays original */
+ /*
+ * Keep information whether this prefix was original. If not, then its origin
+ * is changed to aggregated, because it's going to FIB.
+ */
node->px_origin = ORIGINAL == node->px_origin ? ORIGINAL : AGGREGATED;
assert(node->selected_bucket != NULL);
}
ip4_clrbit(&addr->prefix, node->depth);
}
- /* Leaves with no assigned bucket are removed */
if (NON_FIB == node->status && is_leaf(node))
- {
assert(node->selected_bucket == NULL);
- }
}
/*
net_fill_ip4((net_addr *)&addr, IP4_NONE, 0);
/*
- * If third pass runs from the subtree and not from the root,
- * find prefix of this subtree.
+ * If third pass runs on a subtree and not the whole trie,
+ * find prefix that covers this subtree.
*/
find_subtree_prefix(node, &addr);
{
assert(node != NULL);
- /* Delete information computed by aggregation */
+ /* Delete results computed by aggregation algorithm */
node->selected_bucket = NULL;
node->ancestor = NULL;
node->potential_buckets_count = 0;
memset(node->potential_buckets, 0, sizeof(node->potential_buckets));
/*
- * Original prefixes are IN_FIB and already have their original bucket,
- * otherwise they inherit it from their parents.
+ * Original prefixes are IN_FIB and already have their original bucket
+ * set by trie_insert_prefix(). Otherwise they inherit it from their
+ * parents.
*/
if (ORIGINAL == node->px_origin)
{
}
/*
- * Merge sets of potential buckets going from @node upwards.
- * Stop when sets don't change and return the last updated node.
+ * Merge sets of potential buckets of node's children going from @node upwards.
+ * Stop when the target set doesn't change and return the last updated node.
*/
static struct trie_node *
merge_buckets_above(struct trie_node *node)
struct trie_node *node = updated_node;
- /* Find the closest IN_FIB ancestor */
+ /*
+ * Find the closest IN_FIB ancestor of the updated node and
+ * deaggregate the whole subtree rooted at this node.
+ * Then aggegate it once again, this time with received update.
+ */
while (1)
{
if (IN_FIB == node->status && node != updated_node)
struct trie_node *node = updated_node;
+ /*
+ * Find the closest IN_FIB ancestor of the updated node and
+ * deaggregate the whole subtree rooted at this node.
+ * Then aggegate it once again, this time with received update.
+ */
while (1)
{
if (IN_FIB == node->status)