]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib,zebra: Fix ALL_NEXTHOPS iterator
authorChristian Franke <chris@opensourcerouting.org>
Wed, 12 Jul 2017 16:27:55 +0000 (18:27 +0200)
committerChristian Franke <chris@opensourcerouting.org>
Wed, 12 Jul 2017 16:27:55 +0000 (18:27 +0200)
Signed-off-by: Christian Franke <chris@opensourcerouting.org>
lib/nexthop.c
lib/nexthop.h
zebra/rib.h

index 948baca1985d23543a38da63694c0c4c19d72a02..ef9ae800f66d1528e1218424106efc8ffc8250d8 100644 (file)
@@ -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;
+}
index f48c41dc55d256088d19f9d20bc508022df7f4ac..4d7f32f6f04c8f15acd19af1420589716ad154a7 100644 (file)
@@ -93,6 +93,17 @@ struct nexthop
   struct nexthop_label *nh_label;
 };
 
+/* The following for loop allows to iterate over the nexthop
+ * structure of routes.
+ *
+ * head:      The pointer to the first nexthop in the chain.
+ *
+ * nexthop:   The pointer to the current nexthop, either in the
+ *            top-level chain or in a resolved chain.
+ */
+#define ALL_NEXTHOPS(head, nexthop)   \
+  (nexthop) = (head); (nexthop); (nexthop) = nexthop_next(nexthop)
+
 extern int zebra_rnh_ip_default_route;
 extern int zebra_rnh_ipv6_default_route;
 
@@ -121,4 +132,5 @@ extern int nexthop_same_no_recurse (struct nexthop *next1, struct nexthop *next2
 extern int nexthop_labels_match (struct nexthop *nh1, struct nexthop *nh2);
 
 extern const char * nexthop2str (struct nexthop *nexthop, char *str, int size);
+extern struct nexthop *nexthop_next(struct nexthop *nexthop);
 #endif /*_LIB_NEXTHOP_H */
index 7a1b1485e98ced327ecfb8a0e999bd6cbf749b06..999266241a61482792bc72fc0fb449b883263f5f 100644 (file)
@@ -178,39 +178,6 @@ typedef struct rib_dest_t_
 #define RNODE_FOREACH_RE_SAFE(rn, re, next)                            \
   RE_DEST_FOREACH_ROUTE_SAFE (rib_dest_from_rnode (rn), re, next)
 
-/* The following for loop allows to iterate over the nexthop
- * structure of routes.
- *
- * head:      The pointer to the first nexthop in the chain.
- *
- * nexthop:   The pointer to the current nexthop, either in the
- *            top-level chain or in a resolved chain.
- *
- * Initialization: Set `nexthop' to the head of the top-level chain.
- *
- * Iteration check: Check that the `nexthop' pointer is not NULL.
- *
- * Iteration step: 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 try
- * to get up to the previous recursion level 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
- */
-#define ALL_NEXTHOPS(head, nexthop)                              \
-  (nexthop) = (head);                                               \
-  (nexthop);                                                        \
-  (nexthop) = CHECK_FLAG((nexthop)->flags, NEXTHOP_FLAG_RECURSIVE)  \
-    ? ((nexthop)->resolved)                                         \
-       : ((nexthop)->next ? (nexthop)->next                         \
-          : ((nexthop)->rparent ? (nexthop)->rparent->next : NULL))
-
 #if defined (HAVE_RTADV)
 /* Structure which hold status of router advertisement. */
 struct rtadv