The branch main has been updated by rscheff:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=2d01998e9e8ab3081d7f586d59dc41a487bb5f0c

commit 2d01998e9e8ab3081d7f586d59dc41a487bb5f0c
Author:     Richard Scheffenegger <[email protected]>
AuthorDate: 2026-07-28 20:42:25 +0000
Commit:     Richard Scheffenegger <[email protected]>
CommitDate: 2026-07-28 21:13:20 +0000

    tcp_hostcache: ensure expire and prune values stay consistent with each 
other
    
        When configuring the expire timeout to something short, make sure that 
the
        prune time runs at least at that interval. Similarly, when adjusting the
        prune interval up, ensure the expire timeout reflect that expected 
minimum
        time also. Finally, restart the callout timer so that the next pruning
        happens after the new, expected interval.
    
    Reviewed By:            glebius
    MFC after:              2 weeks
    Sponsored by:           NetApp, Inc.
    Differential Revision:  https://reviews.freebsd.org/D58424
---
 sys/netinet/tcp_hostcache.c | 64 +++++++++++++++++++++++++++++++++++++--------
 1 file changed, 53 insertions(+), 11 deletions(-)

diff --git a/sys/netinet/tcp_hostcache.c b/sys/netinet/tcp_hostcache.c
index 2ed035b6fd06..7a5e2ef095ec 100644
--- a/sys/netinet/tcp_hostcache.c
+++ b/sys/netinet/tcp_hostcache.c
@@ -128,9 +128,9 @@ struct tcp_hostcache {
        u_int           bucket_limit;
        u_int           cache_count;
        u_int           cache_limit;
-       int             expire;
-       int             prune;
-       int             purgeall;
+       u_int           expire;
+       u_int           prune;
+       u_int           purgeall;
 };
 
 /* Arbitrary values */
@@ -146,6 +146,8 @@ VNET_DEFINE_STATIC(struct callout, tcp_hc_callout);
 #define        V_tcp_hc_callout        VNET(tcp_hc_callout)
 
 static struct hc_metrics *tcp_hc_lookup(const struct in_conninfo *);
+static int sysctl_tcp_hc_expire(SYSCTL_HANDLER_ARGS);
+static int sysctl_tcp_hc_prune(SYSCTL_HANDLER_ARGS);
 static int sysctl_tcp_hc_list(SYSCTL_HANDLER_ARGS);
 static int sysctl_tcp_hc_histo(SYSCTL_HANDLER_ARGS);
 static int sysctl_tcp_hc_purgenow(SYSCTL_HANDLER_ARGS);
@@ -178,15 +180,17 @@ SYSCTL_UINT(_net_inet_tcp_hostcache, OID_AUTO, count, 
CTLFLAG_VNET | CTLFLAG_RD,
     &VNET_NAME(tcp_hostcache.cache_count), 0,
     "Current number of entries in hostcache");
 
-SYSCTL_INT(_net_inet_tcp_hostcache, OID_AUTO, expire, CTLFLAG_VNET | 
CTLFLAG_RW,
-    &VNET_NAME(tcp_hostcache.expire), 0,
+SYSCTL_PROC(_net_inet_tcp_hostcache, OID_AUTO, expire,
+    CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_MPSAFE,
+    &VNET_NAME(tcp_hostcache.expire), 0, sysctl_tcp_hc_expire, "IU",
     "Expire time of TCP hostcache entries");
 
-SYSCTL_INT(_net_inet_tcp_hostcache, OID_AUTO, prune, CTLFLAG_VNET | CTLFLAG_RW,
-    &VNET_NAME(tcp_hostcache.prune), 0,
+SYSCTL_PROC(_net_inet_tcp_hostcache, OID_AUTO, prune,
+    CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_MPSAFE,
+    &VNET_NAME(tcp_hostcache.prune), 0, sysctl_tcp_hc_prune, "IU",
     "Time between purge runs");
 
-SYSCTL_INT(_net_inet_tcp_hostcache, OID_AUTO, purge, CTLFLAG_VNET | CTLFLAG_RW,
+SYSCTL_UINT(_net_inet_tcp_hostcache, OID_AUTO, purge, CTLFLAG_VNET | 
CTLFLAG_RW,
     &VNET_NAME(tcp_hostcache.purgeall), 0,
     "Expire all entries on next purge run");
 
@@ -201,8 +205,8 @@ SYSCTL_PROC(_net_inet_tcp_hostcache, OID_AUTO, histo,
     "Print a histogram of hostcache hashbucket utilization");
 
 SYSCTL_PROC(_net_inet_tcp_hostcache, OID_AUTO, purgenow,
-    CTLFLAG_VNET | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
-    NULL, 0, sysctl_tcp_hc_purgenow, "I",
+    CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_MPSAFE,
+    NULL, 0, sysctl_tcp_hc_purgenow, "IU",
     "Immediately purge all entries");
 
 static MALLOC_DEFINE(M_HOSTCACHE, "hostcache", "TCP hostcache");
@@ -620,6 +624,44 @@ tcp_hc_update(const struct in_conninfo *inc, struct 
tcp_hc_metrics *hcm)
        THC_UNLOCK(hc_head);
 }
 
+/*
+ * Sysctl function: adjusts the expire timeout and adjusts the prune value 
accordingly.
+ */
+static int
+sysctl_tcp_hc_expire(SYSCTL_HANDLER_ARGS)
+{
+       int error, expire;
+
+       expire = V_tcp_hostcache.expire;
+       error = sysctl_handle_int(oidp, &expire, 0, req);
+       if (error != 0 || !req->newptr)
+               return (error);
+       if (expire < V_tcp_hostcache.prune)
+               V_tcp_hostcache.prune = expire;
+       V_tcp_hostcache.expire = expire;
+       return (0);
+}
+
+/*
+ * Sysctl function: adjusts the prune time and adjusts the expire timeout 
accordingly.
+ */
+static int
+sysctl_tcp_hc_prune(SYSCTL_HANDLER_ARGS)
+{
+       int error, prune;
+
+       prune = V_tcp_hostcache.prune;
+       error = sysctl_handle_int(oidp, &prune, 0, req);
+       if (error != 0 || !req->newptr)
+               return (error);
+       if (prune > V_tcp_hostcache.expire)
+               V_tcp_hostcache.expire = prune;
+       V_tcp_hostcache.prune = prune;
+       callout_reset(&V_tcp_hc_callout, V_tcp_hostcache.prune * hz,
+           tcp_hc_purge, curvnet);
+       return (0);
+}
+
 /*
  * Sysctl function: prints the list and values of all hostcache entries in
  * unsorted order.
@@ -831,7 +873,7 @@ sysctl_tcp_hc_purgenow(SYSCTL_HANDLER_ARGS)
 
        val = 0;
        error = sysctl_handle_int(oidp, &val, 0, req);
-       if (error || !req->newptr)
+       if (error != 0 || !req->newptr)
                return (error);
 
        if (val == 2)

Reply via email to