summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authormvs <mvs@cvs.openbsd.org>2021-03-26 22:41:07 +0000
committermvs <mvs@cvs.openbsd.org>2021-03-26 22:41:07 +0000
commitc289c5aef6e9bcbe0f9a31a02e049d24f09f6b32 (patch)
tree1f37ca60e7d87be20ce3a309c95727ce4b977694 /sys/net
parentf48c36a771cc62d2dd17caee94cdf69b9202a0be (diff)
Push kernel lock within rtable_add(9) and rework it to return 0 in the
case when requested table is already exists. Except initialization time, route_output() and if_createrdomain() are the only paths where we call rtable_add(9). We check requested table existence by rtable_exists(9) and it's not the error condition if the table exists. Otherwise we are trying to create requested table by rtable_add(9). Those paths are kernel locked so concurrent thread can't create requested table just after rtable_exists(9) check. Also rtable_add(9) has internal rtable_exists(9) check and in this case the table existence assumed as EEXIST error. This error path is never reached. We are going to unlock PF_ROUTE sockets. This means route_output() will not be serialized with if_createrdomain() and concurrent thread could create requested table. Table existence check and creation should be serialized and it makes sense to do this within rtable_add(9). This time kernel lock is used for this so it pushed down to rtable_add(9). The internal rtable_exists(9) check was modified and table existence is not error now. Since the external rtable_exists(9) check is useless it was removed from if_createrdomain(). It still exists in route_output() path because the logic is more complicated here. ok mpi@
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if.c4
-rw-r--r--sys/net/rtable.c20
2 files changed, 14 insertions, 10 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index e5c5e65129d..c11710b75fc 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.c,v 1.639 2021/03/20 17:08:57 florian Exp $ */
+/* $OpenBSD: if.c,v 1.640 2021/03/26 22:41:06 mvs Exp $ */
/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
/*
@@ -1780,7 +1780,7 @@ if_createrdomain(int rdomain, struct ifnet *ifp)
char loifname[IFNAMSIZ];
unsigned int unit = rdomain;
- if (!rtable_exists(rdomain) && (error = rtable_add(rdomain)) != 0)
+ if ((error = rtable_add(rdomain)) != 0)
return (error);
if (!rtable_empty(rdomain))
return (EEXIST);
diff --git a/sys/net/rtable.c b/sys/net/rtable.c
index d88544e2a22..4d00cd101f7 100644
--- a/sys/net/rtable.c
+++ b/sys/net/rtable.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtable.c,v 1.73 2021/03/10 10:21:48 jsg Exp $ */
+/* $OpenBSD: rtable.c,v 1.74 2021/03/26 22:41:06 mvs Exp $ */
/*
* Copyright (c) 2014-2016 Martin Pieuchot
@@ -195,15 +195,15 @@ rtable_add(unsigned int id)
struct dommp *dmm;
sa_family_t af;
unsigned int off, alen;
- int i;
-
- KERNEL_ASSERT_LOCKED();
+ int i, error = 0;
if (id > RT_TABLEID_MAX)
return (EINVAL);
+ KERNEL_LOCK();
+
if (rtable_exists(id))
- return (EEXIST);
+ goto out;
for (i = 0; (dp = domains[i]) != NULL; i++) {
if (dp->dom_rtoffset == 0)
@@ -217,8 +217,10 @@ rtable_add(unsigned int id)
rtmap_grow(id + 1, af);
tbl = rtable_alloc(id, alen, off);
- if (tbl == NULL)
- return (ENOMEM);
+ if (tbl == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
map = srp_get_locked(&afmap[af2idx[af]]);
map->tbl[id] = tbl;
@@ -233,8 +235,10 @@ rtable_add(unsigned int id)
/* Use main rtable/rdomain by default. */
dmm = srp_get_locked(&afmap[0]);
dmm->value[id] = 0;
+out:
+ KERNEL_UNLOCK();
- return (0);
+ return (error);
}
void *