git: e28330832be4 - main - tcp: socket option to get stack alias name

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Wed, 27 Oct 2021 15:22:56 UTC
The branch main has been updated by glebius:

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

commit e28330832be41d2ef012dda1dafef25895ab2c6b
Author:     Peter Lei <peterlei@netflix.com>
AuthorDate: 2021-10-26 03:08:54 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2021-10-27 15:21:59 +0000

    tcp: socket option to get stack alias name
    
    TCP stack sysctl nodes are currently inserted using the stack
    name alias. Allow the user to get the current stack's alias to
    allow for programatic sysctl access.
    
    Obtained from:  Netflix
---
 sys/netinet/tcp.h        |  1 +
 sys/netinet/tcp_subr.c   | 31 +++++++++++++++++++++++++++++++
 sys/netinet/tcp_usrreq.c | 15 +++++++++++----
 sys/netinet/tcp_var.h    |  1 +
 4 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/sys/netinet/tcp.h b/sys/netinet/tcp.h
index e7c47e85bb7b..6dc7403aae28 100644
--- a/sys/netinet/tcp.h
+++ b/sys/netinet/tcp.h
@@ -210,6 +210,7 @@ struct tcphdr {
 #define	TCP_PCAP_OUT	2048	/* number of output packets to keep */
 #define	TCP_PCAP_IN	4096	/* number of input packets to keep */
 #define TCP_FUNCTION_BLK 8192	/* Set the tcp function pointers to the specified stack */
+#define TCP_FUNCTION_ALIAS 8193	/* Get the current tcp function pointer name alias */
 /* Options for Rack and BBR */
 #define	TCP_REUSPORT_LB_NUMA   1026	/* set listen socket numa domain */
 #define TCP_RACK_MBUF_QUEUE   1050 /* Do we allow mbuf queuing if supported */
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 9d66086a383b..2752773a95fc 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -473,6 +473,37 @@ find_and_ref_tcp_fb(struct tcp_function_block *blk)
 	return(rblk);
 }
 
+/* Find a matching alias for the given tcp_function_block. */
+int
+find_tcp_function_alias(struct tcp_function_block *blk,
+    struct tcp_function_set *fs)
+{
+	struct tcp_function *f;
+	int found;
+
+	found = 0;
+	rw_rlock(&tcp_function_lock);
+	TAILQ_FOREACH(f, &t_functions, tf_next) {
+		if ((f->tf_fb == blk) &&
+		    (strncmp(f->tf_name, blk->tfb_tcp_block_name,
+		        TCP_FUNCTION_NAME_LEN_MAX) != 0)) {
+			/* Matching function block with different name. */
+			strncpy(fs->function_set_name, f->tf_name,
+			    TCP_FUNCTION_NAME_LEN_MAX);
+			found = 1;
+			break;
+		}
+	}
+	/* Null terminate the string appropriately. */
+	if (found) {
+		fs->function_set_name[TCP_FUNCTION_NAME_LEN_MAX - 1] = '\0';
+	} else {
+		fs->function_set_name[0] = '\0';
+	}
+	rw_runlock(&tcp_function_lock);
+	return (found);
+}
+
 static struct tcp_function_block *
 find_and_ref_tcp_default_fb(void)
 {
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index e9f7fa541461..f004d54b4657 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -1894,10 +1894,17 @@ err_out:
 		INP_WUNLOCK(inp);
 		return (error);
 	} else if ((sopt->sopt_dir == SOPT_GET) &&
-	    (sopt->sopt_name == TCP_FUNCTION_BLK)) {
-		strncpy(fsn.function_set_name, tp->t_fb->tfb_tcp_block_name,
-		    TCP_FUNCTION_NAME_LEN_MAX);
-		fsn.function_set_name[TCP_FUNCTION_NAME_LEN_MAX - 1] = '\0';
+	    ((sopt->sopt_name == TCP_FUNCTION_BLK) ||
+	     (sopt->sopt_name == TCP_FUNCTION_ALIAS))) {
+		if (sopt->sopt_name == TCP_FUNCTION_ALIAS) {
+			memset(&fsn, 0, sizeof(fsn));
+			find_tcp_function_alias(tp->t_fb, &fsn);
+		} else {
+			strncpy(fsn.function_set_name,
+			    tp->t_fb->tfb_tcp_block_name,
+			    TCP_FUNCTION_NAME_LEN_MAX);
+			fsn.function_set_name[TCP_FUNCTION_NAME_LEN_MAX - 1] = '\0';
+		}
 		fsn.pcbcnt = tp->t_fb->tfb_refcnt;
 		INP_WUNLOCK(inp);
 		error = sooptcopyout(sopt, &fsn, sizeof fsn);
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index d5b2963ef4dc..2775fb392a1a 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -1020,6 +1020,7 @@ int register_tcp_functions_as_name(struct tcp_function_block *blk,
 int deregister_tcp_functions(struct tcp_function_block *blk, bool quiesce,
     bool force);
 struct tcp_function_block *find_and_ref_tcp_functions(struct tcp_function_set *fs);
+int find_tcp_function_alias(struct tcp_function_block *blk, struct tcp_function_set *fs);
 void tcp_switch_back_to_default(struct tcpcb *tp);
 struct tcp_function_block *
 find_and_ref_tcp_fb(struct tcp_function_block *fs);