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/lib/memtypes.c b/lib/memtypes.c
index bbf9692..76dece2 100644
--- a/lib/memtypes.c
+++ b/lib/memtypes.c
@@ -82,6 +82,7 @@
{ MTYPE_RIB_QUEUE, "RIB process work queue" },
{ MTYPE_STATIC_IPV4, "Static IPv4 route" },
{ MTYPE_STATIC_IPV6, "Static IPv6 route" },
+ { MTYPE_RIB_DEST, "RIB destination" },
{ -1, NULL },
};
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index 4276f1d..4765824 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -107,7 +107,7 @@
rn = route_node_lookup (table, (struct prefix *)&p);
if (rn)
{
- for (newrib = rn->info; newrib; newrib = newrib->next)
+ RNODE_FOREACH_RIB (rn, newrib)
if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)
&& newrib->distance != DISTANCE_INFINITY)
zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, &rn->p, newrib);
@@ -127,7 +127,7 @@
rn = route_node_lookup (table, (struct prefix *)&p6);
if (rn)
{
- for (newrib = rn->info; newrib; newrib = newrib->next)
+ RNODE_FOREACH_RIB (rn, newrib)
if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)
&& newrib->distance != DISTANCE_INFINITY)
zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, &rn->p, newrib);
@@ -148,7 +148,7 @@
table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
if (table)
for (rn = route_top (table); rn; rn = route_next (rn))
- for (newrib = rn->info; newrib; newrib = newrib->next)
+ RNODE_FOREACH_RIB (rn, newrib)
if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)
&& newrib->type == type
&& newrib->distance != DISTANCE_INFINITY
@@ -159,7 +159,7 @@
table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
if (table)
for (rn = route_top (table); rn; rn = route_next (rn))
- for (newrib = rn->info; newrib; newrib = newrib->next)
+ RNODE_FOREACH_RIB (rn, newrib)
if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)
&& newrib->type == type
&& newrib->distance != DISTANCE_INFINITY
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 */
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 0e29e61..f0d5c9d 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -351,7 +351,7 @@
return 0;
/* Pick up selected route. */
- for (match = rn->info; match; match = match->next)
+ RNODE_FOREACH_RIB (rn, match)
{
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
continue;
@@ -452,7 +452,7 @@
return 0;
/* Pick up selected route. */
- for (match = rn->info; match; match = match->next)
+ RNODE_FOREACH_RIB (rn, match)
{
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
continue;
@@ -543,7 +543,7 @@
route_unlock_node (rn);
/* Pick up selected route. */
- for (match = rn->info; match; match = match->next)
+ RNODE_FOREACH_RIB (rn, match)
{
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
continue;
@@ -601,7 +601,7 @@
/* Unlock node. */
route_unlock_node (rn);
- for (match = rn->info; match; match = match->next)
+ RNODE_FOREACH_RIB (rn, match)
{
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
continue;
@@ -658,7 +658,7 @@
route_unlock_node (rn);
/* Find out if a "selected" RR for the discovered RIB entry exists ever. */
- for (match = rn->info; match; match = match->next)
+ RNODE_FOREACH_RIB (rn, match)
{
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
continue;
@@ -725,7 +725,7 @@
route_unlock_node (rn);
/* Pick up selected route. */
- for (match = rn->info; match; match = match->next)
+ RNODE_FOREACH_RIB (rn, match)
{
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
continue;
@@ -975,6 +975,61 @@
static void rib_unlink (struct route_node *, struct rib *);
+/*
+ * rib_can_delete_dest
+ *
+ * Returns TRUE if the given dest can be deleted from the table.
+ */
+static int
+rib_can_delete_dest (rib_dest_t *dest)
+{
+ if (dest->routes)
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * rib_gc_dest
+ *
+ * Garbage collect the rib dest corresponding to the given route node
+ * if appropriate.
+ *
+ * Returns TRUE if the dest was deleted, FALSE otherwise.
+ */
+int
+rib_gc_dest (struct route_node *rn)
+{
+ rib_dest_t *dest;
+ char buf[INET6_ADDRSTRLEN];
+
+ dest = rib_dest_from_rnode (rn);
+ if (!dest)
+ return 0;
+
+ if (!rib_can_delete_dest (dest))
+ return 0;
+
+ if (IS_ZEBRA_DEBUG_RIB)
+ {
+ inet_ntop (rn->p.family, &rn->p.u.prefix, buf, sizeof (buf));
+ zlog_debug ("%s: %s/%d: removing dest from table", __func__,
+ buf, rn->p.prefixlen);
+ }
+
+ dest->rnode = NULL;
+ XFREE (MTYPE_RIB_DEST, dest);
+ rn->info = NULL;
+
+ /*
+ * Release the one reference that we keep on the route node.
+ */
+ route_unlock_node (rn);
+ return 1;
+}
+
/* Core function for processing routing information base. */
static void
rib_process (struct route_node *rn)
@@ -993,13 +1048,8 @@
if (IS_ZEBRA_DEBUG_RIB || IS_ZEBRA_DEBUG_RIB_Q)
inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
- for (rib = rn->info; rib; rib = next)
+ RNODE_FOREACH_RIB_SAFE (rn, rib, next)
{
- /* The next pointer is saved, because current pointer
- * may be passed to rib_unlink() in the middle of iteration.
- */
- next = rib->next;
-
/* Currently installed rib. */
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
{
@@ -1017,7 +1067,7 @@
if (IS_ZEBRA_DEBUG_RIB)
zlog_debug ("%s: %s/%d: rn %p, removing rib %p", __func__,
buf, rn->p.prefixlen, rn, rib);
- rib_unlink (rn, rib);
+ rib_unlink (rn, rib);
}
else
del = rib;
@@ -1074,7 +1124,7 @@
/* metric tie-breaks equal distance */
if (rib->metric <= select->metric)
select = rib;
- } /* for (rib = rn->info; rib; rib = next) */
+ } /* RNODE_FOREACH_RIB_SAFE */
/* After the cycle is finished, the following pointers will be set:
* select --- the winner RIB entry, if any was found, otherwise NULL
@@ -1171,6 +1221,11 @@
end:
if (IS_ZEBRA_DEBUG_RIB_Q)
zlog_debug ("%s: %s/%d: rn %p dequeued", __func__, buf, rn->p.prefixlen, rn);
+
+ /*
+ * Check if the dest can be deleted now.
+ */
+ rib_gc_dest (rn);
}
/* Take a list of route_node structs and return 1, if there was a record
@@ -1189,8 +1244,9 @@
rnode = listgetdata (lnode);
rib_process (rnode);
- if (rnode->info) /* The first RIB record is holding the flags bitmask. */
- UNSET_FLAG (((struct rib *)rnode->info)->rn_status, RIB_ROUTE_QUEUED(qindex));
+ if (rnode->info)
+ UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex));
+
#if 0
else
{
@@ -1223,7 +1279,9 @@
return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
}
-/* Map from rib types to queue type (priority) in meta queue */
+/*
+ * Map from rib types to queue type (priority) in meta queue
+ */
static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
[ZEBRA_ROUTE_SYSTEM] = 4,
[ZEBRA_ROUTE_KERNEL] = 0,
@@ -1251,12 +1309,13 @@
if (IS_ZEBRA_DEBUG_RIB_Q)
inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
{
u_char qindex = meta_queue_map[rib->type];
/* Invariant: at this point we always have rn->info set. */
- if (CHECK_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex)))
+ if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags,
+ RIB_ROUTE_QUEUED (qindex)))
{
if (IS_ZEBRA_DEBUG_RIB_Q)
zlog_debug ("%s: %s/%d: rn %p is already queued in sub-queue %u",
@@ -1264,7 +1323,7 @@
continue;
}
- SET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex));
+ SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex));
listnode_add (mq->subq[qindex], rn);
route_lock_node (rn);
mq->size++;
@@ -1286,7 +1345,7 @@
inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
/* Pointless to queue a route_node with no RIB entries to add or remove */
- if (!rn->info)
+ if (!rnode_to_ribs (rn))
{
zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
__func__, rn, rn->lock);
@@ -1395,17 +1454,16 @@
* |-> set RIB_ENTRY_REMOVE |
* rib_delnode (RIB freed)
*
- *
- * Queueing state for a route_node is kept in the head RIB entry, this
- * state must be preserved as and when the head RIB entry of a
- * route_node is changed by rib_unlink / rib_link. A small complication,
- * but saves having to allocate a dedicated object for this.
+ * The 'info' pointer of a route_node points to a rib_dest_t
+ * ('dest'). Queueing state for a route_node is kept on the dest. The
+ * dest is created on-demand by rib_link() and is kept around at least
+ * as long as there are ribs hanging off it (@see rib_gc_dest()).
*
* Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
*
* - route_nodes: refcounted by:
- * - RIBs attached to route_node:
- * - managed by: rib_link/unlink
+ * - dest attached to route_node:
+ * - managed by: rib_link/rib_gc_dest
* - route_node processing queue
* - managed by: rib_addqueue, rib_process.
*
@@ -1416,12 +1474,11 @@
rib_link (struct route_node *rn, struct rib *rib)
{
struct rib *head;
+ rib_dest_t *dest;
char buf[INET6_ADDRSTRLEN];
-
+
assert (rib && rn);
- route_lock_node (rn); /* rn route table reference */
-
if (IS_ZEBRA_DEBUG_RIB)
{
inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
@@ -1429,18 +1486,28 @@
buf, rn->p.prefixlen, rn, rib);
}
- head = rn->info;
- if (head)
+ dest = rib_dest_from_rnode (rn);
+ if (!dest)
{
if (IS_ZEBRA_DEBUG_RIB)
- zlog_debug ("%s: %s/%d: new head, rn_status copied over", __func__,
- buf, rn->p.prefixlen);
+ {
+ zlog_debug ("%s: %s/%d: adding dest to table", __func__,
+ buf, rn->p.prefixlen);
+ }
+
+ dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t));
+ route_lock_node (rn); /* rn route table reference */
+ rn->info = dest;
+ dest->rnode = rn;
+ }
+
+ head = dest->routes;
+ if (head)
+ {
head->prev = rib;
- /* Transfer the rn status flags to the new head RIB */
- rib->rn_status = head->rn_status;
}
rib->next = head;
- rn->info = rib;
+ dest->routes = rib;
rib_queue_add (&zebrad, rn);
}
@@ -1465,11 +1532,21 @@
rib_link (rn, rib);
}
+/*
+ * rib_unlink
+ *
+ * Detach a rib structure from a route_node.
+ *
+ * Note that a call to rib_unlink() should be followed by a call to
+ * rib_gc_dest() at some point. This allows a rib_dest_t that is no
+ * longer required to be deleted.
+ */
static void
rib_unlink (struct route_node *rn, struct rib *rib)
{
struct nexthop *nexthop, *next;
char buf[INET6_ADDRSTRLEN];
+ rib_dest_t *dest;
assert (rn && rib);
@@ -1480,6 +1557,8 @@
__func__, buf, rn->p.prefixlen, rn, rib);
}
+ dest = rib_dest_from_rnode (rn);
+
if (rib->next)
rib->next->prev = rib->prev;
@@ -1487,15 +1566,7 @@
rib->prev->next = rib->next;
else
{
- rn->info = rib->next;
-
- if (rn->info)
- {
- if (IS_ZEBRA_DEBUG_RIB)
- zlog_debug ("%s: %s/%d: rn %p, rib %p, new head copy",
- __func__, buf, rn->p.prefixlen, rn, rib);
- rib->next->rn_status = rib->rn_status;
- }
+ dest->routes = rib->next;
}
/* free RIB and nexthops */
@@ -1506,7 +1577,6 @@
}
XFREE (MTYPE_RIB, rib);
- route_unlock_node (rn); /* rn route table reference */
}
static void
@@ -1561,7 +1631,7 @@
/* If same type of route are installed, treat it as a implicit
withdraw. */
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
{
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
continue;
@@ -1717,7 +1787,7 @@
route_unlock_node (rn);
/* let's go */
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
{
zlog_debug
(
@@ -1764,7 +1834,7 @@
* RIBQ record already on head. This is necessary for proper revalidation
* of the rest of the RIB.
*/
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
{
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
! RIB_SYSTEM_ROUTE (rib))
@@ -1816,7 +1886,7 @@
/* If same type of route are installed, treat it as a implicit
withdraw. */
- for (same = rn->info; same; same = same->next)
+ RNODE_FOREACH_RIB (rn, same)
{
if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
continue;
@@ -1907,7 +1977,7 @@
}
/* Lookup same type route. */
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
{
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
continue;
@@ -2000,7 +2070,7 @@
/* Lookup existing route */
rn = route_node_get (table, p);
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
{
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
continue;
@@ -2096,7 +2166,7 @@
if (! rn)
return;
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
{
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
continue;
@@ -2355,7 +2425,7 @@
/* If same type of route are installed, treat it as a implicit
withdraw. */
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
{
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
continue;
@@ -2458,7 +2528,7 @@
}
/* Lookup same type route. */
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
{
if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
continue;
@@ -2551,7 +2621,7 @@
/* Lookup existing route */
rn = route_node_get (table, p);
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
{
if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
continue;
@@ -2648,7 +2718,7 @@
if (! rn)
return;
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
{
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
continue;
@@ -2844,13 +2914,13 @@
table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
if (table)
for (rn = route_top (table); rn; rn = route_next (rn))
- if (rn->info)
+ if (rnode_to_ribs (rn))
rib_queue_add (&zebrad, rn);
table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
if (table)
for (rn = route_top (table); rn; rn = route_next (rn))
- if (rn->info)
+ if (rnode_to_ribs (rn))
rib_queue_add (&zebrad, rn);
}
@@ -2865,10 +2935,8 @@
if (table)
for (rn = route_top (table); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = next)
+ RNODE_FOREACH_RIB_SAFE (rn, rib, next)
{
- next = rib->next;
-
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
continue;
@@ -2897,10 +2965,8 @@
if (table)
for (rn = route_top (table); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = next)
+ RNODE_FOREACH_RIB_SAFE (rn, rib, next)
{
- next = rib->next;
-
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
continue;
@@ -2933,9 +2999,8 @@
if (table)
for (rn = route_top (table); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = next)
+ RNODE_FOREACH_RIB_SAFE (rn, rib, next)
{
- next = rib->next;
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
continue;
if (rib->type == proto)
@@ -2965,11 +3030,13 @@
if (table)
for (rn = route_top (table); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
{
- if (! RIB_SYSTEM_ROUTE (rib)
- && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
- rib_uninstall_kernel (rn, rib);
+ if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
+ continue;
+
+ if (! RIB_SYSTEM_ROUTE (rib))
+ rib_uninstall_kernel (rn, rib);
}
}
diff --git a/zebra/zebra_snmp.c b/zebra/zebra_snmp.c
index f52bbcb..e06e144 100644
--- a/zebra/zebra_snmp.c
+++ b/zebra/zebra_snmp.c
@@ -150,7 +150,7 @@
/* Return number of routing entries. */
result = 0;
for (rn = route_top (table); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
result++;
return (u_char *)&result;
@@ -175,7 +175,7 @@
/* Return number of routing entries. */
result = 0;
for (rn = route_top (table); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
result++;
return (u_char *)&result;
@@ -369,7 +369,7 @@
{
if (!in_addr_cmp(&(*np)->p.u.prefix, (u_char *)&dest))
{
- for (*rib = (*np)->info; *rib; *rib = (*rib)->next)
+ RNODE_FOREACH_RIB (*np, *rib)
{
if (!in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4,
(u_char *)&nexthop))
@@ -388,12 +388,12 @@
/* Check destination first */
if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) > 0)
- for (rib2 = np2->info; rib2; rib2 = rib2->next)
+ RNODE_FOREACH_RIB (np2, rib2)
check_replace(np2, rib2, np, rib);
if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) == 0)
{ /* have to look at each rib individually */
- for (rib2 = np2->info; rib2; rib2 = rib2->next)
+ RNODE_FOREACH_RIB (np2, rib2)
{
int proto2, policy2;
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 743c13f..d07b09c 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -535,7 +535,7 @@
struct rib *rib;
struct nexthop *nexthop;
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
{
vty_out (vty, "Routing entry for %s/%d%s",
inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
@@ -822,7 +822,7 @@
/* Show all IPv4 routes. */
for (rn = route_top (table); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
{
if (first)
{
@@ -863,7 +863,7 @@
/* Show matched type IPv4 routes. */
for (rn = route_top (table); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
if (prefix_match (&p, &rn->p))
{
if (first)
@@ -896,7 +896,7 @@
/* Show matched type IPv4 routes. */
for (rn = route_top (table); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
{
addr = ntohl (rn->p.u.prefix4.s_addr);
@@ -942,7 +942,7 @@
/* Show matched type IPv4 routes. */
for (rn = route_top (table); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
if (rib->type == type)
{
if (first)
@@ -1046,7 +1046,7 @@
memset (&rib_cnt, 0, sizeof(rib_cnt));
memset (&fib_cnt, 0, sizeof(fib_cnt));
for (rn = route_top (table); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
{
rib_cnt[ZEBRA_ROUTE_TOTAL]++;
@@ -1219,7 +1219,7 @@
/* Show all IPv4 routes. */
for (rn = route_top (table); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
{
if (first)
{
@@ -1546,7 +1546,7 @@
struct nexthop *nexthop;
char buf[BUFSIZ];
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
{
vty_out (vty, "Routing entry for %s/%d%s",
inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
@@ -1795,7 +1795,7 @@
/* Show all IPv6 route. */
for (rn = route_top (table); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
{
if (first)
{
@@ -1836,7 +1836,7 @@
/* Show matched type IPv6 routes. */
for (rn = route_top (table); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
if (prefix_match (&p, &rn->p))
{
if (first)
@@ -1876,7 +1876,7 @@
/* Show matched type IPv6 routes. */
for (rn = route_top (table); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
if (rib->type == type)
{
if (first)
@@ -2008,7 +2008,7 @@
/* Show all IPv6 route. */
for (rn = route_top (table); rn; rn = route_next (rn))
- for (rib = rn->info; rib; rib = rib->next)
+ RNODE_FOREACH_RIB (rn, rib)
{
if (first)
{