/* * Routing Table * Copyright (C) 1998 Kunihiro Ishiguro * * This file is part of GNU Zebra. * * GNU Zebra is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * GNU Zebra is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #ifndef _ZEBRA_TABLE_H #define _ZEBRA_TABLE_H /* * Forward declarations. */ struct route_node; struct route_table; /* * route_table_delegate_t * * Function vector that can be used by a client to customize the * behavior of one or more route tables. */ typedef struct route_table_delegate_t_ route_table_delegate_t; typedef struct route_node * (*route_table_create_node_func_t) (route_table_delegate_t *, struct route_table *); typedef void (*route_table_destroy_node_func_t) (route_table_delegate_t *, struct route_table *, struct route_node *); struct route_table_delegate_t_ { route_table_create_node_func_t create_node; route_table_destroy_node_func_t destroy_node; }; /* Routing table top structure. */ struct route_table { struct route_node *top; /* * Delegate that performs certain functions for this table. */ route_table_delegate_t *delegate; unsigned long count; /* * User data. */ void *info; }; /* * Macro that defines all fields in a route node. */ #define ROUTE_NODE_FIELDS \ /* Actual prefix of this radix. */ \ struct prefix p; \ \ /* Tree link. */ \ struct route_table *table; \ struct route_node *parent; \ struct route_node *link[2]; \ \ /* Lock of this radix */ \ unsigned int lock; \ \ /* Each node of route. */ \ void *info; \ \ /* Aggregation. */ \ void *aggregate; /* Each routing entry. */ struct route_node { ROUTE_NODE_FIELDS; #define l_left link[0] #define l_right link[1] }; typedef struct route_table_iter_t_ route_table_iter_t; typedef enum { RT_ITER_STATE_INIT, RT_ITER_STATE_ITERATING, RT_ITER_STATE_PAUSED, RT_ITER_STATE_DONE } route_table_iter_state_t; /* * route_table_iter_t * * Structure that holds state for iterating over a route table. */ struct route_table_iter_t_ { route_table_iter_state_t state; /* * Routing table that we are iterating over. The caller must ensure * that that table outlives the iterator. */ struct route_table *table; /* * The node that the iterator is currently on. */ struct route_node *current; /* * The last prefix that the iterator processed before it was paused. */ struct prefix pause_prefix; }; /* Prototypes. */ extern struct route_table *route_table_init (void); extern struct route_table * route_table_init_with_delegate (route_table_delegate_t *); extern void route_table_finish (struct route_table *); extern void route_unlock_node (struct route_node *node); extern struct route_node *route_top (struct route_table *); extern struct route_node *route_next (struct route_node *); extern struct route_node *route_next_until (struct route_node *, struct route_node *); extern struct route_node *route_node_get (struct route_table *const, struct prefix *); extern struct route_node *route_node_lookup (const struct route_table *, struct prefix *); extern struct route_node *route_lock_node (struct route_node *node); extern struct route_node *route_node_match (const struct route_table *, const struct prefix *); extern struct route_node *route_node_match_ipv4 (const struct route_table *, const struct in_addr *); #ifdef HAVE_IPV6 extern struct route_node *route_node_match_ipv6 (const struct route_table *, const struct in6_addr *); #endif /* HAVE_IPV6 */ extern unsigned long route_table_count (const struct route_table *); extern struct route_node * route_table_get_next (const struct route_table *table, struct prefix *p); extern int route_table_prefix_iter_cmp (struct prefix *p1, struct prefix *p2); /* * Iterator functions. */ extern void route_table_iter_init (route_table_iter_t *iter, struct route_table *table); extern void route_table_iter_pause (route_table_iter_t *iter); extern void route_table_iter_cleanup (route_table_iter_t *iter); /* * Inline functions. */ /* * route_table_iter_next * * Get the next node in the tree. */ static inline struct route_node * route_table_iter_next (route_table_iter_t * iter) { struct route_node *node; switch (iter->state) { case RT_ITER_STATE_INIT: /* * We're just starting the iteration. */ node = route_top (iter->table); break; case RT_ITER_STATE_ITERATING: node = route_next (iter->current); break; case RT_ITER_STATE_PAUSED: /* * Start with the node following pause_prefix. */ node = route_table_get_next (iter->table, &iter->pause_prefix); break; case RT_ITER_STATE_DONE: return NULL; default: assert (0); } iter->current = node; if (node) iter->state = RT_ITER_STATE_ITERATING; else iter->state = RT_ITER_STATE_DONE; return node; } /* * route_table_iter_is_done * * Returns TRUE if the iteration is complete. */ static inline int route_table_iter_is_done (route_table_iter_t *iter) { return iter->state == RT_ITER_STATE_DONE; } /* * route_table_iter_started * * Returns TRUE if this iterator has started iterating over the tree. */ static inline int route_table_iter_started (route_table_iter_t *iter) { return iter->state != RT_ITER_STATE_INIT; } #endif /* _ZEBRA_TABLE_H */