lib: convert namespace code to use red-black trees

We definitely need to stop abusing the route table data structure when
it's not necessary.  Convert the namespace code to use red-black trees
instead. This greatly improves code readability.

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
Renato Westphal 2016-10-28 23:03:35 -02:00
parent 51bdc5f85c
commit c7fdd84f36
2 changed files with 37 additions and 53 deletions

View File

@ -31,8 +31,6 @@
#include "if.h" #include "if.h"
#include "ns.h" #include "ns.h"
#include "prefix.h"
#include "table.h"
#include "log.h" #include "log.h"
#include "memory.h" #include "memory.h"
@ -43,6 +41,13 @@ DEFINE_MTYPE_STATIC(LIB, NS, "Logical-Router")
DEFINE_MTYPE_STATIC(LIB, NS_NAME, "Logical-Router Name") DEFINE_MTYPE_STATIC(LIB, NS_NAME, "Logical-Router Name")
DEFINE_MTYPE_STATIC(LIB, NS_BITMAP, "Logical-Router bit-map") DEFINE_MTYPE_STATIC(LIB, NS_BITMAP, "Logical-Router bit-map")
static __inline int ns_compare (struct ns *, struct ns *);
static struct ns *ns_lookup (ns_id_t);
RB_GENERATE (ns_head, ns, entry, ns_compare)
struct ns_head ns_tree = RB_INITIALIZER (&ns_tree);
#ifndef CLONE_NEWNET #ifndef CLONE_NEWNET
#define CLONE_NEWNET 0x40000000 /* New network namespace (lo, device, names sockets, etc) */ #define CLONE_NEWNET 0x40000000 /* New network namespace (lo, device, names sockets, etc) */
#endif #endif
@ -100,44 +105,30 @@ struct ns_master
int (*ns_disable_hook) (ns_id_t, void **); int (*ns_disable_hook) (ns_id_t, void **);
} ns_master = {0,}; } ns_master = {0,};
/* NS table */
struct route_table *ns_table = NULL;
static int ns_is_enabled (struct ns *ns); static int ns_is_enabled (struct ns *ns);
static int ns_enable (struct ns *ns); static int ns_enable (struct ns *ns);
static void ns_disable (struct ns *ns); static void ns_disable (struct ns *ns);
static __inline int
/* Build the table key */ ns_compare(struct ns *a, struct ns *b)
static void
ns_build_key (ns_id_t ns_id, struct prefix *p)
{ {
p->family = AF_INET; return (a->ns_id - b->ns_id);
p->prefixlen = IPV4_MAX_BITLEN;
p->u.prefix4.s_addr = ns_id;
} }
/* Get a NS. If not found, create one. */ /* Get a NS. If not found, create one. */
static struct ns * static struct ns *
ns_get (ns_id_t ns_id) ns_get (ns_id_t ns_id)
{ {
struct prefix p;
struct route_node *rn;
struct ns *ns; struct ns *ns;
ns_build_key (ns_id, &p); ns = ns_lookup (ns_id);
rn = route_node_get (ns_table, &p); if (ns)
if (rn->info) return (ns);
{
ns = (struct ns *)rn->info;
route_unlock_node (rn); /* get */
return ns;
}
ns = XCALLOC (MTYPE_NS, sizeof (struct ns)); ns = XCALLOC (MTYPE_NS, sizeof (struct ns));
ns->ns_id = ns_id; ns->ns_id = ns_id;
ns->fd = -1; ns->fd = -1;
rn->info = ns; RB_INSERT (ns_head, &ns_tree, ns);
/* /*
* Initialize interfaces. * Initialize interfaces.
@ -172,6 +163,7 @@ ns_delete (struct ns *ns)
*/ */
//if_terminate (&ns->iflist); //if_terminate (&ns->iflist);
RB_REMOVE (ns_head, &ns_tree, ns);
if (ns->name) if (ns->name)
XFREE (MTYPE_NS_NAME, ns->name); XFREE (MTYPE_NS_NAME, ns->name);
@ -182,18 +174,9 @@ ns_delete (struct ns *ns)
static struct ns * static struct ns *
ns_lookup (ns_id_t ns_id) ns_lookup (ns_id_t ns_id)
{ {
struct prefix p; struct ns ns;
struct route_node *rn; ns.ns_id = ns_id;
struct ns *ns = NULL; return (RB_FIND (ns_head, &ns_tree, &ns));
ns_build_key (ns_id, &p);
rn = route_node_lookup (ns_table, &p);
if (rn)
{
ns = (struct ns *)rn->info;
route_unlock_node (rn); /* lookup */
}
return ns;
} }
/* /*
@ -414,16 +397,16 @@ static struct cmd_node ns_node =
static int static int
ns_config_write (struct vty *vty) ns_config_write (struct vty *vty)
{ {
struct route_node *rn;
struct ns *ns; struct ns *ns;
int write = 0; int write = 0;
for (rn = route_top (ns_table); rn; rn = route_next (rn)) RB_FOREACH (ns, ns_head, &ns_tree) {
if ((ns = rn->info) != NULL && if (ns->ns_id == NS_DEFAULT || ns->name == NULL)
ns->ns_id != NS_DEFAULT && ns->name) continue;
{
vty_out (vty, "logical-router %u netns %s%s", ns->ns_id, ns->name, VTY_NEWLINE); vty_out (vty, "logical-router %u netns %s%s", ns->ns_id, ns->name,
write++; VTY_NEWLINE);
write = 1;
} }
return write; return write;
@ -435,9 +418,6 @@ ns_init (void)
{ {
struct ns *default_ns; struct ns *default_ns;
/* Allocate NS table. */
ns_table = route_table_init ();
/* The default NS always exists. */ /* The default NS always exists. */
default_ns = ns_get (NS_DEFAULT); default_ns = ns_get (NS_DEFAULT);
if (!default_ns) if (!default_ns)
@ -469,15 +449,10 @@ ns_init (void)
void void
ns_terminate (void) ns_terminate (void)
{ {
struct route_node *rn;
struct ns *ns; struct ns *ns;
for (rn = route_top (ns_table); rn; rn = route_next (rn)) while ((ns = RB_ROOT (&ns_tree)) != NULL)
if ((ns = rn->info) != NULL)
ns_delete (ns); ns_delete (ns);
route_table_finish (ns_table);
ns_table = NULL;
} }
/* Create a socket for the NS. */ /* Create a socket for the NS. */

View File

@ -23,6 +23,7 @@
#ifndef _ZEBRA_NS_H #ifndef _ZEBRA_NS_H
#define _ZEBRA_NS_H #define _ZEBRA_NS_H
#include "openbsd-tree.h"
#include "linklist.h" #include "linklist.h"
typedef u_int16_t ns_id_t; typedef u_int16_t ns_id_t;
@ -35,10 +36,14 @@ typedef u_int16_t ns_id_t;
struct ns struct ns
{ {
RB_ENTRY(ns) entry;
/* Identifier, same as the vector index */ /* Identifier, same as the vector index */
ns_id_t ns_id; ns_id_t ns_id;
/* Name */ /* Name */
char *name; char *name;
/* File descriptor */ /* File descriptor */
int fd; int fd;
@ -48,6 +53,10 @@ struct ns
/* User data */ /* User data */
void *info; void *info;
}; };
RB_HEAD (ns_head, ns);
RB_PROTOTYPE (ns_head, ns, entry, ns_compare)
extern struct ns_head ns_tree;
/* /*
* NS hooks * NS hooks