diff options
author | Renato Westphal <renato@opensourcerouting.org> | 2016-10-29 03:03:35 +0200 |
---|---|---|
committer | Renato Westphal <renato@opensourcerouting.org> | 2016-11-28 19:18:35 +0100 |
commit | c7fdd84f36a262d062a10c1439121df361ab78d3 (patch) | |
tree | 31751b0f29e4c778abd74aafab19807dffff86e9 /lib | |
parent | zebra: nuke zvrf_list and always use vrf_list instead (diff) | |
download | frr-c7fdd84f36a262d062a10c1439121df361ab78d3.tar.xz frr-c7fdd84f36a262d062a10c1439121df361ab78d3.zip |
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>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ns.c | 81 | ||||
-rw-r--r-- | lib/ns.h | 9 |
2 files changed, 37 insertions, 53 deletions
@@ -31,8 +31,6 @@ #include "if.h" #include "ns.h" -#include "prefix.h" -#include "table.h" #include "log.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_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 #define CLONE_NEWNET 0x40000000 /* New network namespace (lo, device, names sockets, etc) */ #endif @@ -100,44 +105,30 @@ struct ns_master int (*ns_disable_hook) (ns_id_t, void **); } ns_master = {0,}; -/* NS table */ -struct route_table *ns_table = NULL; - static int ns_is_enabled (struct ns *ns); static int ns_enable (struct ns *ns); static void ns_disable (struct ns *ns); - -/* Build the table key */ -static void -ns_build_key (ns_id_t ns_id, struct prefix *p) +static __inline int +ns_compare(struct ns *a, struct ns *b) { - p->family = AF_INET; - p->prefixlen = IPV4_MAX_BITLEN; - p->u.prefix4.s_addr = ns_id; + return (a->ns_id - b->ns_id); } /* Get a NS. If not found, create one. */ static struct ns * ns_get (ns_id_t ns_id) { - struct prefix p; - struct route_node *rn; struct ns *ns; - ns_build_key (ns_id, &p); - rn = route_node_get (ns_table, &p); - if (rn->info) - { - ns = (struct ns *)rn->info; - route_unlock_node (rn); /* get */ - return ns; - } + ns = ns_lookup (ns_id); + if (ns) + return (ns); ns = XCALLOC (MTYPE_NS, sizeof (struct ns)); ns->ns_id = ns_id; ns->fd = -1; - rn->info = ns; + RB_INSERT (ns_head, &ns_tree, ns); /* * Initialize interfaces. @@ -172,6 +163,7 @@ ns_delete (struct ns *ns) */ //if_terminate (&ns->iflist); + RB_REMOVE (ns_head, &ns_tree, ns); if (ns->name) XFREE (MTYPE_NS_NAME, ns->name); @@ -182,18 +174,9 @@ ns_delete (struct ns *ns) static struct ns * ns_lookup (ns_id_t ns_id) { - struct prefix p; - struct route_node *rn; - struct ns *ns = NULL; - - 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; + struct ns ns; + ns.ns_id = ns_id; + return (RB_FIND (ns_head, &ns_tree, &ns)); } /* @@ -414,17 +397,17 @@ static struct cmd_node ns_node = static int ns_config_write (struct vty *vty) { - struct route_node *rn; struct ns *ns; int write = 0; - for (rn = route_top (ns_table); rn; rn = route_next (rn)) - if ((ns = rn->info) != NULL && - ns->ns_id != NS_DEFAULT && ns->name) - { - vty_out (vty, "logical-router %u netns %s%s", ns->ns_id, ns->name, VTY_NEWLINE); - write++; - } + RB_FOREACH (ns, ns_head, &ns_tree) { + if (ns->ns_id == NS_DEFAULT || ns->name == NULL) + continue; + + vty_out (vty, "logical-router %u netns %s%s", ns->ns_id, ns->name, + VTY_NEWLINE); + write = 1; + } return write; } @@ -435,9 +418,6 @@ ns_init (void) { struct ns *default_ns; - /* Allocate NS table. */ - ns_table = route_table_init (); - /* The default NS always exists. */ default_ns = ns_get (NS_DEFAULT); if (!default_ns) @@ -469,15 +449,10 @@ ns_init (void) void ns_terminate (void) { - struct route_node *rn; struct ns *ns; - for (rn = route_top (ns_table); rn; rn = route_next (rn)) - if ((ns = rn->info) != NULL) - ns_delete (ns); - - route_table_finish (ns_table); - ns_table = NULL; + while ((ns = RB_ROOT (&ns_tree)) != NULL) + ns_delete (ns); } /* Create a socket for the NS. */ @@ -23,6 +23,7 @@ #ifndef _ZEBRA_NS_H #define _ZEBRA_NS_H +#include "openbsd-tree.h" #include "linklist.h" typedef u_int16_t ns_id_t; @@ -35,10 +36,14 @@ typedef u_int16_t ns_id_t; struct ns { + RB_ENTRY(ns) entry; + /* Identifier, same as the vector index */ ns_id_t ns_id; + /* Name */ char *name; + /* File descriptor */ int fd; @@ -48,6 +53,10 @@ struct ns /* User data */ void *info; }; +RB_HEAD (ns_head, ns); +RB_PROTOTYPE (ns_head, ns, entry, ns_compare) + +extern struct ns_head ns_tree; /* * NS hooks |