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)
