Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 16 Apr 2021 20:45:35 GMT
From:      Richard Scheffenegger <rscheff@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 38088b12fe64 - stable/13 - tcp: Add hash histogram output and validate bucket length accounting
Message-ID:  <202104162045.13GKjZMs066034@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by rscheff:

URL: https://cgit.FreeBSD.org/src/commit/?id=38088b12fe64f35d4f80b5a8f257b1edcdd6ffae

commit 38088b12fe64f35d4f80b5a8f257b1edcdd6ffae
Author:     Richard Scheffenegger <rscheff@FreeBSD.org>
AuthorDate: 2021-04-01 12:44:05 +0000
Commit:     Richard Scheffenegger <rscheff@FreeBSD.org>
CommitDate: 2021-04-16 19:53:15 +0000

    tcp: Add hash histogram output and validate bucket length accounting
    
    Provide a histogram output to check, if the hashsize or
    bucketlimit could be optimized. Also add some basic sanity
    checks around the accounting of the hash utilization.
    
    MFC after: 2 weeks
    Reviewed By: tuexen, #transport
    Sponsored by: NetApp, Inc.
    Differential Revision: https://reviews.freebsd.org/D29506
    
    (cherry picked from commit 02f26e98c7f4d43d6bd077421286da455e069146)
---
 sys/netinet/tcp_hostcache.c | 62 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/sys/netinet/tcp_hostcache.c b/sys/netinet/tcp_hostcache.c
index 87023cc1a760..36439e90a611 100644
--- a/sys/netinet/tcp_hostcache.c
+++ b/sys/netinet/tcp_hostcache.c
@@ -121,6 +121,7 @@ VNET_DEFINE_STATIC(struct callout, tcp_hc_callout);
 static struct hc_metrics *tcp_hc_lookup(struct in_conninfo *);
 static struct hc_metrics *tcp_hc_insert(struct in_conninfo *);
 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);
 static void tcp_hc_purge_internal(int);
 static void tcp_hc_purge(void *);
@@ -168,6 +169,11 @@ SYSCTL_PROC(_net_inet_tcp_hostcache, OID_AUTO, list,
     0, 0, sysctl_tcp_hc_list, "A",
     "List of all hostcache entries");
 
+SYSCTL_PROC(_net_inet_tcp_hostcache, OID_AUTO, histo,
+    CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_SKIP | CTLFLAG_MPSAFE,
+    0, 0, sysctl_tcp_hc_histo, "A",
+    "Print a histogram of hostcache hashbucket utilization");
+
 SYSCTL_PROC(_net_inet_tcp_hostcache, OID_AUTO, purgenow,
     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
     NULL, 0, sysctl_tcp_hc_purgenow, "I",
@@ -390,6 +396,11 @@ tcp_hc_insert(struct in_conninfo *inc)
 			return NULL;
 		}
 		TAILQ_REMOVE(&hc_head->hch_bucket, hc_entry, rmx_q);
+		KASSERT(V_tcp_hostcache.hashbase[hash].hch_length > 0 &&
+			V_tcp_hostcache.hashbase[hash].hch_length <=
+			V_tcp_hostcache.bucket_limit,
+			("tcp_hostcache: bucket length range violated at %u: %u",
+			hash, V_tcp_hostcache.hashbase[hash].hch_length));
 		V_tcp_hostcache.hashbase[hash].hch_length--;
 		atomic_subtract_int(&V_tcp_hostcache.cache_count, 1);
 		TCPSTAT_INC(tcps_hc_bucketoverflow);
@@ -424,6 +435,10 @@ tcp_hc_insert(struct in_conninfo *inc)
 	 */
 	TAILQ_INSERT_HEAD(&hc_head->hch_bucket, hc_entry, rmx_q);
 	V_tcp_hostcache.hashbase[hash].hch_length++;
+	KASSERT(V_tcp_hostcache.hashbase[hash].hch_length <
+		V_tcp_hostcache.bucket_limit,
+		("tcp_hostcache: bucket length too high at %u: %u",
+		hash, V_tcp_hostcache.hashbase[hash].hch_length));
 	atomic_add_int(&V_tcp_hostcache.cache_count, 1);
 	TCPSTAT_INC(tcps_hc_added);
 
@@ -696,6 +711,48 @@ sysctl_tcp_hc_list(SYSCTL_HANDLER_ARGS)
 	return(error);
 }
 
+/*
+ * Sysctl function: prints a histogram of the hostcache hashbucket
+ * utilization.
+ */
+static int
+sysctl_tcp_hc_histo(SYSCTL_HANDLER_ARGS)
+{
+	const int linesize = 50;
+	struct sbuf sb;
+	int i, error;
+	int *histo;
+	u_int hch_length;
+
+	if (jailed_without_vnet(curthread->td_ucred) != 0)
+		return (EPERM);
+
+	histo = (int *)malloc(sizeof(int) * (V_tcp_hostcache.bucket_limit + 1),
+			M_TEMP, M_NOWAIT|M_ZERO);
+	if (histo == NULL)
+		return(ENOMEM);
+
+	for (i = 0; i < V_tcp_hostcache.hashsize; i++) {
+		hch_length = V_tcp_hostcache.hashbase[i].hch_length;
+		KASSERT(hch_length <= V_tcp_hostcache.bucket_limit,
+			("tcp_hostcache: bucket limit exceeded at %u: %u",
+			i, hch_length));
+		histo[hch_length]++;
+	}
+
+	/* Use a buffer for 16 lines */
+	sbuf_new_for_sysctl(&sb, NULL, 16 * linesize, req);
+
+	sbuf_printf(&sb, "\nLength\tCount\n");
+	for (i = 0; i <= V_tcp_hostcache.bucket_limit; i++) {
+		sbuf_printf(&sb, "%u\t%u\n", i, histo[i]);
+	}
+	error = sbuf_finish(&sb);
+	sbuf_delete(&sb);
+	free(histo, M_TEMP);
+	return(error);
+}
+
 /*
  * Caller has to make sure the curvnet is set properly.
  */
@@ -709,6 +766,11 @@ tcp_hc_purge_internal(int all)
 		THC_LOCK(&V_tcp_hostcache.hashbase[i].hch_mtx);
 		TAILQ_FOREACH_SAFE(hc_entry,
 		    &V_tcp_hostcache.hashbase[i].hch_bucket, rmx_q, hc_next) {
+			KASSERT(V_tcp_hostcache.hashbase[i].hch_length > 0 &&
+				V_tcp_hostcache.hashbase[i].hch_length <=
+				V_tcp_hostcache.bucket_limit,
+				("tcp_hostcache: bucket langth out of range at %u: %u",
+				i, V_tcp_hostcache.hashbase[i].hch_length));
 			if (all || hc_entry->rmx_expire <= 0) {
 				TAILQ_REMOVE(&V_tcp_hostcache.hashbase[i].hch_bucket,
 					      hc_entry, rmx_q);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202104162045.13GKjZMs066034>