diff options
| author | David Lamparter <equinox@opensourcerouting.org> | 2016-12-05 19:43:38 +0100 |
|---|---|---|
| committer | David Lamparter <equinox@opensourcerouting.org> | 2016-12-05 19:48:38 +0100 |
| commit | 53dc2b05c76f4f5cd6a72373fb241afdcedb2ee1 (patch) | |
| tree | d43e2f4f851f368dcc943a9b30e73ff603ea5bc1 /lib/ns.c | |
| parent | 0577b824e137f143c899a567b1bbeb109841c796 (diff) | |
| parent | 8793176b5a180bff8e637ce7cba6005f880e8915 (diff) | |
Merge branch 'stable/2.0'
Conflicts:
bgpd/bgp_route.c
lib/if.c
ripd/rip_interface.c
zebra/interface.c
zebra/zebra_vty.c
Diffstat (limited to 'lib/ns.c')
| -rw-r--r-- | lib/ns.c | 309 |
1 files changed, 28 insertions, 281 deletions
@@ -31,8 +31,6 @@ #include "if.h" #include "ns.h" -#include "prefix.h" -#include "table.h" #include "log.h" #include "memory.h" @@ -41,7 +39,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) */ @@ -91,22 +95,6 @@ static int have_netns(void) #endif } -struct ns -{ - /* Identifier, same as the vector index */ - ns_id_t ns_id; - /* Name */ - char *name; - /* File descriptor */ - int fd; - - /* Master list of interfaces belonging to this NS */ - struct list *iflist; - - /* User data */ - void *info; -}; - /* Holding NS hooks */ struct ns_master { @@ -116,44 +104,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. @@ -188,6 +162,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); @@ -198,18 +173,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)); } /* @@ -310,217 +276,6 @@ ns_add_hook (int type, int (*func)(ns_id_t, void **)) } } -/* Return the iterator of the first NS. */ -ns_iter_t -ns_first (void) -{ - struct route_node *rn; - - for (rn = route_top (ns_table); rn; rn = route_next (rn)) - if (rn->info) - { - route_unlock_node (rn); /* top/next */ - return (ns_iter_t)rn; - } - return NS_ITER_INVALID; -} - -/* Return the next NS iterator to the given iterator. */ -ns_iter_t -ns_next (ns_iter_t iter) -{ - struct route_node *rn = NULL; - - /* Lock it first because route_next() will unlock it. */ - if (iter != NS_ITER_INVALID) - rn = route_next (route_lock_node ((struct route_node *)iter)); - - for (; rn; rn = route_next (rn)) - if (rn->info) - { - route_unlock_node (rn); /* next */ - return (ns_iter_t)rn; - } - return NS_ITER_INVALID; -} - -/* Return the NS iterator of the given NS ID. If it does not exist, - * the iterator of the next existing NS is returned. */ -ns_iter_t -ns_iterator (ns_id_t ns_id) -{ - struct prefix p; - struct route_node *rn; - - ns_build_key (ns_id, &p); - rn = route_node_get (ns_table, &p); - if (rn->info) - { - /* OK, the NS exists. */ - route_unlock_node (rn); /* get */ - return (ns_iter_t)rn; - } - - /* Find the next NS. */ - for (rn = route_next (rn); rn; rn = route_next (rn)) - if (rn->info) - { - route_unlock_node (rn); /* next */ - return (ns_iter_t)rn; - } - - return NS_ITER_INVALID; -} - -/* Obtain the NS ID from the given NS iterator. */ -ns_id_t -ns_iter2id (ns_iter_t iter) -{ - struct route_node *rn = (struct route_node *) iter; - return (rn && rn->info) ? ((struct ns *)rn->info)->ns_id : NS_DEFAULT; -} - -/* Obtain the data pointer from the given NS iterator. */ -void * -ns_iter2info (ns_iter_t iter) -{ - struct route_node *rn = (struct route_node *) iter; - return (rn && rn->info) ? ((struct ns *)rn->info)->info : NULL; -} - -/* Obtain the interface list from the given NS iterator. */ -struct list * -ns_iter2iflist (ns_iter_t iter) -{ - struct route_node *rn = (struct route_node *) iter; - return (rn && rn->info) ? ((struct ns *)rn->info)->iflist : NULL; -} - -/* Get the data pointer of the specified NS. If not found, create one. */ -void * -ns_info_get (ns_id_t ns_id) -{ - struct ns *ns = ns_get (ns_id); - return ns->info; -} - -/* Look up the data pointer of the specified NS. */ -void * -ns_info_lookup (ns_id_t ns_id) -{ - struct ns *ns = ns_lookup (ns_id); - return ns ? ns->info : NULL; -} - -/* Look up the interface list in a NS. */ -struct list * -ns_iflist (ns_id_t ns_id) -{ - struct ns * ns = ns_lookup (ns_id); - return ns ? ns->iflist : NULL; -} - -/* Get the interface list of the specified NS. Create one if not find. */ -struct list * -ns_iflist_get (ns_id_t ns_id) -{ - struct ns * ns = ns_get (ns_id); - return ns->iflist; -} - -/* - * NS bit-map - */ - -#define NS_BITMAP_NUM_OF_GROUPS 8 -#define NS_BITMAP_NUM_OF_BITS_IN_GROUP \ - (UINT16_MAX / NS_BITMAP_NUM_OF_GROUPS) -#define NS_BITMAP_NUM_OF_BYTES_IN_GROUP \ - (NS_BITMAP_NUM_OF_BITS_IN_GROUP / CHAR_BIT + 1) /* +1 for ensure */ - -#define NS_BITMAP_GROUP(_id) \ - ((_id) / NS_BITMAP_NUM_OF_BITS_IN_GROUP) -#define NS_BITMAP_BIT_OFFSET(_id) \ - ((_id) % NS_BITMAP_NUM_OF_BITS_IN_GROUP) - -#define NS_BITMAP_INDEX_IN_GROUP(_bit_offset) \ - ((_bit_offset) / CHAR_BIT) -#define NS_BITMAP_FLAG(_bit_offset) \ - (((u_char)1) << ((_bit_offset) % CHAR_BIT)) - -struct ns_bitmap -{ - u_char *groups[NS_BITMAP_NUM_OF_GROUPS]; -}; - -ns_bitmap_t -ns_bitmap_init (void) -{ - return (ns_bitmap_t) XCALLOC (MTYPE_NS_BITMAP, sizeof (struct ns_bitmap)); -} - -void -ns_bitmap_free (ns_bitmap_t bmap) -{ - struct ns_bitmap *bm = (struct ns_bitmap *) bmap; - int i; - - if (bmap == NS_BITMAP_NULL) - return; - - for (i = 0; i < NS_BITMAP_NUM_OF_GROUPS; i++) - if (bm->groups[i]) - XFREE (MTYPE_NS_BITMAP, bm->groups[i]); - - XFREE (MTYPE_NS_BITMAP, bm); -} - -void -ns_bitmap_set (ns_bitmap_t bmap, ns_id_t ns_id) -{ - struct ns_bitmap *bm = (struct ns_bitmap *) bmap; - u_char group = NS_BITMAP_GROUP (ns_id); - u_char offset = NS_BITMAP_BIT_OFFSET (ns_id); - - if (bmap == NS_BITMAP_NULL) - return; - - if (bm->groups[group] == NULL) - bm->groups[group] = XCALLOC (MTYPE_NS_BITMAP, - NS_BITMAP_NUM_OF_BYTES_IN_GROUP); - - SET_FLAG (bm->groups[group][NS_BITMAP_INDEX_IN_GROUP (offset)], - NS_BITMAP_FLAG (offset)); -} - -void -ns_bitmap_unset (ns_bitmap_t bmap, ns_id_t ns_id) -{ - struct ns_bitmap *bm = (struct ns_bitmap *) bmap; - u_char group = NS_BITMAP_GROUP (ns_id); - u_char offset = NS_BITMAP_BIT_OFFSET (ns_id); - - if (bmap == NS_BITMAP_NULL || bm->groups[group] == NULL) - return; - - UNSET_FLAG (bm->groups[group][NS_BITMAP_INDEX_IN_GROUP (offset)], - NS_BITMAP_FLAG (offset)); -} - -int -ns_bitmap_check (ns_bitmap_t bmap, ns_id_t ns_id) -{ - struct ns_bitmap *bm = (struct ns_bitmap *) bmap; - u_char group = NS_BITMAP_GROUP (ns_id); - u_char offset = NS_BITMAP_BIT_OFFSET (ns_id); - - if (bmap == NS_BITMAP_NULL || bm->groups[group] == NULL) - return 0; - - return CHECK_FLAG (bm->groups[group][NS_BITMAP_INDEX_IN_GROUP (offset)], - NS_BITMAP_FLAG (offset)) ? 1 : 0; -} - /* * NS realization with NETNS */ @@ -645,17 +400,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; } @@ -666,9 +421,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) @@ -700,15 +452,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. */ |
