forked from Mirror/frr
zebra: add iterator for walking all tables in RIB
* lib/zebra.h Add macro ZEBRA_NUM_OF, which returns the number of elements in a static array. * zebra/rib.h Add the rib_tables_iter_t structure and associated functions, which allow one to walk all tables in the rib. * zebra/zebra_rib.c - Add vrf_id_get_next() to retrieve the first VRF id (if any) that is greater than a given VRF id. - Add rib_tables_iter_next(). Signed-off-by: Avneesh Sachdev <avneesh@opensourcerouting.org> Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
parent
1b5ed1b054
commit
0915bb0ce2
|
@ -387,6 +387,8 @@ struct in_pktinfo
|
|||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define ZEBRA_NUM_OF(x) (sizeof (x) / sizeof (x[0]))
|
||||
|
||||
/* For old definition. */
|
||||
#ifndef IN6_ARE_ADDR_EQUAL
|
||||
#define IN6_ARE_ADDR_EQUAL IN6_IS_ADDR_EQUAL
|
||||
|
|
52
zebra/rib.h
52
zebra/rib.h
|
@ -286,6 +286,25 @@ typedef struct rib_table_info_t_
|
|||
|
||||
} rib_table_info_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
RIB_TABLES_ITER_S_INIT,
|
||||
RIB_TABLES_ITER_S_ITERATING,
|
||||
RIB_TABLES_ITER_S_DONE
|
||||
} rib_tables_iter_state_t;
|
||||
|
||||
/*
|
||||
* Structure that holds state for iterating over all tables in the
|
||||
* Routing Information Base.
|
||||
*/
|
||||
typedef struct rib_tables_iter_t_
|
||||
{
|
||||
uint32_t vrf_id;
|
||||
int afi_safi_ix;
|
||||
|
||||
rib_tables_iter_state_t state;
|
||||
} rib_tables_iter_t;
|
||||
|
||||
extern struct nexthop *nexthop_ifindex_add (struct rib *, unsigned int);
|
||||
extern struct nexthop *nexthop_ifname_add (struct rib *, char *);
|
||||
extern struct nexthop *nexthop_blackhole_add (struct rib *);
|
||||
|
@ -374,6 +393,7 @@ static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
|
|||
#endif /* HAVE_IPV6 */
|
||||
|
||||
extern int rib_gc_dest (struct route_node *rn);
|
||||
extern struct route_table *rib_tables_iter_next (rib_tables_iter_t *iter);
|
||||
|
||||
/*
|
||||
* Inline functions.
|
||||
|
@ -453,4 +473,36 @@ rib_dest_vrf (rib_dest_t *dest)
|
|||
return rib_table_info (rib_dest_table (dest))->vrf;
|
||||
}
|
||||
|
||||
/*
|
||||
* rib_tables_iter_init
|
||||
*/
|
||||
static inline void
|
||||
rib_tables_iter_init (rib_tables_iter_t *iter)
|
||||
|
||||
{
|
||||
memset (iter, 0, sizeof (*iter));
|
||||
iter->state = RIB_TABLES_ITER_S_INIT;
|
||||
}
|
||||
|
||||
/*
|
||||
* rib_tables_iter_started
|
||||
*
|
||||
* Returns TRUE if this iterator has started iterating over the set of
|
||||
* tables.
|
||||
*/
|
||||
static inline int
|
||||
rib_tables_iter_started (rib_tables_iter_t *iter)
|
||||
{
|
||||
return iter->state != RIB_TABLES_ITER_S_INIT;
|
||||
}
|
||||
|
||||
/*
|
||||
* rib_tables_iter_cleanup
|
||||
*/
|
||||
static inline void
|
||||
rib_tables_iter_cleanup (rib_tables_iter_t *iter)
|
||||
{
|
||||
iter->state = RIB_TABLES_ITER_S_DONE;
|
||||
}
|
||||
|
||||
#endif /*_ZEBRA_RIB_H */
|
||||
|
|
|
@ -3077,3 +3077,106 @@ rib_init (void)
|
|||
/* VRF initialization. */
|
||||
vrf_init ();
|
||||
}
|
||||
|
||||
/*
|
||||
* vrf_id_get_next
|
||||
*
|
||||
* Get the first vrf id that is greater than the given vrf id if any.
|
||||
*
|
||||
* Returns TRUE if a vrf id was found, FALSE otherwise.
|
||||
*/
|
||||
static inline int
|
||||
vrf_id_get_next (uint32_t id, uint32_t *next_id_p)
|
||||
{
|
||||
while (++id < vector_active (vrf_vector))
|
||||
{
|
||||
if (vrf_lookup (id))
|
||||
{
|
||||
*next_id_p = id;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* rib_tables_iter_next
|
||||
*
|
||||
* Returns the next table in the iteration.
|
||||
*/
|
||||
struct route_table *
|
||||
rib_tables_iter_next (rib_tables_iter_t *iter)
|
||||
{
|
||||
struct route_table *table;
|
||||
|
||||
/*
|
||||
* Array that helps us go over all AFI/SAFI combinations via one
|
||||
* index.
|
||||
*/
|
||||
static struct {
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
} afi_safis[] = {
|
||||
{ AFI_IP, SAFI_UNICAST },
|
||||
{ AFI_IP, SAFI_MULTICAST },
|
||||
{ AFI_IP6, SAFI_UNICAST },
|
||||
{ AFI_IP6, SAFI_MULTICAST },
|
||||
};
|
||||
|
||||
table = NULL;
|
||||
|
||||
switch (iter->state)
|
||||
{
|
||||
|
||||
case RIB_TABLES_ITER_S_INIT:
|
||||
iter->vrf_id = 0;
|
||||
iter->afi_safi_ix = -1;
|
||||
|
||||
/* Fall through */
|
||||
|
||||
case RIB_TABLES_ITER_S_ITERATING:
|
||||
iter->afi_safi_ix++;
|
||||
while (1)
|
||||
{
|
||||
|
||||
while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis))
|
||||
{
|
||||
table = vrf_table (afi_safis[iter->afi_safi_ix].afi,
|
||||
afi_safis[iter->afi_safi_ix].safi,
|
||||
iter->vrf_id);
|
||||
if (table)
|
||||
break;
|
||||
|
||||
iter->afi_safi_ix++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Found another table in this vrf.
|
||||
*/
|
||||
if (table)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Done with all tables in the current vrf, go to the next
|
||||
* one.
|
||||
*/
|
||||
if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id))
|
||||
break;
|
||||
|
||||
iter->afi_safi_ix = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RIB_TABLES_ITER_S_DONE:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (table)
|
||||
iter->state = RIB_TABLES_ITER_S_ITERATING;
|
||||
else
|
||||
iter->state = RIB_TABLES_ITER_S_DONE;
|
||||
|
||||
return table;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue