summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2015-10-14 10:09:31 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2015-10-14 10:09:31 +0000
commitba713922bfb5e418eb0ecbeff735a08d37bb330a (patch)
tree8fd2aecd29dc0d9dc84102584fbf69dff13dbe2e
parentf3f1a2b45b7111f8b56d40f4837ebb02ff6dccf3 (diff)
Rewrite the logic around the dymanic array of routing tables to help
turning rtable_get(9) MP-safe. Use only one per-AF array, as suggested by claudio@, pointing to an array of pointers to the routing table heads. Routing tables are now allocated/initialized per-AF. This will let us allocate routing table on-demand instead of always having an AF_INET, AF_MPLS and AF_INET table as soon as a new rtableID is used. This also get rid of the "void ***" madness. ok dlg@, jmatthew@
-rw-r--r--sys/net/art.c4
-rw-r--r--sys/net/art.h4
-rw-r--r--sys/net/route.c6
-rw-r--r--sys/net/rtable.c208
4 files changed, 131 insertions, 91 deletions
diff --git a/sys/net/art.c b/sys/net/art.c
index 74f13a0b39e..0f8c1182c92 100644
--- a/sys/net/art.c
+++ b/sys/net/art.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: art.c,v 1.4 2015/10/07 10:50:35 mpi Exp $ */
+/* $OpenBSD: art.c,v 1.5 2015/10/14 10:09:30 mpi Exp $ */
/*
* Copyright (c) 2015 Martin Pieuchot
@@ -79,7 +79,7 @@ int art_table_walk(struct art_table *,
* Per routing table initialization API function.
*/
struct art_root *
-art_attach(unsigned int rtableid, int off)
+art_alloc(unsigned int rtableid, int off)
{
struct art_root *ar;
int i;
diff --git a/sys/net/art.h b/sys/net/art.h
index 0c97e96ef84..d433d4751c6 100644
--- a/sys/net/art.h
+++ b/sys/net/art.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: art.h,v 1.3 2015/10/07 10:50:35 mpi Exp $ */
+/* $OpenBSD: art.h,v 1.4 2015/10/14 10:09:30 mpi Exp $ */
/*
* Copyright (c) 2015 Martin Pieuchot
@@ -50,7 +50,7 @@ struct art_node {
};
void art_init(void);
-struct art_root *art_attach(unsigned int, int);
+struct art_root *art_alloc(unsigned int, int);
struct art_node *art_insert(struct art_root *, struct art_node *, uint8_t *,
int);
struct art_node *art_delete(struct art_root *, struct art_node *, uint8_t *,
diff --git a/sys/net/route.c b/sys/net/route.c
index 861a43294c9..fcf62811f6f 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: route.c,v 1.250 2015/10/13 09:59:37 mpi Exp $ */
+/* $OpenBSD: route.c,v 1.251 2015/10/14 10:09:30 mpi Exp $ */
/* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */
/*
@@ -139,7 +139,6 @@
/* Give some jitter to hash, to avoid synchronization between routers. */
static uint32_t rt_hashjitter;
-extern void ***rtables;
extern unsigned int rtables_id_max;
struct rtstat rtstat;
@@ -1657,9 +1656,6 @@ rt_if_track(struct ifnet *ifp)
int i;
u_int tid;
- if (rtables == NULL)
- return;
-
for (tid = 0; tid <= rtables_id_max; tid++) {
/* skip rtables that are not in the rdomain of the ifp */
if (rtable_l2(tid) != ifp->if_rdomain)
diff --git a/sys/net/rtable.c b/sys/net/rtable.c
index 7aee943965d..90a8cc10db7 100644
--- a/sys/net/rtable.c
+++ b/sys/net/rtable.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtable.c,v 1.11 2015/10/07 11:39:49 mpi Exp $ */
+/* $OpenBSD: rtable.c,v 1.12 2015/10/14 10:09:30 mpi Exp $ */
/*
* Copyright (c) 2014-2015 Martin Pieuchot
@@ -28,16 +28,21 @@
#include <net/route.h>
uint8_t af2idx[AF_MAX+1]; /* To only allocate supported AF */
-uint8_t af2idx_max = 1; /* Must have NULL at index 0 */
+uint8_t af2idx_max;
-void ***rtables; /* Array of routing tables */
-unsigned int rtables_id_max = 0;
-unsigned int *rtables2dom; /* rtable to domain lookup table */
+union rtmap {
+ void **tbl;
+ unsigned int *dom;
+};
+
+union rtmap *rtmap; /* Array of per domain routing table */
+unsigned int rtables_id_max;
void rtable_init_backend(unsigned int);
-int rtable_attach(unsigned int, sa_family_t, int);
+void *rtable_alloc(unsigned int, sa_family_t, unsigned int);
+void rtable_free(unsigned int);
+void rtable_grow(unsigned int, sa_family_t);
void *rtable_get(unsigned int, sa_family_t);
-void rtable_set(unsigned int, sa_family_t, void *);
void
rtable_init(void)
@@ -46,6 +51,8 @@ rtable_init(void)
unsigned int keylen = 0;
int i;
+ /* We use index 0 for the rtable/rdomain map. */
+ af2idx_max = 1;
memset(af2idx, 0, sizeof(af2idx));
/*
@@ -57,92 +64,139 @@ rtable_init(void)
af2idx[dp->dom_family] = af2idx_max++;
if (dp->dom_rtkeylen > keylen)
keylen = dp->dom_rtkeylen;
+
+ }
+
+ rtables_id_max = 0;
+ rtmap = mallocarray(af2idx_max + 1, sizeof(*rtmap), M_RTABLE, M_WAITOK);
+
+ /* Start with a single table for every domain that requires it. */
+ for (i = 0; i < af2idx_max + 1; i++) {
+ rtmap[i].tbl = mallocarray(1, sizeof(rtmap[0].tbl),
+ M_RTABLE, M_WAITOK|M_ZERO);
}
rtable_init_backend(keylen);
}
+void
+rtable_grow(unsigned int id, sa_family_t af)
+{
+ void **tbl, **ntbl;
+ int i;
+
+ KASSERT(id > rtables_id_max);
+
+ KERNEL_ASSERT_LOCKED();
+
+ tbl = rtmap[af2idx[af]].tbl;
+ ntbl = mallocarray(id + 1, sizeof(rtmap[0].tbl), M_RTABLE, M_WAITOK);
+
+ for (i = 0; i < rtables_id_max + 1; i++)
+ ntbl[i] = tbl[i];
+
+ while (i < id + 1) {
+ ntbl[i] = NULL;
+ i++;
+ }
+
+ rtmap[af2idx[af]].tbl = ntbl;
+ free(tbl, M_RTABLE, (rtables_id_max + 1) * sizeof(rtmap[0].tbl));
+}
+
int
rtable_add(unsigned int id)
{
- struct domain *dp;
- void *p, *q;
- int i, rv = 0;
+ struct domain *dp;
+ void *rtbl;
+ sa_family_t af;
+ unsigned int off;
+ int i;
- if (id > RT_TABLEID_MAX)
+ if (id > RT_TABLEID_MAX || rtable_exists(id))
return (EINVAL);
- if (id == 0 || id > rtables_id_max) {
- if ((p = mallocarray(id + 1, sizeof(void *), M_RTABLE,
- M_NOWAIT|M_ZERO)) == NULL)
- return (ENOMEM);
+ for (i = 0; (dp = domains[i]) != NULL; i++) {
+ if (dp->dom_rtoffset == 0)
+ continue;
+
+ af = dp->dom_family;
+ off = dp->dom_rtoffset;
+
+ if (id > rtables_id_max)
+ rtable_grow(id, af);
- if ((q = mallocarray(id + 1, sizeof(unsigned int), M_RTABLE,
- M_NOWAIT|M_ZERO)) == NULL) {
- free(p, M_RTABLE, (id + 1) * sizeof(void *));
+ rtbl = rtable_alloc(id, af, off);
+ if (rtbl == NULL)
return (ENOMEM);
- }
- if (rtables) {
- memcpy(p, rtables, (rtables_id_max+1) * sizeof(void *));
- free(rtables, M_RTABLE,
- (rtables_id_max+1) * sizeof(void *));
-
- memcpy(q, rtables2dom,
- (rtables_id_max+1) * sizeof(unsigned int));
- free(rtables2dom, M_RTABLE,
- (rtables_id_max+1) * sizeof(unsigned int));
- }
- rtables = p;
- rtables2dom = q;
+
+ rtmap[af2idx[af]].tbl[id] = rtbl;
+ }
+
+ /* Reflect possible growth. */
+ if (id > rtables_id_max) {
+ rtable_grow(id, 0);
rtables_id_max = id;
}
- if (rtables[id] != NULL) /* already exists */
- return (EEXIST);
+ /* Use main rtable/rdomain by default. */
+ rtmap[0].dom[id] = 0;
+
- rtables2dom[id] = 0; /* use main table/domain by default */
- rtables[id] = mallocarray(af2idx_max + 1, sizeof(void *), M_RTABLE,
- M_NOWAIT|M_ZERO);
- if (rtables[id] == NULL)
- return (ENOMEM);
+ return (0);
+}
+
+void
+rtable_del(unsigned int id)
+{
+ struct domain *dp;
+ sa_family_t af;
+ int i;
+
+ if (id > rtables_id_max || !rtable_exists(id))
+ return;
- /* Per domain initialization. */
for (i = 0; (dp = domains[i]) != NULL; i++) {
if (dp->dom_rtoffset == 0)
continue;
- rv |= rtable_attach(id, dp->dom_family, dp->dom_rtoffset);
- }
- return (rv);
+ af = dp->dom_family;
+
+ rtable_free(id);
+ rtmap[af2idx[af]].tbl[id] = NULL;
+ }
}
+
void *
rtable_get(unsigned int rtableid, sa_family_t af)
{
- if (rtableid > rtables_id_max)
+ if (af >= nitems(af2idx) || rtableid > rtables_id_max)
return (NULL);
- return (rtables[rtableid] ? rtables[rtableid][af2idx[af]] : NULL);
-}
-void
-rtable_set(unsigned int rtableid, sa_family_t af, void *p)
-{
- if (rtableid > rtables_id_max)
- return;
+ if (af2idx[af] == 0 || rtmap[af2idx[af]].tbl == NULL)
+ return (NULL);
- if (rtables[rtableid])
- rtables[rtableid][af2idx[af]] = p;
+ return (rtmap[af2idx[af]].tbl[rtableid]);
}
int
rtable_exists(unsigned int rtableid)
{
+ struct domain *dp;
+ int i;
+
if (rtableid > rtables_id_max)
return (0);
- if (rtables[rtableid] == NULL)
- return (0);
+ for (i = 0; (dp = domains[i]) != NULL; i++) {
+ if (dp->dom_rtoffset == 0)
+ continue;
- return (1);
+ if (rtable_get(rtableid, dp->dom_family) != NULL)
+ return (1);
+ }
+
+ return (0);
}
unsigned int
@@ -151,7 +205,7 @@ rtable_l2(unsigned int rtableid)
if (rtableid > rtables_id_max)
return (0);
- return (rtables2dom[rtableid]);
+ return (rtmap[0].dom[rtableid]);
}
void
@@ -160,7 +214,7 @@ rtable_l2set(unsigned int rtableid, unsigned int parent)
if (!rtable_exists(rtableid) || !rtable_exists(parent))
return;
- rtables2dom[rtableid] = parent;
+ rtmap[0].dom[rtableid] = parent;
}
#ifndef ART
@@ -170,27 +224,24 @@ rtable_init_backend(unsigned int keylen)
rn_init(keylen); /* initialize all zeroes, all ones, mask table */
}
-int
-rtable_attach(unsigned int rtableid, sa_family_t af, int off)
+void *
+rtable_alloc(unsigned int rtableid, sa_family_t af, unsigned int off)
{
- struct radix_node_head *rnh;
- int rv = 1;
-
- rnh = rtable_get(rtableid, af);
- if (rnh != NULL)
- return (EEXIST);
+ struct radix_node_head *rnh = NULL;
if (rn_inithead((void **)&rnh, off)) {
#ifndef SMALL_KERNEL
rnh->rnh_multipath = 1;
#endif /* SMALL_KERNEL */
rnh->rnh_rtableid = rtableid;
- rv = 0;
}
- rtable_set(rtableid, af, rnh);
+ return (rnh);
+}
- return (rv);
+void
+rtable_free(unsigned int rtableid)
+{
}
struct rtentry *
@@ -393,22 +444,15 @@ rtable_init_backend(unsigned int keylen)
pool_init(&an_pool, sizeof(struct art_node), 0, 0, 0, "art node", NULL);
}
-int
-rtable_attach(unsigned int rtableid, sa_family_t af, int off)
+void *
+rtable_alloc(unsigned int rtableid, sa_family_t af, unsigned int off)
{
- struct art_root *ar;
-
- ar = rtable_get(rtableid, af);
- if (ar != NULL)
- return (EEXIST);
-
- ar = art_attach(rtableid, off);
- if (ar == NULL)
- return (ENOMEM);
-
- rtable_set(rtableid, af, ar);
+ return (art_alloc(rtableid, off));
+}
- return (0);
+void
+rtable_free(unsigned int rtableid)
+{
}
struct rtentry *