zebra: add structure to hold per-prefix state in RIB

Add the rib_dest_t structure to hold per-prefix state in the routing
information base. This gives us an appropriate place to maintain the
queueing state of a route_node. Queuing state was previously being
stored on the first rib in the list of ribs hanging off the
route_node.

  * zebra/rib.h

    - Add new structure rib_dest_t.

    - Remove the rn_status field from 'struct rib', it is no longer
      required.

    - Add macros (RNODE_FOREACH_RIB, RNODE_FOREACH_RIB_SAFE) for
      walking all 'struct ribs' corresponding to a route_node. These
      hide the fact that there is an intermediate rib_dest_t
      structure.

    - Add a few utility inlines to go between a rib_dest_t and
      associated structures.

  * zebra/zebra_rib.c

    - rib_link()/rib_unlink()

      Tweak for new behavior, where the 'info' pointer of a route_node
      points to a rib_dest_t. The list of ribs for a prefix now hangs
      off of the dest.

      Change the way we ref count route_nodes. We now hold a single
      ref count on a route_node if there is a corresponding
      rib_dest_t.

    - Maintain the queuing state of a route_node on the flags field of
      the rib_dest_t.

    - Add the rib_gc_dest() function, which deletes a rib_dest_t if it
      is no longer required. A rib_dest_t can be deleted iff there are
      no struct ribs hanging off of it.

    - Call rib_gc_dest() any time we unlink a rib from the
      rib_dest_t. Currently we only need to call it once, just before
      we return from rib_process().

  * zebra/{redistribute,zebra_rib,zebra_snmp,zebra_vty}.c

    Use new macros to walk over route_node ribs.

  * lib/memtypes.c

    Add memory type for rib_dest_t.

Signed-off-by: Avneesh Sachdev <avneesh@opensourcerouting.org>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
diff --git a/zebra/rib.h b/zebra/rib.h
index 1b85c81..084f351 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -24,6 +24,7 @@
 #define _ZEBRA_RIB_H
 
 #include "prefix.h"
+#include "table.h"
 
 #define DISTANCE_INFINITY  255
 
@@ -38,10 +39,6 @@
 
 struct rib
 {
-  /* Status Flags for the *route_node*, but kept in the head RIB.. */
-  u_char rn_status;
-#define RIB_ROUTE_QUEUED(x)	(1 << (x))
-
   /* Link list. */
   struct rib *next;
   struct rib *prev;
@@ -97,6 +94,57 @@
   u_int32_t size; /* sum of lengths of all subqueues */
 };
 
+/*
+ * Structure that represents a single destination (prefix).
+ */
+typedef struct rib_dest_t_
+{
+
+  /*
+   * Back pointer to the route node for this destination. This helps
+   * us get to the prefix that this structure is for.
+   */
+  struct route_node *rnode;
+
+  /*
+   * Doubly-linked list of routes for this prefix.
+   */
+  struct rib *routes;
+
+  /*
+   * Flags, see below.
+   */
+  u_int32_t flags;
+
+} rib_dest_t;
+
+#define RIB_ROUTE_QUEUED(x)	(1 << (x))
+
+/*
+ * The maximum qindex that can be used.
+ */
+#define ZEBRA_MAX_QINDEX        (MQ_SIZE - 1)
+
+/*
+ * Macro to iterate over each route for a destination (prefix).
+ */
+#define RIB_DEST_FOREACH_ROUTE(dest, rib)				\
+  for ((rib) = (dest) ? (dest)->routes : NULL; (rib); (rib) = (rib)->next)
+
+/*
+ * Same as above, but allows the current node to be unlinked.
+ */
+#define RIB_DEST_FOREACH_ROUTE_SAFE(dest, rib, next)	\
+  for ((rib) = (dest) ? (dest)->routes : NULL;		\
+       (rib) && ((next) = (rib)->next, 1);		\
+       (rib) = (next))
+
+#define RNODE_FOREACH_RIB(rn, rib)				\
+  RIB_DEST_FOREACH_ROUTE (rib_dest_from_rnode (rn), rib)
+
+#define RNODE_FOREACH_RIB_SAFE(rn, rib, next)				\
+  RIB_DEST_FOREACH_ROUTE_SAFE (rib_dest_from_rnode (rn), rib, next)
+
 /* Static route information. */
 struct static_ipv4
 {
@@ -307,4 +355,66 @@
 
 #endif /* HAVE_IPV6 */
 
+extern int rib_gc_dest (struct route_node *rn);
+
+/*
+ * Inline functions.
+ */
+
+/*
+ * rib_dest_from_rnode
+ */
+static inline rib_dest_t *
+rib_dest_from_rnode (struct route_node *rn)
+{
+  return (rib_dest_t *) rn->info;
+}
+
+/*
+ * rnode_to_ribs
+ *
+ * Returns a pointer to the list of routes corresponding to the given
+ * route_node.
+ */
+static inline struct rib *
+rnode_to_ribs (struct route_node *rn)
+{
+  rib_dest_t *dest;
+
+  dest = rib_dest_from_rnode (rn);
+  if (!dest)
+    return NULL;
+
+  return dest->routes;
+}
+
+/*
+ * rib_dest_prefix
+ */
+static inline struct prefix *
+rib_dest_prefix (rib_dest_t *dest)
+{
+  return &dest->rnode->p;
+}
+
+/*
+ * rib_dest_af
+ *
+ * Returns the address family that the destination is for.
+ */
+static inline u_char
+rib_dest_af (rib_dest_t *dest)
+{
+  return dest->rnode->p.family;
+}
+
+/*
+ * rib_dest_table
+ */
+static inline struct route_table *
+rib_dest_table (rib_dest_t *dest)
+{
+  return dest->rnode->table;
+}
+
 #endif /*_ZEBRA_RIB_H */