lib: prepare table code for reuse by bgp_table

* lib/table.[ch]

    - Add a macro (ROUTE_NODE_FIELDS) that expands to all the fields
      of a route_node structure.

    - Add the route_table_delegate_t structure, a function vector
      which allows clients to customize the behavior of one or more
      tables.

      The delegate currently contains the 'create_node' and
      'destroy_node' functions, and hence enables a table to use an
      alternative node structure. The alternative node is expected to
      embed the fields of a route_node using ROUTE_NODE_FIELDS.

    - Add route_table_init_with_delegate() to create a new table with
      a given delegate.

    - Make route_table_init() a thin wrapper around
      route_table_init_with_delegate(). The delegate it passes in
      simply creates/destroys route_node structures as before.

    - Add a user data pointer (info) to the route_table
      structure. This can be used by a client to keep per-table state.

Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
Avneesh Sachdev 2012-08-17 08:19:48 -07:00 committed by David Lamparter
parent 3eb8ef37bc
commit f9c1b7bb9b
2 changed files with 120 additions and 26 deletions

View File

@ -30,12 +30,17 @@
static void route_node_delete (struct route_node *); static void route_node_delete (struct route_node *);
static void route_table_free (struct route_table *); static void route_table_free (struct route_table *);
/*
* route_table_init_with_delegate
*/
struct route_table * struct route_table *
route_table_init (void) route_table_init_with_delegate (route_table_delegate_t *delegate)
{ {
struct route_table *rt; struct route_table *rt;
rt = XCALLOC (MTYPE_ROUTE_TABLE, sizeof (struct route_table)); rt = XCALLOC (MTYPE_ROUTE_TABLE, sizeof (struct route_table));
rt->delegate = delegate;
return rt; return rt;
} }
@ -47,11 +52,9 @@ route_table_finish (struct route_table *rt)
/* Allocate new route node. */ /* Allocate new route node. */
static struct route_node * static struct route_node *
route_node_new (void) route_node_new (struct route_table *table)
{ {
struct route_node *node; return table->delegate->create_node (table->delegate, table);
node = XCALLOC (MTYPE_ROUTE_NODE, sizeof (struct route_node));
return node;
} }
/* Allocate new route node with prefix set. */ /* Allocate new route node with prefix set. */
@ -60,7 +63,7 @@ route_node_set (struct route_table *table, struct prefix *prefix)
{ {
struct route_node *node; struct route_node *node;
node = route_node_new (); node = route_node_new (table);
prefix_copy (&node->p, prefix); prefix_copy (&node->p, prefix);
node->table = table; node->table = table;
@ -70,9 +73,9 @@ route_node_set (struct route_table *table, struct prefix *prefix)
/* Free route node. */ /* Free route node. */
static void static void
route_node_free (struct route_node *node) route_node_free (struct route_table *table, struct route_node *node)
{ {
XFREE (MTYPE_ROUTE_NODE, node); table->delegate->destroy_node (table->delegate, table, node);
} }
/* Free route table. */ /* Free route table. */
@ -109,7 +112,7 @@ route_table_free (struct route_table *rt)
tmp_node->table->count--; tmp_node->table->count--;
tmp_node->lock = 0; /* to cause assert if unlocked after this */ tmp_node->lock = 0; /* to cause assert if unlocked after this */
route_node_free (tmp_node); route_node_free (rt, tmp_node);
if (node != NULL) if (node != NULL)
{ {
@ -314,7 +317,7 @@ route_node_get (struct route_table *const table, struct prefix *p)
} }
else else
{ {
new = route_node_new (); new = route_node_new (table);
route_common (&node->p, p, &new->p); route_common (&node->p, p, &new->p);
new->p.family = p->family; new->p.family = p->family;
new->table = table; new->table = table;
@ -374,7 +377,7 @@ route_node_delete (struct route_node *node)
node->table->count--; node->table->count--;
route_node_free (node); route_node_free (node->table, node);
/* If parent node is stub then delete it also. */ /* If parent node is stub then delete it also. */
if (parent && parent->lock == 0) if (parent && parent->lock == 0)
@ -482,3 +485,46 @@ route_table_count (const struct route_table *table)
{ {
return table->count; return table->count;
} }
/**
* route_node_create
*
* Default function for creating a route node.
*/
static struct route_node *
route_node_create (route_table_delegate_t *delegate,
struct route_table *table)
{
struct route_node *node;
node = XCALLOC (MTYPE_ROUTE_NODE, sizeof (struct route_node));
return node;
}
/**
* route_node_destroy
*
* Default function for destroying a route node.
*/
static void
route_node_destroy (route_table_delegate_t *delegate,
struct route_table *table, struct route_node *node)
{
XFREE (MTYPE_ROUTE_NODE, node);
}
/*
* Default delegate.
*/
static route_table_delegate_t default_delegate = {
.create_node = route_node_create,
.destroy_node = route_node_destroy
};
/*
* route_table_init
*/
struct route_table *
route_table_init (void)
{
return route_table_init_with_delegate (&default_delegate);
}

View File

@ -23,39 +23,87 @@
#ifndef _ZEBRA_TABLE_H #ifndef _ZEBRA_TABLE_H
#define _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. */ /* Routing table top structure. */
struct route_table struct route_table
{ {
struct route_node *top; struct route_node *top;
/*
* Delegate that performs certain functions for this table.
*/
route_table_delegate_t *delegate;
unsigned long count; 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. */ /* Each routing entry. */
struct route_node struct route_node
{ {
/* Actual prefix of this radix. */ ROUTE_NODE_FIELDS;
struct prefix p;
/* Tree link. */
struct route_table *table;
struct route_node *parent;
struct route_node *link[2];
#define l_left link[0] #define l_left link[0]
#define l_right link[1] #define l_right link[1]
/* Lock of this radix */
unsigned int lock;
/* Each node of route. */
void *info;
/* Aggregation. */
void *aggregate;
}; };
/* Prototypes. */ /* Prototypes. */
extern struct route_table *route_table_init (void); 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_table_finish (struct route_table *);
extern void route_unlock_node (struct route_node *node); extern void route_unlock_node (struct route_node *node);
extern struct route_node *route_top (struct route_table *); extern struct route_node *route_top (struct route_table *);