zebra: rework recursive route resolution

Change the datastructure for recursive routes. This brings the following
benefits:

By using struct nexthop also to store nexthops obtained by recursive
resolution, we can get rid of quite a bit of code duplication in the fib
management. (rt_netlink, rt_socket, ...)

With the new datastructure we can make use of all available paths when
recursive routes are resolved with multipath routes.

Signed-off-by: Christian Franke <chris@opensourcerouting.org>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 1182937..5df521b 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -389,7 +389,8 @@
   
   for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
     {
-      if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
+      if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
+          || nexthop_has_fib_child(nexthop))
         {
           SET_FLAG (zapi_flags, ZAPI_MESSAGE_NEXTHOP);
           SET_FLAG (zapi_flags, ZAPI_MESSAGE_IFINDEX);
@@ -488,6 +489,9 @@
       num = 0;
       nump = stream_get_endp(s);
       stream_putc (s, 0);
+      /* Only non-recursive routes are elegible to resolve nexthop we
+       * are looking up. Therefore, we will just iterate over the top
+       * chain of nexthops. */
       for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
 	if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
 	  {
@@ -554,6 +558,9 @@
       num = 0;
       nump = stream_get_endp(s);
       stream_putc (s, 0);
+      /* Only non-recursive routes are elegible to resolve the nexthop we
+       * are looking up. Therefore, we will just iterate over the top
+       * chain of nexthops. */
       for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
 	if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
 	  {
@@ -619,7 +626,8 @@
       nump = stream_get_endp(s);
       stream_putc (s, 0);
       for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
-	if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
+	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
+            || nexthop_has_fib_child(nexthop))
 	  {
 	    stream_putc (s, nexthop->type);
 	    switch (nexthop->type)