summaryrefslogtreecommitdiff
path: root/lib/nexthop.c
diff options
context:
space:
mode:
authorChristian Franke <chris@opensourcerouting.org>2017-07-12 18:27:55 +0200
committerChristian Franke <chris@opensourcerouting.org>2017-07-12 18:27:55 +0200
commit9fb47c0584ced64080c977ade8597de377d47b7f (patch)
tree3b5c2a42de7ac98eb3b9afae688c1ef2829a5102 /lib/nexthop.c
parent7215c4f0584c5bf2804890a3dc2d69697a05c49a (diff)
lib,zebra: Fix ALL_NEXTHOPS iterator
Signed-off-by: Christian Franke <chris@opensourcerouting.org>
Diffstat (limited to 'lib/nexthop.c')
-rw-r--r--lib/nexthop.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/lib/nexthop.c b/lib/nexthop.c
index 948baca198..ef9ae800f6 100644
--- a/lib/nexthop.c
+++ b/lib/nexthop.c
@@ -242,3 +242,34 @@ nexthop2str (struct nexthop *nexthop, char *str, int size)
return str;
}
+
+/*
+ * Iteration step for ALL_NEXTHOPS macro:
+ * This is the tricky part. Check if `nexthop' has
+ * NEXTHOP_FLAG_RECURSIVE set. If yes, this implies that `nexthop' has
+ * at least one nexthop attached to `nexthop->resolved', which will be
+ * the next one.
+ *
+ * If NEXTHOP_FLAG_RECURSIVE is not set, `nexthop' will progress in its
+ * current chain. In case its current chain end is reached, it will move
+ * upwards in the recursion levels and progress there. Whenever a step
+ * forward in a chain is done, recursion will be checked again.
+ * In a nustshell, it's equivalent to a pre-traversal order assuming that
+ * left branch is 'resolved' and right branch is 'next':
+ * https://en.wikipedia.org/wiki/Tree_traversal#/media/File:Sorted_binary_tree_preorder.svg
+ */
+struct nexthop *
+nexthop_next(struct nexthop *nexthop)
+{
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
+ return nexthop->resolved;
+
+ if (nexthop->next)
+ return nexthop->next;
+
+ for (struct nexthop *par = nexthop->rparent; par; par = par->rparent)
+ if (par->next)
+ return par->next;
+
+ return NULL;
+}