diff options
Diffstat (limited to 'zebra')
| -rw-r--r-- | zebra/rib.h | 52 | ||||
| -rw-r--r-- | zebra/zebra_rib.c | 103 | 
2 files changed, 155 insertions, 0 deletions
diff --git a/zebra/rib.h b/zebra/rib.h index c98d99a4..4f99d714 100644 --- a/zebra/rib.h +++ b/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 */ diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 2cbee935..5c75b909 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -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; +}  | 
