Index | Thread | Search

From:
Vitaliy Makkoveev <mvs@openbsd.org>
Subject:
tcp, sysctl: unlock TCPCTL_REASS_LIMIT and TCPCTL_SACKHOLE_LIMIT
To:
Alexander Bluhm <bluhm@openbsd.org>, tech@openbsd.org
Date:
Sat, 10 May 2025 08:00:27 +0300

Download raw body.

Thread
They are identical, so unlock them both. The temporary `tcp_sysctl_lock'
and the pool_sethardlimit() serialization are useless because we are
serialized with sysctl_lock rwlock(9). However I want to do this
serialization for consistency reason. I will replace `tcp_sysctl_lock'
with `sysctl_lock' after tcp_sysctl() unlocked.

Index: sys/netinet/tcp_usrreq.c
===================================================================
RCS file: /cvs/src/sys/netinet/tcp_usrreq.c,v
retrieving revision 1.245
diff -u -p -r1.245 tcp_usrreq.c
--- sys/netinet/tcp_usrreq.c	10 Mar 2025 15:11:46 -0000	1.245
+++ sys/netinet/tcp_usrreq.c	10 May 2025 04:54:26 -0000
@@ -1405,6 +1405,9 @@ tcp_sysctl_tcpstat(void *oldp, size_t *o
 	    &tcpstat, sizeof(tcpstat)));
 }
 
+/* XXXSMP: temporary, until tcp_sysctl() unlocked */
+struct rwlock tcp_sysctl_lock = RWLOCK_INITIALIZER("tcpctllk");
+
 /*
  * Sysctl for tcp variables.
  */
@@ -1442,29 +1445,34 @@ tcp_sysctl(int *name, u_int namelen, voi
 		return tcp_ident(oldp, oldlenp, newp, newlen, 1);
 
 	case TCPCTL_REASS_LIMIT:
-		NET_LOCK();
-		nval = tcp_reass_limit;
-		error = sysctl_int(oldp, oldlenp, newp, newlen, &nval);
-		if (!error && nval != tcp_reass_limit) {
-			error = pool_sethardlimit(&tcpqe_pool, nval, NULL, 0);
-			if (!error)
-				tcp_reass_limit = nval;
+	case TCPCTL_SACKHOLE_LIMIT: {
+		struct pool *pool;
+		int *var;
+
+		if (name[0] == TCPCTL_REASS_LIMIT) {
+			pool = &tcpqe_pool;
+			var = &tcp_reass_limit;
+		} else {
+			pool = &sackhl_pool;
+			var = &tcp_sackhole_limit;
 		}
-		NET_UNLOCK();
-		return (error);
 
-	case TCPCTL_SACKHOLE_LIMIT:
-		NET_LOCK();
-		nval = tcp_sackhole_limit;
+		oval = nval = atomic_load_int(var);
 		error = sysctl_int(oldp, oldlenp, newp, newlen, &nval);
-		if (!error && nval != tcp_sackhole_limit) {
-			error = pool_sethardlimit(&sackhl_pool, nval, NULL, 0);
-			if (!error)
-				tcp_sackhole_limit = nval;
+
+		if (error == 0 && oval != nval) {
+			rw_enter_write(&tcp_sysctl_lock);
+			if (nval != atomic_load_int(var)) {
+				error = pool_sethardlimit(pool, nval,
+				    NULL, 0);
+				if (error == 0)
+					atomic_store_int(var, nval);
+			}
+			rw_exit_write(&tcp_sysctl_lock);
 		}
-		NET_UNLOCK();
-		return (error);
 
+		return (error);
+	}
 	case TCPCTL_STATS:
 		return (tcp_sysctl_tcpstat(oldp, oldlenp, newp));