diff options
author | 2017-10-09 08:35:38 +0000 | |
---|---|---|
committer | 2017-10-09 08:35:38 +0000 | |
commit | df4a15bc1fe47e27f4c1e62e865ee303c6e12c79 (patch) | |
tree | a59104b5975da8c5e1e2cfb35e2bffb33fc729ab /sys/netinet/tcp_usrreq.c | |
parent | Correct logic check preventing the device to attach. (diff) | |
download | wireguard-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.c | 127 |
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 */ |