summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_usrreq.c
diff options
context:
space:
mode:
authormpi <mpi@openbsd.org>2017-10-09 08:35:38 +0000
committermpi <mpi@openbsd.org>2017-10-09 08:35:38 +0000
commitdf4a15bc1fe47e27f4c1e62e865ee303c6e12c79 (patch)
treea59104b5975da8c5e1e2cfb35e2bffb33fc729ab /sys/netinet/tcp_usrreq.c
parentCorrect logic check preventing the device to attach. (diff)
downloadwireguard-openbsd-df4a15bc1fe47e27f4c1e62e865ee303c6e12c79.tar.xz
wireguard-openbsd-df4a15bc1fe47e27f4c1e62e865ee303c6e12c79.zip
Reduces the scope of the NET_LOCK() in sysctl(2) path.
Exposes per-CPU counters to real parrallelism. ok visa@, bluhm@, jca@
Diffstat (limited to 'sys/netinet/tcp_usrreq.c')
-rw-r--r--sys/netinet/tcp_usrreq.c127
1 files changed, 75 insertions, 52 deletions
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 1ff211b69ae..1e70b9e07c9 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_usrreq.c,v 1.155 2017/09/05 07:59:11 mpi Exp $ */
+/* $OpenBSD: tcp_usrreq.c,v 1.156 2017/10/09 08:35:38 mpi Exp $ */
/* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */
/*
@@ -955,8 +955,6 @@ tcp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
{
int error, nval;
- NET_ASSERT_LOCKED();
-
/* All sysctl names at this level are terminal. */
if (namelen != 1)
return (ENOTDIR);
@@ -964,73 +962,91 @@ tcp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
switch (name[0]) {
#ifdef TCP_SACK
case TCPCTL_SACK:
- return (sysctl_int(oldp, oldlenp, newp, newlen,
- &tcp_do_sack));
+ NET_LOCK();
+ error = sysctl_int(oldp, oldlenp, newp, newlen,
+ &tcp_do_sack);
+ NET_UNLOCK();
+ return (error);
#endif
case TCPCTL_SLOWHZ:
return (sysctl_rdint(oldp, oldlenp, newp, PR_SLOWHZ));
case TCPCTL_BADDYNAMIC:
- return (sysctl_struct(oldp, oldlenp, newp, newlen,
- baddynamicports.tcp, sizeof(baddynamicports.tcp)));
+ NET_LOCK();
+ error = sysctl_struct(oldp, oldlenp, newp, newlen,
+ baddynamicports.tcp, sizeof(baddynamicports.tcp));
+ NET_UNLOCK();
+ return (error);
case TCPCTL_ROOTONLY:
if (newp && securelevel > 0)
return (EPERM);
- return (sysctl_struct(oldp, oldlenp, newp, newlen,
- rootonlyports.tcp, sizeof(rootonlyports.tcp)));
+ NET_LOCK();
+ error = sysctl_struct(oldp, oldlenp, newp, newlen,
+ rootonlyports.tcp, sizeof(rootonlyports.tcp));
+ NET_UNLOCK();
+ return (error);
case TCPCTL_IDENT:
- return (tcp_ident(oldp, oldlenp, newp, newlen, 0));
+ NET_LOCK();
+ error = tcp_ident(oldp, oldlenp, newp, newlen, 0);
+ NET_UNLOCK();
+ return (error);
case TCPCTL_DROP:
- return (tcp_ident(oldp, oldlenp, newp, newlen, 1));
+ NET_LOCK();
+ error = tcp_ident(oldp, oldlenp, newp, newlen, 1);
+ NET_UNLOCK();
+ return (error);
case TCPCTL_ALWAYS_KEEPALIVE:
- return (sysctl_int(oldp, oldlenp, newp, newlen,
- &tcp_always_keepalive));
+ NET_LOCK();
+ error = sysctl_int(oldp, oldlenp, newp, newlen,
+ &tcp_always_keepalive);
+ NET_UNLOCK();
+ return (error);
#ifdef TCP_ECN
case TCPCTL_ECN:
- return (sysctl_int(oldp, oldlenp, newp, newlen,
- &tcp_do_ecn));
+ NET_LOCK();
+ error = sysctl_int(oldp, oldlenp, newp, newlen,
+ &tcp_do_ecn);
+ NET_UNLOCK();
+ return (error);
#endif
case TCPCTL_REASS_LIMIT:
+ NET_LOCK();
nval = tcp_reass_limit;
error = sysctl_int(oldp, oldlenp, newp, newlen, &nval);
- if (error)
- return (error);
- if (nval != tcp_reass_limit) {
+ if (!error && nval != tcp_reass_limit) {
error = pool_sethardlimit(&tcpqe_pool, nval, NULL, 0);
- if (error)
- return (error);
- tcp_reass_limit = nval;
+ if (!error)
+ tcp_reass_limit = nval;
}
- return (0);
+ NET_UNLOCK();
+ return (error);
#ifdef TCP_SACK
case TCPCTL_SACKHOLE_LIMIT:
+ NET_LOCK();
nval = tcp_sackhole_limit;
error = sysctl_int(oldp, oldlenp, newp, newlen, &nval);
- if (error)
- return (error);
- if (nval != tcp_sackhole_limit) {
+ if (!error && nval != tcp_sackhole_limit) {
error = pool_sethardlimit(&sackhl_pool, nval, NULL, 0);
- if (error)
- return (error);
- tcp_sackhole_limit = nval;
+ if (!error)
+ tcp_sackhole_limit = nval;
}
- return (0);
+ NET_UNLOCK();
+ return (error);
#endif
case TCPCTL_STATS:
return (tcp_sysctl_tcpstat(oldp, oldlenp, newp));
case TCPCTL_SYN_USE_LIMIT:
+ NET_LOCK();
error = sysctl_int(oldp, oldlenp, newp, newlen,
&tcp_syn_use_limit);
- if (error)
- return (error);
- if (newp != NULL) {
+ if (!error && newp != NULL) {
/*
* Global tcp_syn_use_limit is used when reseeding a
* new cache. Also update the value in active cache.
@@ -1040,33 +1056,40 @@ tcp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
if (tcp_syn_cache[1].scs_use > tcp_syn_use_limit)
tcp_syn_cache[1].scs_use = tcp_syn_use_limit;
}
- return (0);
+ NET_UNLOCK();
+ return (error);
case TCPCTL_SYN_HASH_SIZE:
+ NET_LOCK();
nval = tcp_syn_hash_size;
error = sysctl_int(oldp, oldlenp, newp, newlen, &nval);
- if (error)
- return (error);
- if (nval != tcp_syn_hash_size) {
- if (nval < 1 || nval > 100000)
- return (EINVAL);
- /*
- * If global hash size has been changed, switch sets as
- * soon as possible. Then the actual hash array will
- * be reallocated.
- */
- if (tcp_syn_cache[0].scs_size != nval)
- tcp_syn_cache[0].scs_use = 0;
- if (tcp_syn_cache[1].scs_size != nval)
- tcp_syn_cache[1].scs_use = 0;
- tcp_syn_hash_size = nval;
+ if (!error && nval != tcp_syn_hash_size) {
+ if (nval < 1 || nval > 100000) {
+ error = EINVAL;
+ } else {
+ /*
+ * If global hash size has been changed,
+ * switch sets as soon as possible. Then
+ * the actual hash array will be reallocated.
+ */
+ if (tcp_syn_cache[0].scs_size != nval)
+ tcp_syn_cache[0].scs_use = 0;
+ if (tcp_syn_cache[1].scs_size != nval)
+ tcp_syn_cache[1].scs_use = 0;
+ tcp_syn_hash_size = nval;
+ }
}
- return (0);
+ NET_UNLOCK();
+ return (error);
default:
- if (name[0] < TCPCTL_MAXID)
- return (sysctl_int_arr(tcpctl_vars, name, namelen,
- oldp, oldlenp, newp, newlen));
+ if (name[0] < TCPCTL_MAXID) {
+ NET_LOCK();
+ error = sysctl_int_arr(tcpctl_vars, name, namelen,
+ oldp, oldlenp, newp, newlen);
+ NET_UNLOCK();
+ return (error);
+ }
return (ENOPROTOOPT);
}
/* NOTREACHED */