git: f8f05fe48d0f - main - tcp: collect and report more statistics on the TCP host cache
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 18 Sep 2026 22:02:20 UTC
The branch main has been updated by glebius:
URL: https://cgit.FreeBSD.org/src/commit/?id=f8f05fe48d0fe2538dad4c2d0f8e26ea3407b1f7
commit f8f05fe48d0fe2538dad4c2d0f8e26ea3407b1f7
Author: Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2026-09-18 21:56:54 +0000
Commit: Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2026-09-18 21:56:54 +0000
tcp: collect and report more statistics on the TCP host cache
Reviewed by: tuexen
Differential Revision: https://reviews.freebsd.org/D59451
---
sys/netinet/in_kdtrace.c | 12 ++++++++---
sys/netinet/in_kdtrace.h | 12 ++++++++---
sys/netinet/tcp_hostcache.c | 12 +++++++----
sys/netinet/tcp_var.h | 13 +++++++++---
usr.bin/netstat/inet.c | 49 ++++++++++++++++++++++++++++++---------------
5 files changed, 69 insertions(+), 29 deletions(-)
diff --git a/sys/netinet/in_kdtrace.c b/sys/netinet/in_kdtrace.c
index de2a98ce541c..917e6b8be137 100644
--- a/sys/netinet/in_kdtrace.c
+++ b/sys/netinet/in_kdtrace.c
@@ -259,9 +259,6 @@ MIB_PROBE_TCP(tcps_pawsdrop);
MIB_PROBE_TCP(tcps_predack);
MIB_PROBE_TCP(tcps_preddat);
MIB_PROBE_TCP(tcps_pcbackemiss);
-MIB_PROBE_TCP(tcps_cachedrtt);
-MIB_PROBE_TCP(tcps_cachedrttvar);
-MIB_PROBE_TCP(tcps_cachedssthresh);
MIB_PROBE_TCP(tcps_usedrtt);
MIB_PROBE_TCP(tcps_usedrttvar);
MIB_PROBE_TCP(tcps_usedssthresh);
@@ -289,8 +286,17 @@ MIB_PROBE_TCP(tcps_sc_recvcookie);
MIB_PROBE_TCP(tcps_sc_spurcookie);
MIB_PROBE_TCP(tcps_sc_failcookie);
+MIB_PROBE_TCP(tcps_hc_hits);
+MIB_PROBE_TCP(tcps_hc_misses);
MIB_PROBE_TCP(tcps_hc_added);
MIB_PROBE_TCP(tcps_hc_bucketoverflow);
+MIB_PROBE_TCP(tcps_hc_allocfail);
+MIB_PROBE_TCP(tcps_cachedrtt);
+MIB_PROBE_TCP(tcps_cachedrttvar);
+MIB_PROBE_TCP(tcps_cachedssthresh);
+MIB_PROBE_TCP(tcps_cachedcwnd);
+MIB_PROBE_TCP(tcps_cachedsendpipe);
+MIB_PROBE_TCP(tcps_cachedrecvpipe);
MIB_PROBE_TCP(tcps_finwait2_drops);
diff --git a/sys/netinet/in_kdtrace.h b/sys/netinet/in_kdtrace.h
index a203b660d777..08fab3949b5c 100644
--- a/sys/netinet/in_kdtrace.h
+++ b/sys/netinet/in_kdtrace.h
@@ -251,9 +251,6 @@ SDT_PROBE_DECLARE(mib, tcp, count, tcps_pawsdrop);
SDT_PROBE_DECLARE(mib, tcp, count, tcps_predack);
SDT_PROBE_DECLARE(mib, tcp, count, tcps_preddat);
SDT_PROBE_DECLARE(mib, tcp, count, tcps_pcbcachemiss);
-SDT_PROBE_DECLARE(mib, tcp, count, tcps_cachedrtt);
-SDT_PROBE_DECLARE(mib, tcp, count, tcps_cachedrttvar);
-SDT_PROBE_DECLARE(mib, tcp, count, tcps_cachedssthresh);
SDT_PROBE_DECLARE(mib, tcp, count, tcps_usedrtt);
SDT_PROBE_DECLARE(mib, tcp, count, tcps_usedrttvar);
SDT_PROBE_DECLARE(mib, tcp, count, tcps_usedssthresh);
@@ -281,8 +278,17 @@ SDT_PROBE_DECLARE(mib, tcp, count, tcps_sc_recvcookie);
SDT_PROBE_DECLARE(mib, tcp, count, tcps_sc_spurcookie);
SDT_PROBE_DECLARE(mib, tcp, count, tcps_sc_failcookie);
+SDT_PROBE_DECLARE(mib, tcp, count, tcps_hc_hits);
+SDT_PROBE_DECLARE(mib, tcp, count, tcps_hc_misses);
SDT_PROBE_DECLARE(mib, tcp, count, tcps_hc_added);
SDT_PROBE_DECLARE(mib, tcp, count, tcps_hc_bucketoverflow);
+SDT_PROBE_DECLARE(mib, tcp, count, tcps_hc_allocfail);
+SDT_PROBE_DECLARE(mib, tcp, count, tcps_cachedrtt);
+SDT_PROBE_DECLARE(mib, tcp, count, tcps_cachedrttvar);
+SDT_PROBE_DECLARE(mib, tcp, count, tcps_cachedssthresh);
+SDT_PROBE_DECLARE(mib, tcp, count, tcps_cachedcwnd);
+SDT_PROBE_DECLARE(mib, tcp, count, tcps_cachedsendpipe);
+SDT_PROBE_DECLARE(mib, tcp, count, tcps_cachedrecvpipe);
SDT_PROBE_DECLARE(mib, tcp, count, tcps_finwait2_drops);
diff --git a/sys/netinet/tcp_hostcache.c b/sys/netinet/tcp_hostcache.c
index 7a5e2ef095ec..d3bac8f7f11d 100644
--- a/sys/netinet/tcp_hostcache.c
+++ b/sys/netinet/tcp_hostcache.c
@@ -362,8 +362,11 @@ tcp_hc_lookup(const struct in_conninfo *inc)
#ifdef TCP_HC_COUNTERS
hc_entry->hc_hits++;
#endif
- } else
+ TCPSTAT_INC(tcps_hc_hits);
+ } else {
smr_exit(V_tcp_hostcache.smr);
+ TCPSTAT_INC(tcps_hc_misses);
+ }
return (hc_entry);
}
@@ -527,6 +530,7 @@ tcp_hc_update(const struct in_conninfo *inc, struct tcp_hc_metrics *hcm)
hc_entry = uma_zalloc_smr(V_tcp_hostcache.zone, M_NOWAIT);
if (hc_entry == NULL) {
THC_UNLOCK(hc_head);
+ TCPSTAT_INC(tcps_hc_allocfail);
return;
}
@@ -584,7 +588,7 @@ tcp_hc_update(const struct in_conninfo *inc, struct tcp_hc_metrics *hcm)
v = ((uint64_t)hc_entry->hc_cwnd +
(uint64_t)hcm->hc_cwnd) / 2;
atomic_store_32(&hc_entry->hc_cwnd, v);
- /* TCPSTAT_INC(tcps_cachedcwnd); */
+ TCPSTAT_INC(tcps_cachedcwnd);
}
if (hcm->hc_sendpipe != 0) {
if (hc_entry->hc_sendpipe == 0)
@@ -593,7 +597,7 @@ tcp_hc_update(const struct in_conninfo *inc, struct tcp_hc_metrics *hcm)
v = ((uint64_t)hc_entry->hc_sendpipe +
(uint64_t)hcm->hc_sendpipe) / 2;
atomic_store_32(&hc_entry->hc_sendpipe, v);
- /* TCPSTAT_INC(tcps_cachedsendpipe); */
+ TCPSTAT_INC(tcps_cachedsendpipe);
}
if (hcm->hc_recvpipe != 0) {
if (hc_entry->hc_recvpipe == 0)
@@ -602,7 +606,7 @@ tcp_hc_update(const struct in_conninfo *inc, struct tcp_hc_metrics *hcm)
v = ((uint64_t)hc_entry->hc_recvpipe +
(uint64_t)hcm->hc_recvpipe) / 2;
atomic_store_32(&hc_entry->hc_recvpipe, v);
- /* TCPSTAT_INC(tcps_cachedrecvpipe); */
+ TCPSTAT_INC(tcps_cachedrecvpipe);
}
/*
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 39a5cca1d635..8400824761ed 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -1022,9 +1022,6 @@ struct tcpstat {
uint64_t tcps_predack; /* times hdr predict ok for acks */
uint64_t tcps_preddat; /* times hdr predict ok for data pkts */
uint64_t tcps_pcbcachemiss;
- uint64_t tcps_cachedrtt; /* times cached RTT in route updated */
- uint64_t tcps_cachedrttvar; /* times cached rttvar updated */
- uint64_t tcps_cachedssthresh; /* times cached ssthresh updated */
uint64_t tcps_usedrtt; /* times RTT initialized from route */
uint64_t tcps_usedrttvar; /* times RTTVAR initialized from rt */
uint64_t tcps_usedssthresh; /* times ssthresh initialized from rt*/
@@ -1052,8 +1049,18 @@ struct tcpstat {
uint64_t tcps_sc_spurcookie; /* SYN cookie spurious, rejected */
uint64_t tcps_sc_failcookie; /* SYN cookie failed, rejected */
+ /* TCP host cache */
+ uint64_t tcps_hc_hits;
+ uint64_t tcps_hc_misses;
uint64_t tcps_hc_added; /* entry added to hostcache */
uint64_t tcps_hc_bucketoverflow;/* hostcache per bucket limit hit */
+ uint64_t tcps_hc_allocfail; /* hostcache zone full */
+ uint64_t tcps_cachedrtt; /* times cached RTT in route updated */
+ uint64_t tcps_cachedrttvar; /* times cached rttvar updated */
+ uint64_t tcps_cachedssthresh; /* times cached ssthresh updated */
+ uint64_t tcps_cachedcwnd; /* times cached congestion window */
+ uint64_t tcps_cachedsendpipe; /* times cached send buffer size */
+ uint64_t tcps_cachedrecvpipe; /* times cached recv buffer size */
uint64_t tcps_finwait2_drops; /* Drop FIN_WAIT_2 connection after time limit */
diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c
index ddc9a2fdd2f4..07e3e952a289 100644
--- a/usr.bin/netstat/inet.c
+++ b/usr.bin/netstat/inet.c
@@ -612,6 +612,8 @@ tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
xo_emit(m, (uintmax_t )tcpstat.f, plural(tcpstat.f))
#define p1a(f, m) if (tcpstat.f || sflag <= 1) \
xo_emit(m, (uintmax_t )tcpstat.f)
+#define p1b(f, m) if (tcpstat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t )tcpstat.f, plurales(tcpstat.f))
#define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
xo_emit(m, (uintmax_t )tcpstat.f1, plural(tcpstat.f1), \
(uintmax_t )tcpstat.f2, plural(tcpstat.f2))
@@ -714,23 +716,9 @@ tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
"{N:/ignored RSTs in the window%s}\n");
p(tcps_connects, "\t{:connections-established/%ju} "
"{N:/connection%s established (including accepts)}\n");
- p(tcps_usedrtt, "\t\t{:connections-hostcache-rtt/%ju} "
- "{N:/time%s used RTT from hostcache}\n");
- p(tcps_usedrttvar, "\t\t{:connections-hostcache-rttvar/%ju} "
- "{N:/time%s used RTT variance from hostcache}\n");
- p(tcps_usedssthresh, "\t\t{:connections-hostcache-ssthresh/%ju} "
- "{N:/time%s used slow-start threshold from hostcache}\n");
p2(tcps_closed, tcps_drops, "\t{:connections-closed/%ju} "
"{N:/connection%s closed (including} "
"{:connection-drops/%ju} {N:/drop%s})\n");
- p(tcps_cachedrtt, "\t\t{:connections-updated-rtt-on-close/%ju} "
- "{N:/connection%s updated cached RTT on close}\n");
- p(tcps_cachedrttvar, "\t\t"
- "{:connections-updated-variance-on-close/%ju} "
- "{N:/connection%s updated cached RTT variance on close}\n");
- p(tcps_cachedssthresh, "\t\t"
- "{:connections-updated-ssthresh-on-close/%ju} "
- "{N:/connection%s updated cached ssthresh on close}\n");
p(tcps_conndrops, "\t{:embryonic-connections-dropped/%ju} "
"{N:/embryonic connection%s dropped}\n");
p2(tcps_rttupdated, tcps_segstimed, "\t{:segments-updated-rtt/%ju} "
@@ -800,8 +788,37 @@ tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
p3(tcps_hc_added, "\t{:entries-added/%ju} "
"{N:/hostcache entr%s added}\n");
- p1a(tcps_hc_bucketoverflow, "\t\t{:buffer-overflows/%ju} "
- "{N:/bucket overflow}\n");
+ p(tcps_hc_hits, "\t\t{:cache-hits/%ju} "
+ "{N:/cache lookup hit%s}\n");
+ p1b(tcps_hc_misses, "\t\t{:cache-misses/%ju} "
+ "{N:/cache lookup miss%s}\n");
+ p(tcps_hc_bucketoverflow, "\t\t{:bucket-overflows/%ju} "
+ "{N:/bucket overflow%s}\n");
+ p(tcps_hc_allocfail, "\t\t{:allocation-failures/%ju} "
+ "{N:/allocation failure%s}\n");
+ p(tcps_cachedrtt, "\t\t{:connections-updated-rtt-on-close/%ju} "
+ "{N:/connection%s updated cached RTT on close}\n");
+ p(tcps_usedrtt, "\t\t{:connections-hostcache-rtt/%ju} "
+ "{N:/time%s used RTT from hostcache}\n");
+ p(tcps_cachedrttvar, "\t\t"
+ "{:connections-updated-variance-on-close/%ju} "
+ "{N:/connection%s updated cached RTT variance on close}\n");
+ p(tcps_usedrttvar, "\t\t{:connections-hostcache-rttvar/%ju} "
+ "{N:/time%s used RTT variance from hostcache}\n");
+ p(tcps_cachedssthresh, "\t\t"
+ "{:connections-updated-ssthresh-on-close/%ju} "
+ "{N:/connection%s updated cached ssthresh on close}\n");
+ p(tcps_usedssthresh, "\t\t{:connections-hostcache-ssthresh/%ju} "
+ "{N:/time%s used slow-start threshold from hostcache}\n");
+ p(tcps_cachedcwnd, "\t\t"
+ "{:connections-updated-cwnd-on-close/%ju} "
+ "{N:/connection%s updated cached congestion windows on close}\n");
+ p(tcps_cachedsendpipe, "\t\t"
+ "{:connections-updated-send-space-on-close/%ju} "
+ "{N:/connection%s updated cached send buffer space on close}\n");
+ p(tcps_cachedrecvpipe, "\t\t"
+ "{:connections-updated-recv-space-on-close/%ju} "
+ "{N:/connection%s updated cached recv buffer space on close}\n");
xo_close_container("hostcache");