MPTCP Linux Development
 help / color / mirror / Atom feed
* [PATCH mptcp-next v6 00/10] selftests: consolidate TCP_INQ testing into sockopt
@ 2026-07-10  8:59 Geliang Tang
  2026-07-10  8:59 ` [PATCH mptcp-next v6 01/10] selftests: mptcp: sockopt: add tx/rx protocol options Geliang Tang
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: Geliang Tang @ 2026-07-10  8:59 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

v6:
 - A new patch to use recvmsg instead of read.
 - Squash the four original patches into two.
 - Reset msg.msg_controllen.
 - Check cmsg_len in get_tcp_inq.
 - Check return value of client_huge_transfer.
 - Address other comments from Sashiko.

v5:
 - Continue using the approach from v3 and fix the instability issues.
   This version has undergone extensive loop testing.
 - The new two separate functions, server_huge_transfer() and
   client_huge_transfer(), improve code structure.
 - https://patchwork.kernel.org/project/mptcp/cover/cover.1783579976.git.tanggeliang@kylinos.cn/

v4:
 - v3 changed the behavior of process_one_client and connect_one_server,
   causing intermittent failures during loop testing. Revert to using the
   v2 approach, along with some cleanups.
 - https://patchwork.kernel.org/project/mptcp/cover/cover.1757686538.git.tanggeliang@kylinos.cn/

v3:
 - No longer using process_one_client_inq() and connect_one_server_inq()
   for switching; instead, the inq-related code has been merged into
   process_one_client() and connect_one_server().
 - https://patchwork.kernel.org/project/mptcp/cover/cover.1756200029.git.tanggeliang@kylinos.cn/

v2:
 - patch 4, a new patch, add do_setsockopt_inq helper.
 - cleanups.
 - https://patchwork.kernel.org/project/mptcp/cover/cover.1754664106.git.tanggeliang@kylinos.cn/

v1:
 - https://patchwork.kernel.org/project/mptcp/cover/cover.1754620968.git.tanggeliang@kylinos.cn/

This series consolidates the TCP_INQ test functionality from mptcp_inq
into mptcp_sockopt, simplifying the test suite while maintaining full
test coverage.

Geliang Tang (10):
  selftests: mptcp: sockopt: add tx/rx protocol options
  selftests: mptcp: sockopt: add TCP_INQ test option
  selftests: mptcp: sockopt: use unix socket instead of pipe
  selftests: mptcp: sockopt: pass echo length over unixfd
  selftests: mptcp: sockopt: set FIONREAD ioctl
  selftests: mptcp: sockopt: add huge data transfer tests
  selftests: mptcp: sockopt: add wait_for_ack helper
  selftests: mptcp: sockopt: use recvmsg instead of read
  selftests: mptcp: sockopt: add get_tcp_inq helper
  selftests: mptcp: sockopt: replace mptcp_inq with sockopt

 tools/testing/selftests/net/mptcp/.gitignore  |   1 -
 tools/testing/selftests/net/mptcp/Makefile    |   1 -
 tools/testing/selftests/net/mptcp/mptcp_inq.c | 614 ------------------
 .../selftests/net/mptcp/mptcp_sockopt.c       | 382 ++++++++++-
 .../selftests/net/mptcp/mptcp_sockopt.sh      |   8 +-
 5 files changed, 351 insertions(+), 655 deletions(-)
 delete mode 100644 tools/testing/selftests/net/mptcp/mptcp_inq.c

-- 
2.53.0


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH mptcp-next v6 01/10] selftests: mptcp: sockopt: add tx/rx protocol options
  2026-07-10  8:59 [PATCH mptcp-next v6 00/10] selftests: consolidate TCP_INQ testing into sockopt Geliang Tang
@ 2026-07-10  8:59 ` Geliang Tang
  2026-07-10  8:59 ` [PATCH mptcp-next v6 02/10] selftests: mptcp: sockopt: add TCP_INQ test option Geliang Tang
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Geliang Tang @ 2026-07-10  8:59 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

Add -t and -r options to specify tx/rx protocols (TCP/MPTCP). This
increases testing flexibility by allowing explicit protocol selection
for both transmission and reception paths.

These codes are from mptcp_inq.c.

Enhance compatibility with TCP tests by skipping MPTCP getsockopt checks
during TCP tests since MPTCP socket options are not available.

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 .../selftests/net/mptcp/mptcp_sockopt.c       | 37 ++++++++++++++++---
 1 file changed, 31 insertions(+), 6 deletions(-)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index b6e58d936ebe..70e8d6c5094c 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -28,6 +28,8 @@
 #include <linux/compiler.h>
 
 static int pf = AF_INET;
+static int proto_tx = IPPROTO_MPTCP;
+static int proto_rx = IPPROTO_MPTCP;
 
 #ifndef IPPROTO_MPTCP
 #define IPPROTO_MPTCP 262
@@ -137,6 +139,7 @@ static void __noreturn die_perror(const char *msg)
 static void die_usage(int r)
 {
 	fprintf(stderr, "Usage: mptcp_sockopt [-6]\n");
+	fprintf(stderr, "                     [-t tcp|mptcp] [-r tcp|mptcp]\n");
 	exit(r);
 }
 
@@ -202,7 +205,7 @@ static int sock_listen_mptcp(const char * const listenaddr,
 	hints.ai_family = pf;
 
 	for (a = addr; a; a = a->ai_next) {
-		sock = socket(a->ai_family, a->ai_socktype, IPPROTO_MPTCP);
+		sock = socket(a->ai_family, a->ai_socktype, proto_rx);
 		if (sock < 0)
 			continue;
 
@@ -260,11 +263,22 @@ static int sock_connect_mptcp(const char * const remoteaddr,
 	return sock;
 }
 
+static int protostr_to_num(const char *s)
+{
+	if (strcasecmp(s, "tcp") == 0)
+		return IPPROTO_TCP;
+	if (strcasecmp(s, "mptcp") == 0)
+		return IPPROTO_MPTCP;
+
+	die_usage(1);
+	return 0;
+}
+
 static void parse_opts(int argc, char **argv)
 {
 	int c;
 
-	while ((c = getopt(argc, argv, "h6")) != -1) {
+	while ((c = getopt(argc, argv, "h6t:r:")) != -1) {
 		switch (c) {
 		case 'h':
 			die_usage(0);
@@ -272,6 +286,12 @@ static void parse_opts(int argc, char **argv)
 		case '6':
 			pf = AF_INET6;
 			break;
+		case 't':
+			proto_tx = protostr_to_num(optarg);
+			break;
+		case 'r':
+			proto_rx = protostr_to_num(optarg);
+			break;
 		default:
 			die_usage(1);
 			break;
@@ -557,6 +577,9 @@ static void do_getsockopt_mptcp_full_info(struct so_state *s, int fd)
 
 static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 {
+	if (proto_tx != IPPROTO_MPTCP || proto_rx != IPPROTO_MPTCP)
+		return;
+
 	do_getsockopt_mptcp_info(s, fd, w);
 
 	do_getsockopt_tcp_info(s, fd, r, w);
@@ -632,7 +655,8 @@ static void connect_one_server(int fd, int pipefd)
 	if (eof)
 		total += 1; /* sequence advances due to FIN */
 
-	assert(s.mptcpi_rcv_delta == (uint64_t)total);
+	if (proto_tx == IPPROTO_MPTCP && proto_rx == IPPROTO_MPTCP)
+		assert(s.mptcpi_rcv_delta == (uint64_t)total);
 	close(fd);
 }
 
@@ -667,7 +691,8 @@ static void process_one_client(int fd, int pipefd)
 		xerror("expected EOF, got %lu", ret3);
 
 	do_getsockopts(&s, fd, ret, ret2);
-	if (s.mptcpi_rcv_delta != (uint64_t)ret + 1)
+	if (proto_tx == IPPROTO_MPTCP && proto_rx == IPPROTO_MPTCP &&
+	    s.mptcpi_rcv_delta != (uint64_t)ret + 1)
 		xerror("mptcpi_rcv_delta %" PRIu64 ", expect %" PRIu64 ", diff %" PRId64,
 		       s.mptcpi_rcv_delta, ret + 1, s.mptcpi_rcv_delta - (ret + 1));
 
@@ -777,10 +802,10 @@ static int client(int pipefd)
 
 	switch (pf) {
 	case AF_INET:
-		fd = sock_connect_mptcp("127.0.0.1", "15432", IPPROTO_MPTCP);
+		fd = sock_connect_mptcp("127.0.0.1", "15432", proto_tx);
 		break;
 	case AF_INET6:
-		fd = sock_connect_mptcp("::1", "15432", IPPROTO_MPTCP);
+		fd = sock_connect_mptcp("::1", "15432", proto_tx);
 		break;
 	default:
 		xerror("Unknown pf %d\n", pf);
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH mptcp-next v6 02/10] selftests: mptcp: sockopt: add TCP_INQ test option
  2026-07-10  8:59 [PATCH mptcp-next v6 00/10] selftests: consolidate TCP_INQ testing into sockopt Geliang Tang
  2026-07-10  8:59 ` [PATCH mptcp-next v6 01/10] selftests: mptcp: sockopt: add tx/rx protocol options Geliang Tang
@ 2026-07-10  8:59 ` Geliang Tang
  2026-07-10  8:59 ` [PATCH mptcp-next v6 03/10] selftests: mptcp: sockopt: use unix socket instead of pipe Geliang Tang
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Geliang Tang @ 2026-07-10  8:59 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

Add -i option to enable TCP_INQ testing. This prepares for consolidating
TCP_INQ tests into a single binary by adding the necessary command-line
interface.

Add helper functions to conditionally set TCP_INQ sockopt on accepted
sockets when running in inq mode. This ensures proper testing of TCP_CM_INQ
functionality by enabling the required socket option on the incoming server
connection.

These codes are from mptcp_inq.c.

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 .../selftests/net/mptcp/mptcp_sockopt.c        | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index 70e8d6c5094c..92661da821fa 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -30,6 +30,7 @@
 static int pf = AF_INET;
 static int proto_tx = IPPROTO_MPTCP;
 static int proto_rx = IPPROTO_MPTCP;
+static bool inq;
 
 #ifndef IPPROTO_MPTCP
 #define IPPROTO_MPTCP 262
@@ -140,6 +141,7 @@ static void die_usage(int r)
 {
 	fprintf(stderr, "Usage: mptcp_sockopt [-6]\n");
 	fprintf(stderr, "                     [-t tcp|mptcp] [-r tcp|mptcp]\n");
+	fprintf(stderr, "                     [-i]\n");
 	exit(r);
 }
 
@@ -278,7 +280,7 @@ static void parse_opts(int argc, char **argv)
 {
 	int c;
 
-	while ((c = getopt(argc, argv, "h6t:r:")) != -1) {
+	while ((c = getopt(argc, argv, "h6t:r:i")) != -1) {
 		switch (c) {
 		case 'h':
 			die_usage(0);
@@ -292,6 +294,9 @@ static void parse_opts(int argc, char **argv)
 		case 'r':
 			proto_rx = protostr_to_num(optarg);
 			break;
+		case 'i':
+			inq = true;
+			break;
 		default:
 			die_usage(1);
 			break;
@@ -718,6 +723,14 @@ static void process_one_client(int fd, int pipefd)
 	close(fd);
 }
 
+static void do_setsockopt_inq(int fd)
+{
+	int on = 1;
+
+	if (setsockopt(fd, IPPROTO_TCP, TCP_INQ, &on, sizeof(on)))
+		die_perror("setsockopt(TCP_INQ)");
+}
+
 static int xaccept(int s)
 {
 	int fd = accept(s, NULL, 0);
@@ -725,6 +738,9 @@ static int xaccept(int s)
 	if (fd < 0)
 		die_perror("accept");
 
+	if (inq)
+		do_setsockopt_inq(fd);
+
 	return fd;
 }
 
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH mptcp-next v6 03/10] selftests: mptcp: sockopt: use unix socket instead of pipe
  2026-07-10  8:59 [PATCH mptcp-next v6 00/10] selftests: consolidate TCP_INQ testing into sockopt Geliang Tang
  2026-07-10  8:59 ` [PATCH mptcp-next v6 01/10] selftests: mptcp: sockopt: add tx/rx protocol options Geliang Tang
  2026-07-10  8:59 ` [PATCH mptcp-next v6 02/10] selftests: mptcp: sockopt: add TCP_INQ test option Geliang Tang
@ 2026-07-10  8:59 ` Geliang Tang
  2026-07-10  8:59 ` [PATCH mptcp-next v6 04/10] selftests: mptcp: sockopt: pass echo length over unixfd Geliang Tang
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Geliang Tang @ 2026-07-10  8:59 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

Replace pipe-based synchronization with Unix domain socket pairs
(SOCK_DGRAM) for better bidirectional communication reliability between
server and client processes.

These codes are from mptcp_inq.c.

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 .../selftests/net/mptcp/mptcp_sockopt.c       | 40 +++++++++----------
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index 92661da821fa..fdc7500b79b3 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -595,7 +595,7 @@ static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 		do_getsockopt_mptcp_full_info(s, fd);
 }
 
-static void connect_one_server(int fd, int pipefd)
+static void connect_one_server(int fd, int unixfd)
 {
 	char buf[4096], buf2[4096];
 	size_t len, i, total;
@@ -620,9 +620,9 @@ static void connect_one_server(int fd, int pipefd)
 	do_getsockopts(&s, fd, 0, 0);
 
 	/* un-block server */
-	ret = read(pipefd, buf2, 4);
+	ret = read(unixfd, buf2, 4);
 	assert(ret == 4);
-	close(pipefd);
+	close(unixfd);
 
 	assert(strncmp(buf2, "xmit", 4) == 0);
 
@@ -665,7 +665,7 @@ static void connect_one_server(int fd, int pipefd)
 	close(fd);
 }
 
-static void process_one_client(int fd, int pipefd)
+static void process_one_client(int fd, int unixfd)
 {
 	ssize_t ret, ret2, ret3;
 	struct so_state s;
@@ -674,7 +674,7 @@ static void process_one_client(int fd, int pipefd)
 	memset(&s, 0, sizeof(s));
 	do_getsockopts(&s, fd, 0, 0);
 
-	ret = write(pipefd, "xmit", 4);
+	ret = write(unixfd, "xmit", 4);
 	assert(ret == 4);
 
 	ret = read(fd, buf, sizeof(buf));
@@ -744,7 +744,7 @@ static int xaccept(int s)
 	return fd;
 }
 
-static int server(int pipefd)
+static int server(int unixfd)
 {
 	int fd = -1, r;
 
@@ -760,13 +760,13 @@ static int server(int pipefd)
 		break;
 	}
 
-	r = write(pipefd, "conn", 4);
+	r = write(unixfd, "conn", 4);
 	assert(r == 4);
 
 	alarm(15);
 	r = xaccept(fd);
 
-	process_one_client(r, pipefd);
+	process_one_client(r, unixfd);
 
 	close(fd);
 	return 0;
@@ -810,7 +810,7 @@ static void test_ip_tos_sockopt(int fd)
 		xerror("expect socklen_t == -1");
 }
 
-static int client(int pipefd)
+static int client(int unixfd)
 {
 	int fd = -1;
 
@@ -829,7 +829,7 @@ static int client(int pipefd)
 
 	test_ip_tos_sockopt(fd);
 
-	connect_one_server(fd, pipefd);
+	connect_one_server(fd, unixfd);
 
 	return 0;
 }
@@ -883,35 +883,35 @@ int main(int argc, char *argv[])
 {
 	int e1, e2, wstatus;
 	pid_t s, c, ret;
-	int pipefds[2];
+	int unixfds[2];
 
 	parse_opts(argc, argv);
 
 	init_rng();
 
-	e1 = pipe(pipefds);
+	e1 = socketpair(AF_UNIX, SOCK_DGRAM, 0, unixfds);
 	if (e1 < 0)
-		die_perror("pipe");
+		die_perror("socketpair");
 
 	s = xfork();
 	if (s == 0) {
-		close(pipefds[0]);
-		ret = server(pipefds[1]);
-		close(pipefds[1]);
+		close(unixfds[0]);
+		ret = server(unixfds[1]);
+		close(unixfds[1]);
 		return ret;
 	}
 
-	close(pipefds[1]);
+	close(unixfds[1]);
 
 	/* wait until server bound a socket */
-	e1 = read(pipefds[0], &e1, 4);
+	e1 = read(unixfds[0], &e1, 4);
 	assert(e1 == 4);
 
 	c = xfork();
 	if (c == 0)
-		return client(pipefds[0]);
+		return client(unixfds[0]);
 
-	close(pipefds[0]);
+	close(unixfds[0]);
 
 	ret = waitpid(s, &wstatus, 0);
 	if (ret == -1)
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH mptcp-next v6 04/10] selftests: mptcp: sockopt: pass echo length over unixfd
  2026-07-10  8:59 [PATCH mptcp-next v6 00/10] selftests: consolidate TCP_INQ testing into sockopt Geliang Tang
                   ` (2 preceding siblings ...)
  2026-07-10  8:59 ` [PATCH mptcp-next v6 03/10] selftests: mptcp: sockopt: use unix socket instead of pipe Geliang Tang
@ 2026-07-10  8:59 ` Geliang Tang
  2026-07-10  8:59 ` [PATCH mptcp-next v6 05/10] selftests: mptcp: sockopt: set FIONREAD ioctl Geliang Tang
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Geliang Tang @ 2026-07-10  8:59 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

Pass 'len' from the client to the server over the unixfd control channel so
that the client knows the server's payload size in advance for the FIONREAD
loop and TCP_CM_INQ validation in subsequent patches.

Also keep the unixfd open for the second write by moving 'close(unixfd)' to
the end of connect_one_server().

Note: Additionally, silence a -Wstringop-overflow false positive by using
'len - total' as the read size, which lets GCC prove the destination is
large enough.

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 tools/testing/selftests/net/mptcp/mptcp_sockopt.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index fdc7500b79b3..5b6408f92fd6 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -622,10 +622,12 @@ static void connect_one_server(int fd, int unixfd)
 	/* un-block server */
 	ret = read(unixfd, buf2, 4);
 	assert(ret == 4);
-	close(unixfd);
 
 	assert(strncmp(buf2, "xmit", 4) == 0);
 
+	ret = write(unixfd, &len, sizeof(len));
+	assert(ret == (ssize_t)sizeof(len));
+
 	ret = write(fd, buf, len);
 	if (ret < 0)
 		die_perror("write");
@@ -635,7 +637,7 @@ static void connect_one_server(int fd, int unixfd)
 
 	total = 0;
 	do {
-		ret = read(fd, buf2 + total, sizeof(buf2) - total);
+		ret = read(fd, buf2 + total, len - total);
 		if (ret < 0)
 			die_perror("read");
 		if (ret == 0) {
@@ -663,12 +665,14 @@ static void connect_one_server(int fd, int unixfd)
 	if (proto_tx == IPPROTO_MPTCP && proto_rx == IPPROTO_MPTCP)
 		assert(s.mptcpi_rcv_delta == (uint64_t)total);
 	close(fd);
+	close(unixfd);
 }
 
 static void process_one_client(int fd, int unixfd)
 {
 	ssize_t ret, ret2, ret3;
 	struct so_state s;
+	size_t expect_len;
 	char buf[4096];
 
 	memset(&s, 0, sizeof(s));
@@ -677,6 +681,12 @@ static void process_one_client(int fd, int unixfd)
 	ret = write(unixfd, "xmit", 4);
 	assert(ret == 4);
 
+	ret = read(unixfd, &expect_len, sizeof(expect_len));
+	assert(ret == (ssize_t)sizeof(expect_len));
+
+	if (expect_len > sizeof(buf))
+		xerror("expect len %zu exceeds buffer size", expect_len);
+
 	ret = read(fd, buf, sizeof(buf));
 	if (ret < 0)
 		die_perror("read");
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH mptcp-next v6 05/10] selftests: mptcp: sockopt: set FIONREAD ioctl
  2026-07-10  8:59 [PATCH mptcp-next v6 00/10] selftests: consolidate TCP_INQ testing into sockopt Geliang Tang
                   ` (3 preceding siblings ...)
  2026-07-10  8:59 ` [PATCH mptcp-next v6 04/10] selftests: mptcp: sockopt: pass echo length over unixfd Geliang Tang
@ 2026-07-10  8:59 ` Geliang Tang
  2026-07-10  8:59 ` [PATCH mptcp-next v6 06/10] selftests: mptcp: sockopt: add huge data transfer tests Geliang Tang
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Geliang Tang @ 2026-07-10  8:59 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

Implement FIONREAD ioctl checks to validate available data size, ensuring
synchronization between write and read operations with non-blocking waits.

These codes are from mptcp_inq.c.

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 .../selftests/net/mptcp/mptcp_sockopt.c       | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index 5b6408f92fd6..0bd5a9c51332 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -20,6 +20,7 @@
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <sys/ioctl.h>
 
 #include <netdb.h>
 #include <netinet/in.h>
@@ -687,6 +688,24 @@ static void process_one_client(int fd, int unixfd)
 	if (expect_len > sizeof(buf))
 		xerror("expect len %zu exceeds buffer size", expect_len);
 
+	for (;;) {
+		struct timespec req;
+		unsigned int queued;
+
+		ret = ioctl(fd, FIONREAD, &queued);
+		if (ret < 0)
+			die_perror("FIONREAD");
+		if (queued > expect_len)
+			xerror("FIONREAD returned %u, but only %zu expected\n",
+			       queued, expect_len);
+		if (queued == expect_len)
+			break;
+
+		req.tv_sec = 0;
+		req.tv_nsec = 1000 * 1000ul;
+		nanosleep(&req, NULL);
+	}
+
 	ret = read(fd, buf, sizeof(buf));
 	if (ret < 0)
 		die_perror("read");
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH mptcp-next v6 06/10] selftests: mptcp: sockopt: add huge data transfer tests
  2026-07-10  8:59 [PATCH mptcp-next v6 00/10] selftests: consolidate TCP_INQ testing into sockopt Geliang Tang
                   ` (4 preceding siblings ...)
  2026-07-10  8:59 ` [PATCH mptcp-next v6 05/10] selftests: mptcp: sockopt: set FIONREAD ioctl Geliang Tang
@ 2026-07-10  8:59 ` Geliang Tang
  2026-07-10  8:59 ` [PATCH mptcp-next v6 07/10] selftests: mptcp: sockopt: add wait_for_ack helper Geliang Tang
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Geliang Tang @ 2026-07-10  8:59 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

Introduce huge data transfer tests (1-17 MB) to validate MPTCP socket
options under high-volume conditions, including proper EOF handling,
preparing for TCP_INQ support in subsequent patches.

These codes are from mptcp_inq.c, but here they have been placed into
two separate functions.

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 .../selftests/net/mptcp/mptcp_sockopt.c       | 132 +++++++++++++++++-
 1 file changed, 126 insertions(+), 6 deletions(-)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index 0bd5a9c51332..16b58f6ac7b7 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -596,6 +596,55 @@ static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 		do_getsockopt_mptcp_full_info(s, fd);
 }
 
+static void server_huge_transfer(int fd, int unixfd, size_t len)
+{
+	char buf[4096], buf2[4];
+	size_t i, total;
+	ssize_t ret;
+
+	for (i = 0; i < len ; i++) {
+		buf[i] = rand() % 26;
+		buf[i] += 'A';
+	}
+
+	buf[i] = '\n';
+
+	ret = read(unixfd, buf2, 4);
+	assert(ret == 4);
+	assert(strncmp(buf2, "huge", 4) == 0);
+
+	total = rand() % (16 * 1024 * 1024);
+	total += (1 * 1024 * 1024);
+
+	ret = write(unixfd, &total, sizeof(total));
+	assert(ret == (ssize_t)sizeof(total));
+
+	while (total > 0) {
+		if (total > sizeof(buf))
+			len = sizeof(buf);
+		else
+			len = total;
+
+		ret = write(fd, buf, len);
+		if (ret < 0)
+			die_perror("write");
+		total -= ret;
+
+		/* we don't have to care about buf content, only
+		 * number of total bytes sent
+		 */
+	}
+
+	ret = read(unixfd, buf2, 4);
+	assert(ret == 4);
+	assert(strncmp(buf2, "shut", 4) == 0);
+
+	ret = write(fd, buf, 1);
+	assert(ret == 1);
+	ret = write(unixfd, "closed", 6);
+	assert(ret == 6);
+}
+
 static void connect_one_server(int fd, int unixfd)
 {
 	char buf[4096], buf2[4096];
@@ -665,16 +714,83 @@ static void connect_one_server(int fd, int unixfd)
 
 	if (proto_tx == IPPROTO_MPTCP && proto_rx == IPPROTO_MPTCP)
 		assert(s.mptcpi_rcv_delta == (uint64_t)total);
+
+	if (inq)
+		server_huge_transfer(fd, unixfd, len);
+
 	close(fd);
 	close(unixfd);
 }
 
+static size_t client_huge_transfer(int fd, int unixfd)
+{
+	char msg_buf[4096];
+	size_t expect_len;
+	ssize_t ret, tot;
+	char buf[4096];
+	char tmp[16];
+	struct iovec iov = {
+		.iov_base = buf,
+		.iov_len = 1,
+	};
+	struct msghdr msg = {
+		.msg_iov = &iov,
+		.msg_iovlen = 1,
+		.msg_control = msg_buf,
+		.msg_controllen = sizeof(msg_buf),
+	};
+
+	/* request a large swath of data. */
+	ret = write(unixfd, "huge", 4);
+	assert(ret == 4);
+
+	ret = read(unixfd, &expect_len, sizeof(expect_len));
+	assert(ret == (ssize_t)sizeof(expect_len));
+
+	/* peer should send us a few mb of data */
+	if (expect_len <= sizeof(buf))
+		xerror("expect len %zu too small\n", expect_len);
+
+	tot = 0;
+	do {
+		iov.iov_len = sizeof(buf);
+		msg.msg_controllen = sizeof(msg_buf);
+		ret = recvmsg(fd, &msg, 0);
+		if (ret < 0)
+			die_perror("recvmsg");
+		if (ret == 0)
+			xerror("unexpected EOF in huge recv");
+
+		tot += ret;
+	} while ((size_t)tot < expect_len);
+
+	ret = write(unixfd, "shut", 4);
+	assert(ret == 4);
+
+	/* wait for hangup. Should have received one more byte of data. */
+	ret = read(unixfd, tmp, sizeof(tmp));
+	assert(ret == 6);
+	assert(strncmp(tmp, "closed", 6) == 0);
+
+	sleep(1);
+
+	iov.iov_len = 1;
+	msg.msg_controllen = sizeof(msg_buf);
+	ret = recvmsg(fd, &msg, 0);
+	if (ret < 0)
+		die_perror("recvmsg");
+	assert(ret == 1);
+
+	return tot + 1;
+}
+
 static void process_one_client(int fd, int unixfd)
 {
 	ssize_t ret, ret2, ret3;
 	struct so_state s;
 	size_t expect_len;
 	char buf[4096];
+	size_t r = 0;
 
 	memset(&s, 0, sizeof(s));
 	do_getsockopts(&s, fd, 0, 0);
@@ -719,16 +835,20 @@ static void process_one_client(int fd, int unixfd)
 	if (ret2 < 0)
 		die_perror("write");
 
+	if (inq)
+		r = client_huge_transfer(fd, unixfd);
+
 	/* wait for hangup */
 	ret3 = read(fd, buf, 1);
 	if (ret3 != 0)
 		xerror("expected EOF, got %lu", ret3);
 
-	do_getsockopts(&s, fd, ret, ret2);
+	do_getsockopts(&s, fd, ret + r, ret2);
 	if (proto_tx == IPPROTO_MPTCP && proto_rx == IPPROTO_MPTCP &&
-	    s.mptcpi_rcv_delta != (uint64_t)ret + 1)
+	    s.mptcpi_rcv_delta != (uint64_t)ret + r + 1)
 		xerror("mptcpi_rcv_delta %" PRIu64 ", expect %" PRIu64 ", diff %" PRId64,
-		       s.mptcpi_rcv_delta, ret + 1, s.mptcpi_rcv_delta - (ret + 1));
+		       s.mptcpi_rcv_delta, ret + r + 1,
+		       s.mptcpi_rcv_delta - (ret + r + 1));
 
 	/* be nice when running on top of older kernel */
 	if (s.pkt_stats_avail) {
@@ -737,11 +857,11 @@ static void process_one_client(int fd, int unixfd)
 			       ", diff %" PRId64,
 			       s.last_sample.mptcpi_bytes_sent, ret2,
 			       s.last_sample.mptcpi_bytes_sent - ret2);
-		if (s.last_sample.mptcpi_bytes_received != ret)
+		if (s.last_sample.mptcpi_bytes_received != ret + r)
 			xerror("mptcpi_bytes_received %" PRIu64 ", expect %" PRIu64
 			       ", diff %" PRId64,
-			       s.last_sample.mptcpi_bytes_received, ret,
-			       s.last_sample.mptcpi_bytes_received - ret);
+			       s.last_sample.mptcpi_bytes_received, ret + r,
+			       s.last_sample.mptcpi_bytes_received - (ret + r));
 		if (s.last_sample.mptcpi_bytes_acked != ret)
 			xerror("mptcpi_bytes_acked %" PRIu64 ", expect %" PRIu64
 			       ", diff %" PRId64,
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH mptcp-next v6 07/10] selftests: mptcp: sockopt: add wait_for_ack helper
  2026-07-10  8:59 [PATCH mptcp-next v6 00/10] selftests: consolidate TCP_INQ testing into sockopt Geliang Tang
                   ` (5 preceding siblings ...)
  2026-07-10  8:59 ` [PATCH mptcp-next v6 06/10] selftests: mptcp: sockopt: add huge data transfer tests Geliang Tang
@ 2026-07-10  8:59 ` Geliang Tang
  2026-07-10  8:59 ` [PATCH mptcp-next v6 08/10] selftests: mptcp: sockopt: use recvmsg instead of read Geliang Tang
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Geliang Tang @ 2026-07-10  8:59 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

Add wait_for_ack() helper using TIOCOUTQ/SIOCOUTQNSD ioctls to synchronize
tests by waiting for data acknowledgment before proceeding.

These codes are from mptcp_inq.c.

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 .../selftests/net/mptcp/mptcp_sockopt.c       | 42 ++++++++++++++++++-
 1 file changed, 41 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index 16b58f6ac7b7..bc2cb3db3264 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -26,6 +26,7 @@
 #include <netinet/in.h>
 
 #include <linux/tcp.h>
+#include <linux/sockios.h>
 #include <linux/compiler.h>
 
 static int pf = AF_INET;
@@ -596,10 +597,44 @@ static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 		do_getsockopt_mptcp_full_info(s, fd);
 }
 
+/* wait up to timeout milliseconds */
+static void wait_for_ack(int fd, int timeout, size_t total)
+{
+	int i;
+
+	for (i = 0; i < timeout; i++) {
+		int nsd, ret, queued = -1;
+		struct timespec req;
+
+		ret = ioctl(fd, TIOCOUTQ, &queued);
+		if (ret < 0)
+			die_perror("TIOCOUTQ");
+
+		ret = ioctl(fd, SIOCOUTQNSD, &nsd);
+		if (ret < 0)
+			die_perror("SIOCOUTQNSD");
+
+		if ((size_t)queued > total)
+			xerror("TIOCOUTQ %u, but only %zu expected\n",
+			       queued, total);
+		assert(nsd <= queued);
+
+		if (queued == 0)
+			return;
+
+		/* wait for peer to ack rx of all data */
+		req.tv_sec = 0;
+		req.tv_nsec = 1 * 1000 * 1000ul; /* 1ms */
+		nanosleep(&req, NULL);
+	}
+
+	xerror("still tx data queued after %u ms\n", timeout);
+}
+
 static void server_huge_transfer(int fd, int unixfd, size_t len)
 {
 	char buf[4096], buf2[4];
-	size_t i, total;
+	size_t i, total, sent;
 	ssize_t ret;
 
 	for (i = 0; i < len ; i++) {
@@ -615,10 +650,13 @@ static void server_huge_transfer(int fd, int unixfd, size_t len)
 
 	total = rand() % (16 * 1024 * 1024);
 	total += (1 * 1024 * 1024);
+	sent = total;
 
 	ret = write(unixfd, &total, sizeof(total));
 	assert(ret == (ssize_t)sizeof(total));
 
+	wait_for_ack(fd, 5000, len);
+
 	while (total > 0) {
 		if (total > sizeof(buf))
 			len = sizeof(buf);
@@ -639,6 +677,8 @@ static void server_huge_transfer(int fd, int unixfd, size_t len)
 	assert(ret == 4);
 	assert(strncmp(buf2, "shut", 4) == 0);
 
+	wait_for_ack(fd, 5000, sent);
+
 	ret = write(fd, buf, 1);
 	assert(ret == 1);
 	ret = write(unixfd, "closed", 6);
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH mptcp-next v6 08/10] selftests: mptcp: sockopt: use recvmsg instead of read
  2026-07-10  8:59 [PATCH mptcp-next v6 00/10] selftests: consolidate TCP_INQ testing into sockopt Geliang Tang
                   ` (6 preceding siblings ...)
  2026-07-10  8:59 ` [PATCH mptcp-next v6 07/10] selftests: mptcp: sockopt: add wait_for_ack helper Geliang Tang
@ 2026-07-10  8:59 ` Geliang Tang
  2026-07-10  8:59 ` [PATCH mptcp-next v6 09/10] selftests: mptcp: sockopt: add get_tcp_inq helper Geliang Tang
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Geliang Tang @ 2026-07-10  8:59 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

Replace read() with recvmsg() in process_one_client() to enable control
message (CMSG) handling. The original read(fd, buf, sizeof(buf)) is split
into two recvmsg() calls: the first reads exactly one byte, and the second
reads the remaining bytes. This allows the code to access CMSG data for
each received segment, facilitating the upcoming TCP_INQ validation.

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 .../selftests/net/mptcp/mptcp_sockopt.c       | 30 +++++++++++++++++--
 1 file changed, 27 insertions(+), 3 deletions(-)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index bc2cb3db3264..53852b44cfeb 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -827,10 +827,21 @@ static size_t client_huge_transfer(int fd, int unixfd)
 static void process_one_client(int fd, int unixfd)
 {
 	ssize_t ret, ret2, ret3;
+	char msg_buf[4096];
 	struct so_state s;
 	size_t expect_len;
 	char buf[4096];
 	size_t r = 0;
+	struct iovec iov = {
+		.iov_base = buf,
+		.iov_len = 1,
+	};
+	struct msghdr msg = {
+		.msg_iov = &iov,
+		.msg_iovlen = 1,
+		.msg_control = msg_buf,
+		.msg_controllen = sizeof(msg_buf),
+	};
 
 	memset(&s, 0, sizeof(s));
 	do_getsockopts(&s, fd, 0, 0);
@@ -862,9 +873,20 @@ static void process_one_client(int fd, int unixfd)
 		nanosleep(&req, NULL);
 	}
 
-	ret = read(fd, buf, sizeof(buf));
+	/* read one byte */
+	ret = recvmsg(fd, &msg, 0);
+	if (ret < 0)
+		die_perror("recvmsg");
+
+	iov.iov_base = buf + 1;
+	iov.iov_len = sizeof(buf) - 1;
+	msg.msg_controllen = sizeof(msg_buf);
+	ret = recvmsg(fd, &msg, 0);
 	if (ret < 0)
-		die_perror("read");
+		die_perror("recvmsg");
+
+	/* add the first byte */
+	ret += 1;
 
 	assert(s.mptcpi_rcv_delta <= (uint64_t)ret);
 
@@ -879,7 +901,9 @@ static void process_one_client(int fd, int unixfd)
 		r = client_huge_transfer(fd, unixfd);
 
 	/* wait for hangup */
-	ret3 = read(fd, buf, 1);
+	iov.iov_len = 1;
+	msg.msg_controllen = sizeof(msg_buf);
+	ret3 = recvmsg(fd, &msg, 0);
 	if (ret3 != 0)
 		xerror("expected EOF, got %lu", ret3);
 
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH mptcp-next v6 09/10] selftests: mptcp: sockopt: add get_tcp_inq helper
  2026-07-10  8:59 [PATCH mptcp-next v6 00/10] selftests: consolidate TCP_INQ testing into sockopt Geliang Tang
                   ` (7 preceding siblings ...)
  2026-07-10  8:59 ` [PATCH mptcp-next v6 08/10] selftests: mptcp: sockopt: use recvmsg instead of read Geliang Tang
@ 2026-07-10  8:59 ` Geliang Tang
  2026-07-10  8:59 ` [PATCH mptcp-next v6 10/10] selftests: mptcp: sockopt: replace mptcp_inq with sockopt Geliang Tang
  2026-07-10 11:30 ` [PATCH mptcp-next v6 00/10] selftests: consolidate TCP_INQ testing into sockopt MPTCP CI
  10 siblings, 0 replies; 12+ messages in thread
From: Geliang Tang @ 2026-07-10  8:59 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

Add check_tcp_inq() helper to extract and verify TCP_CM_INQ values from
control messages, ensuring correct in-queue data tracking during transfers.

These codes are from mptcp_inq.c.

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 .../selftests/net/mptcp/mptcp_sockopt.c       | 58 +++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index 53852b44cfeb..ac209070e8f2 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -762,8 +762,28 @@ static void connect_one_server(int fd, int unixfd)
 	close(unixfd);
 }
 
+static void get_tcp_inq(struct msghdr *msgh, unsigned int *inqv)
+{
+	struct cmsghdr *cmsg;
+
+	for (cmsg = CMSG_FIRSTHDR(msgh); cmsg;
+	     cmsg = CMSG_NXTHDR(msgh, cmsg)) {
+		if (cmsg->cmsg_level == IPPROTO_TCP &&
+		    cmsg->cmsg_type == TCP_CM_INQ) {
+			if (cmsg->cmsg_len < CMSG_LEN(sizeof(*inqv)))
+				xerror("TCP_CM_INQ cmsg_len too small: %u",
+				       cmsg->cmsg_len);
+			memcpy(inqv, CMSG_DATA(cmsg), sizeof(*inqv));
+			return;
+		}
+	}
+
+	xerror("could not find TCP_CM_INQ cmsg type");
+}
+
 static size_t client_huge_transfer(int fd, int unixfd)
 {
+	unsigned int tcp_inq;
 	char msg_buf[4096];
 	size_t expect_len;
 	ssize_t ret, tot;
@@ -802,6 +822,14 @@ static size_t client_huge_transfer(int fd, int unixfd)
 			xerror("unexpected EOF in huge recv");
 
 		tot += ret;
+
+		get_tcp_inq(&msg, &tcp_inq);
+
+		if (tcp_inq > expect_len - tot)
+			xerror("inq %d, remaining %zu total_len %d\n",
+			       tcp_inq, expect_len - tot, (int)expect_len);
+
+		assert(tcp_inq <= expect_len - tot);
 	} while ((size_t)tot < expect_len);
 
 	ret = write(unixfd, "shut", 4);
@@ -821,12 +849,18 @@ static size_t client_huge_transfer(int fd, int unixfd)
 		die_perror("recvmsg");
 	assert(ret == 1);
 
+	get_tcp_inq(&msg, &tcp_inq);
+
+	/* tcp_inq should be 1 due to received fin. */
+	assert(tcp_inq == 1);
+
 	return tot + 1;
 }
 
 static void process_one_client(int fd, int unixfd)
 {
 	ssize_t ret, ret2, ret3;
+	unsigned int tcp_inq;
 	char msg_buf[4096];
 	struct so_state s;
 	size_t expect_len;
@@ -878,6 +912,16 @@ static void process_one_client(int fd, int unixfd)
 	if (ret < 0)
 		die_perror("recvmsg");
 
+	if (inq) {
+		if (msg.msg_controllen == 0)
+			xerror("msg_controllen is 0");
+
+		get_tcp_inq(&msg, &tcp_inq);
+
+		/* expect cmsg to return expected - 1 */
+		assert((size_t)tcp_inq == (expect_len - 1));
+	}
+
 	iov.iov_base = buf + 1;
 	iov.iov_len = sizeof(buf) - 1;
 	msg.msg_controllen = sizeof(msg_buf);
@@ -885,6 +929,15 @@ static void process_one_client(int fd, int unixfd)
 	if (ret < 0)
 		die_perror("recvmsg");
 
+	if (inq) {
+		/* should have gotten exact remainder of all pending data */
+		assert(ret == (ssize_t)tcp_inq);
+
+		/* should be 0, all drained */
+		get_tcp_inq(&msg, &tcp_inq);
+		assert(tcp_inq == 0);
+	}
+
 	/* add the first byte */
 	ret += 1;
 
@@ -907,6 +960,11 @@ static void process_one_client(int fd, int unixfd)
 	if (ret3 != 0)
 		xerror("expected EOF, got %lu", ret3);
 
+	if (inq) {
+		get_tcp_inq(&msg, &tcp_inq);
+		assert(tcp_inq == 1);
+	}
+
 	do_getsockopts(&s, fd, ret + r, ret2);
 	if (proto_tx == IPPROTO_MPTCP && proto_rx == IPPROTO_MPTCP &&
 	    s.mptcpi_rcv_delta != (uint64_t)ret + r + 1)
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH mptcp-next v6 10/10] selftests: mptcp: sockopt: replace mptcp_inq with sockopt
  2026-07-10  8:59 [PATCH mptcp-next v6 00/10] selftests: consolidate TCP_INQ testing into sockopt Geliang Tang
                   ` (8 preceding siblings ...)
  2026-07-10  8:59 ` [PATCH mptcp-next v6 09/10] selftests: mptcp: sockopt: add get_tcp_inq helper Geliang Tang
@ 2026-07-10  8:59 ` Geliang Tang
  2026-07-10 11:30 ` [PATCH mptcp-next v6 00/10] selftests: consolidate TCP_INQ testing into sockopt MPTCP CI
  10 siblings, 0 replies; 12+ messages in thread
From: Geliang Tang @ 2026-07-10  8:59 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

Update mptcp_sockopt.sh to use mptcp_sockopt binary instead of
mptcp_inq. This consolidates TCP_INQ testing into a single test binary
while maintaining equivalent test coverage.

Delete mptcp_inq binary and references since its functionality has been
fully integrated into mptcp_sockopt. This simplifies the test suite
structure and reduces maintenance overhead.

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 tools/testing/selftests/net/mptcp/.gitignore  |   1 -
 tools/testing/selftests/net/mptcp/Makefile    |   1 -
 tools/testing/selftests/net/mptcp/mptcp_inq.c | 614 ------------------
 .../selftests/net/mptcp/mptcp_sockopt.sh      |   8 +-
 4 files changed, 4 insertions(+), 620 deletions(-)
 delete mode 100644 tools/testing/selftests/net/mptcp/mptcp_inq.c

diff --git a/tools/testing/selftests/net/mptcp/.gitignore b/tools/testing/selftests/net/mptcp/.gitignore
index 833279fb34e2..c62e91ce385d 100644
--- a/tools/testing/selftests/net/mptcp/.gitignore
+++ b/tools/testing/selftests/net/mptcp/.gitignore
@@ -1,7 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 mptcp_connect
 mptcp_diag
-mptcp_inq
 mptcp_sockopt
 pm_nl_ctl
 *.pcap
diff --git a/tools/testing/selftests/net/mptcp/Makefile b/tools/testing/selftests/net/mptcp/Makefile
index 22ba0da2adb8..fa80e6448728 100644
--- a/tools/testing/selftests/net/mptcp/Makefile
+++ b/tools/testing/selftests/net/mptcp/Makefile
@@ -22,7 +22,6 @@ TEST_PROGS := \
 TEST_GEN_FILES := \
 	mptcp_connect \
 	mptcp_diag \
-	mptcp_inq \
 	mptcp_sockopt \
 	pm_nl_ctl \
 # end of TEST_GEN_FILES
diff --git a/tools/testing/selftests/net/mptcp/mptcp_inq.c b/tools/testing/selftests/net/mptcp/mptcp_inq.c
deleted file mode 100644
index 5716998da192..000000000000
--- a/tools/testing/selftests/net/mptcp/mptcp_inq.c
+++ /dev/null
@@ -1,614 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-#define _GNU_SOURCE
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <unistd.h>
-#include <time.h>
-
-#include <sys/ioctl.h>
-#include <sys/random.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <netdb.h>
-#include <netinet/in.h>
-
-#include <linux/tcp.h>
-#include <linux/sockios.h>
-#include <linux/compiler.h>
-
-#ifndef IPPROTO_MPTCP
-#define IPPROTO_MPTCP 262
-#endif
-#ifndef SOL_MPTCP
-#define SOL_MPTCP 284
-#endif
-
-static int pf = AF_INET;
-static int proto_tx = IPPROTO_MPTCP;
-static int proto_rx = IPPROTO_MPTCP;
-
-static void __noreturn die_perror(const char *msg)
-{
-	perror(msg);
-	exit(1);
-}
-
-static void die_usage(int r)
-{
-	fprintf(stderr, "Usage: mptcp_inq [-6] [ -t tcp|mptcp ] [ -r tcp|mptcp]\n");
-	exit(r);
-}
-
-static void __noreturn xerror(const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	vfprintf(stderr, fmt, ap);
-	va_end(ap);
-	fputc('\n', stderr);
-	exit(1);
-}
-
-static const char *getxinfo_strerr(int err)
-{
-	if (err == EAI_SYSTEM)
-		return strerror(errno);
-
-	return gai_strerror(err);
-}
-
-static void xgetaddrinfo(const char *node, const char *service,
-			 struct addrinfo *hints,
-			 struct addrinfo **res)
-{
-	int err;
-
-again:
-	err = getaddrinfo(node, service, hints, res);
-	if (err) {
-		const char *errstr;
-
-		if (err == EAI_SOCKTYPE) {
-			hints->ai_protocol = IPPROTO_TCP;
-			goto again;
-		}
-
-		errstr = getxinfo_strerr(err);
-
-		fprintf(stderr, "Fatal: getaddrinfo(%s:%s): %s\n",
-			node ? node : "", service ? service : "", errstr);
-		exit(1);
-	}
-}
-
-static int sock_listen_mptcp(const char * const listenaddr,
-			     const char * const port)
-{
-	int sock = -1;
-	struct addrinfo hints = {
-		.ai_protocol = IPPROTO_MPTCP,
-		.ai_socktype = SOCK_STREAM,
-		.ai_flags = AI_PASSIVE | AI_NUMERICHOST
-	};
-
-	hints.ai_family = pf;
-
-	struct addrinfo *a, *addr;
-	int one = 1;
-
-	xgetaddrinfo(listenaddr, port, &hints, &addr);
-	hints.ai_family = pf;
-
-	for (a = addr; a; a = a->ai_next) {
-		sock = socket(a->ai_family, a->ai_socktype, proto_rx);
-		if (sock < 0)
-			continue;
-
-		if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one,
-				     sizeof(one)))
-			perror("setsockopt");
-
-		if (bind(sock, a->ai_addr, a->ai_addrlen) == 0)
-			break; /* success */
-
-		perror("bind");
-		close(sock);
-		sock = -1;
-	}
-
-	freeaddrinfo(addr);
-
-	if (sock < 0)
-		xerror("could not create listen socket");
-
-	if (listen(sock, 20))
-		die_perror("listen");
-
-	return sock;
-}
-
-static int sock_connect_mptcp(const char * const remoteaddr,
-			      const char * const port, int proto)
-{
-	struct addrinfo hints = {
-		.ai_protocol = IPPROTO_MPTCP,
-		.ai_socktype = SOCK_STREAM,
-	};
-	struct addrinfo *a, *addr;
-	int sock = -1;
-
-	hints.ai_family = pf;
-
-	xgetaddrinfo(remoteaddr, port, &hints, &addr);
-	for (a = addr; a; a = a->ai_next) {
-		sock = socket(a->ai_family, a->ai_socktype, proto);
-		if (sock < 0)
-			continue;
-
-		if (connect(sock, a->ai_addr, a->ai_addrlen) == 0)
-			break; /* success */
-
-		die_perror("connect");
-	}
-
-	if (sock < 0)
-		xerror("could not create connect socket");
-
-	freeaddrinfo(addr);
-	return sock;
-}
-
-static int protostr_to_num(const char *s)
-{
-	if (strcasecmp(s, "tcp") == 0)
-		return IPPROTO_TCP;
-	if (strcasecmp(s, "mptcp") == 0)
-		return IPPROTO_MPTCP;
-
-	die_usage(1);
-	return 0;
-}
-
-static void parse_opts(int argc, char **argv)
-{
-	int c;
-
-	while ((c = getopt(argc, argv, "h6t:r:")) != -1) {
-		switch (c) {
-		case 'h':
-			die_usage(0);
-			break;
-		case '6':
-			pf = AF_INET6;
-			break;
-		case 't':
-			proto_tx = protostr_to_num(optarg);
-			break;
-		case 'r':
-			proto_rx = protostr_to_num(optarg);
-			break;
-		default:
-			die_usage(1);
-			break;
-		}
-	}
-}
-
-/* wait up to timeout milliseconds */
-static void wait_for_ack(int fd, int timeout, size_t total)
-{
-	int i;
-
-	for (i = 0; i < timeout; i++) {
-		int nsd, ret, queued = -1;
-		struct timespec req;
-
-		ret = ioctl(fd, TIOCOUTQ, &queued);
-		if (ret < 0)
-			die_perror("TIOCOUTQ");
-
-		ret = ioctl(fd, SIOCOUTQNSD, &nsd);
-		if (ret < 0)
-			die_perror("SIOCOUTQNSD");
-
-		if ((size_t)queued > total)
-			xerror("TIOCOUTQ %u, but only %zu expected\n", queued, total);
-		assert(nsd <= queued);
-
-		if (queued == 0)
-			return;
-
-		/* wait for peer to ack rx of all data */
-		req.tv_sec = 0;
-		req.tv_nsec = 1 * 1000 * 1000ul; /* 1ms */
-		nanosleep(&req, NULL);
-	}
-
-	xerror("still tx data queued after %u ms\n", timeout);
-}
-
-static void connect_one_server(int fd, int unixfd)
-{
-	size_t len, i, total, sent;
-	char buf[4096], buf2[4096];
-	ssize_t ret;
-
-	len = rand() % (sizeof(buf) - 1);
-
-	if (len < 128)
-		len = 128;
-
-	for (i = 0; i < len ; i++) {
-		buf[i] = rand() % 26;
-		buf[i] += 'A';
-	}
-
-	buf[i] = '\n';
-
-	/* un-block server */
-	ret = read(unixfd, buf2, 4);
-	assert(ret == 4);
-
-	assert(strncmp(buf2, "xmit", 4) == 0);
-
-	ret = write(unixfd, &len, sizeof(len));
-	assert(ret == (ssize_t)sizeof(len));
-
-	ret = write(fd, buf, len);
-	if (ret < 0)
-		die_perror("write");
-
-	if (ret != (ssize_t)len)
-		xerror("short write");
-
-	ret = read(unixfd, buf2, 4);
-	assert(strncmp(buf2, "huge", 4) == 0);
-
-	total = rand() % (16 * 1024 * 1024);
-	total += (1 * 1024 * 1024);
-	sent = total;
-
-	ret = write(unixfd, &total, sizeof(total));
-	assert(ret == (ssize_t)sizeof(total));
-
-	wait_for_ack(fd, 5000, len);
-
-	while (total > 0) {
-		if (total > sizeof(buf))
-			len = sizeof(buf);
-		else
-			len = total;
-
-		ret = write(fd, buf, len);
-		if (ret < 0)
-			die_perror("write");
-		total -= ret;
-
-		/* we don't have to care about buf content, only
-		 * number of total bytes sent
-		 */
-	}
-
-	ret = read(unixfd, buf2, 4);
-	assert(ret == 4);
-	assert(strncmp(buf2, "shut", 4) == 0);
-
-	wait_for_ack(fd, 5000, sent);
-
-	ret = write(fd, buf, 1);
-	assert(ret == 1);
-	close(fd);
-	ret = write(unixfd, "closed", 6);
-	assert(ret == 6);
-
-	close(unixfd);
-}
-
-static void get_tcp_inq(struct msghdr *msgh, unsigned int *inqv)
-{
-	struct cmsghdr *cmsg;
-
-	for (cmsg = CMSG_FIRSTHDR(msgh); cmsg ; cmsg = CMSG_NXTHDR(msgh, cmsg)) {
-		if (cmsg->cmsg_level == IPPROTO_TCP && cmsg->cmsg_type == TCP_CM_INQ) {
-			memcpy(inqv, CMSG_DATA(cmsg), sizeof(*inqv));
-			return;
-		}
-	}
-
-	xerror("could not find TCP_CM_INQ cmsg type");
-}
-
-static void process_one_client(int fd, int unixfd)
-{
-	unsigned int tcp_inq;
-	size_t expect_len;
-	char msg_buf[4096];
-	char buf[4096];
-	char tmp[16];
-	struct iovec iov = {
-		.iov_base = buf,
-		.iov_len = 1,
-	};
-	struct msghdr msg = {
-		.msg_iov = &iov,
-		.msg_iovlen = 1,
-		.msg_control = msg_buf,
-		.msg_controllen = sizeof(msg_buf),
-	};
-	ssize_t ret, tot;
-
-	ret = write(unixfd, "xmit", 4);
-	assert(ret == 4);
-
-	ret = read(unixfd, &expect_len, sizeof(expect_len));
-	assert(ret == (ssize_t)sizeof(expect_len));
-
-	if (expect_len > sizeof(buf))
-		xerror("expect len %zu exceeds buffer size", expect_len);
-
-	for (;;) {
-		struct timespec req;
-		unsigned int queued;
-
-		ret = ioctl(fd, FIONREAD, &queued);
-		if (ret < 0)
-			die_perror("FIONREAD");
-		if (queued > expect_len)
-			xerror("FIONREAD returned %u, but only %zu expected\n",
-			       queued, expect_len);
-		if (queued == expect_len)
-			break;
-
-		req.tv_sec = 0;
-		req.tv_nsec = 1000 * 1000ul;
-		nanosleep(&req, NULL);
-	}
-
-	/* read one byte, expect cmsg to return expected - 1 */
-	ret = recvmsg(fd, &msg, 0);
-	if (ret < 0)
-		die_perror("recvmsg");
-
-	if (msg.msg_controllen == 0)
-		xerror("msg_controllen is 0");
-
-	get_tcp_inq(&msg, &tcp_inq);
-
-	assert((size_t)tcp_inq == (expect_len - 1));
-
-	iov.iov_len = sizeof(buf);
-	ret = recvmsg(fd, &msg, 0);
-	if (ret < 0)
-		die_perror("recvmsg");
-
-	/* should have gotten exact remainder of all pending data */
-	assert(ret == (ssize_t)tcp_inq);
-
-	/* should be 0, all drained */
-	get_tcp_inq(&msg, &tcp_inq);
-	assert(tcp_inq == 0);
-
-	/* request a large swath of data. */
-	ret = write(unixfd, "huge", 4);
-	assert(ret == 4);
-
-	ret = read(unixfd, &expect_len, sizeof(expect_len));
-	assert(ret == (ssize_t)sizeof(expect_len));
-
-	/* peer should send us a few mb of data */
-	if (expect_len <= sizeof(buf))
-		xerror("expect len %zu too small\n", expect_len);
-
-	tot = 0;
-	do {
-		iov.iov_len = sizeof(buf);
-		ret = recvmsg(fd, &msg, 0);
-		if (ret < 0)
-			die_perror("recvmsg");
-
-		tot += ret;
-
-		get_tcp_inq(&msg, &tcp_inq);
-
-		if (tcp_inq > expect_len - tot)
-			xerror("inq %d, remaining %d total_len %d\n",
-			       tcp_inq, expect_len - tot, (int)expect_len);
-
-		assert(tcp_inq <= expect_len - tot);
-	} while ((size_t)tot < expect_len);
-
-	ret = write(unixfd, "shut", 4);
-	assert(ret == 4);
-
-	/* wait for hangup. Should have received one more byte of data. */
-	ret = read(unixfd, tmp, sizeof(tmp));
-	assert(ret == 6);
-	assert(strncmp(tmp, "closed", 6) == 0);
-
-	sleep(1);
-
-	iov.iov_len = 1;
-	ret = recvmsg(fd, &msg, 0);
-	if (ret < 0)
-		die_perror("recvmsg");
-	assert(ret == 1);
-
-	get_tcp_inq(&msg, &tcp_inq);
-
-	/* tcp_inq should be 1 due to received fin. */
-	assert(tcp_inq == 1);
-
-	iov.iov_len = 1;
-	ret = recvmsg(fd, &msg, 0);
-	if (ret < 0)
-		die_perror("recvmsg");
-
-	/* expect EOF */
-	assert(ret == 0);
-	get_tcp_inq(&msg, &tcp_inq);
-	assert(tcp_inq == 1);
-
-	close(fd);
-}
-
-static int xaccept(int s)
-{
-	int fd = accept(s, NULL, 0);
-
-	if (fd < 0)
-		die_perror("accept");
-
-	return fd;
-}
-
-static int server(int unixfd)
-{
-	int fd = -1, r, on = 1;
-
-	switch (pf) {
-	case AF_INET:
-		fd = sock_listen_mptcp("127.0.0.1", "15432");
-		break;
-	case AF_INET6:
-		fd = sock_listen_mptcp("::1", "15432");
-		break;
-	default:
-		xerror("Unknown pf %d\n", pf);
-		break;
-	}
-
-	r = write(unixfd, "conn", 4);
-	assert(r == 4);
-
-	alarm(15);
-	r = xaccept(fd);
-
-	if (-1 == setsockopt(r, IPPROTO_TCP, TCP_INQ, &on, sizeof(on)))
-		die_perror("setsockopt");
-
-	process_one_client(r, unixfd);
-
-	close(fd);
-	return 0;
-}
-
-static int client(int unixfd)
-{
-	int fd = -1;
-
-	alarm(15);
-
-	switch (pf) {
-	case AF_INET:
-		fd = sock_connect_mptcp("127.0.0.1", "15432", proto_tx);
-		break;
-	case AF_INET6:
-		fd = sock_connect_mptcp("::1", "15432", proto_tx);
-		break;
-	default:
-		xerror("Unknown pf %d\n", pf);
-	}
-
-	connect_one_server(fd, unixfd);
-
-	return 0;
-}
-
-static void init_rng(void)
-{
-	unsigned int foo;
-
-	if (getrandom(&foo, sizeof(foo), 0) == -1) {
-		perror("getrandom");
-		exit(1);
-	}
-
-	srand(foo);
-}
-
-static pid_t xfork(void)
-{
-	pid_t p = fork();
-
-	if (p < 0)
-		die_perror("fork");
-	else if (p == 0)
-		init_rng();
-
-	return p;
-}
-
-static int rcheck(int wstatus, const char *what)
-{
-	if (WIFEXITED(wstatus)) {
-		if (WEXITSTATUS(wstatus) == 0)
-			return 0;
-		fprintf(stderr, "%s exited, status=%d\n", what, WEXITSTATUS(wstatus));
-		return WEXITSTATUS(wstatus);
-	} else if (WIFSIGNALED(wstatus)) {
-		xerror("%s killed by signal %d\n", what, WTERMSIG(wstatus));
-	} else if (WIFSTOPPED(wstatus)) {
-		xerror("%s stopped by signal %d\n", what, WSTOPSIG(wstatus));
-	}
-
-	return 111;
-}
-
-int main(int argc, char *argv[])
-{
-	int e1, e2, wstatus;
-	pid_t s, c, ret;
-	int unixfds[2];
-
-	parse_opts(argc, argv);
-
-	e1 = socketpair(AF_UNIX, SOCK_DGRAM, 0, unixfds);
-	if (e1 < 0)
-		die_perror("pipe");
-
-	s = xfork();
-	if (s == 0) {
-		close(unixfds[0]);
-		ret = server(unixfds[1]);
-		close(unixfds[1]);
-		return ret;
-	}
-
-	close(unixfds[1]);
-
-	/* wait until server bound a socket */
-	e1 = read(unixfds[0], &e1, 4);
-	assert(e1 == 4);
-
-	c = xfork();
-	if (c == 0)
-		return client(unixfds[0]);
-
-	close(unixfds[0]);
-
-	ret = waitpid(s, &wstatus, 0);
-	if (ret == -1)
-		die_perror("waitpid");
-	e1 = rcheck(wstatus, "server");
-	ret = waitpid(c, &wstatus, 0);
-	if (ret == -1)
-		die_perror("waitpid");
-	e2 = rcheck(wstatus, "client");
-
-	return e1 ? e1 : e2;
-}
diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
index e850a87429b6..a39265555438 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
@@ -308,7 +308,7 @@ run_tests()
 do_tcpinq_test()
 {
 	print_title "TCP_INQ cmsg/ioctl $*"
-	ip netns exec "$ns_sbox" ./mptcp_inq "$@"
+	ip netns exec "$ns_sbox" ./mptcp_sockopt "$@"
 	local lret=$?
 	if [ $lret -ne 0 ];then
 		ret=$lret
@@ -334,19 +334,19 @@ do_tcpinq_tests()
 
 	local args
 	for args in "-t tcp" "-r tcp"; do
-		do_tcpinq_test $args
+		do_tcpinq_test $args -i
 		lret=$?
 		if [ $lret -ne 0 ] ; then
 			return $lret
 		fi
-		do_tcpinq_test -6 $args
+		do_tcpinq_test -6 $args -i
 		lret=$?
 		if [ $lret -ne 0 ] ; then
 			return $lret
 		fi
 	done
 
-	do_tcpinq_test -r tcp -t tcp
+	do_tcpinq_test -r tcp -t tcp -i
 
 	return $?
 }
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH mptcp-next v6 00/10] selftests: consolidate TCP_INQ testing into sockopt
  2026-07-10  8:59 [PATCH mptcp-next v6 00/10] selftests: consolidate TCP_INQ testing into sockopt Geliang Tang
                   ` (9 preceding siblings ...)
  2026-07-10  8:59 ` [PATCH mptcp-next v6 10/10] selftests: mptcp: sockopt: replace mptcp_inq with sockopt Geliang Tang
@ 2026-07-10 11:30 ` MPTCP CI
  10 siblings, 0 replies; 12+ messages in thread
From: MPTCP CI @ 2026-07-10 11:30 UTC (permalink / raw)
  To: Geliang Tang; +Cc: mptcp

Hi Geliang,

Thank you for your modifications, that's great!

Our CI did some validations and here is its report:

- KVM Validation: normal (except selftest_mptcp_join): Unstable: 1 failed test(s): selftest_simult_flows - Critical: Global Timeout - Notice: Call Traces at boot time, rebooted and continued ❌
- KVM Validation: normal (only selftest_mptcp_join): Success! ✅
- KVM Validation: debug (except selftest_mptcp_join): Success! ✅
- KVM Validation: debug (only selftest_mptcp_join): Success! ✅
- KVM Validation: btf-normal (only bpftest_all): Success! ✅
- KVM Validation: btf-debug (only bpftest_all): Success! ✅
- Task: https://github.com/multipath-tcp/mptcp_net-next/actions/runs/29083422362

Initiator: Patchew Applier
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/4cc154851693
Patchwork: https://patchwork.kernel.org/project/mptcp/list/?series=1125257


If there are some issues, you can reproduce them using the same environment as
the one used by the CI thanks to a docker image, e.g.:

    $ cd [kernel source code]
    $ docker run -v "${PWD}:${PWD}:rw" -w "${PWD}" --privileged --rm -it \
        --pull always mptcp/mptcp-upstream-virtme-docker:latest \
        auto-normal

For more details:

    https://github.com/multipath-tcp/mptcp-upstream-virtme-docker


Please note that despite all the efforts that have been already done to have a
stable tests suite when executed on a public CI like here, it is possible some
reported issues are not due to your modifications. Still, do not hesitate to
help us improve that ;-)

Cheers,
MPTCP GH Action bot
Bot operated by Matthieu Baerts (NGI0 Core)

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2026-07-10 11:30 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-10  8:59 [PATCH mptcp-next v6 00/10] selftests: consolidate TCP_INQ testing into sockopt Geliang Tang
2026-07-10  8:59 ` [PATCH mptcp-next v6 01/10] selftests: mptcp: sockopt: add tx/rx protocol options Geliang Tang
2026-07-10  8:59 ` [PATCH mptcp-next v6 02/10] selftests: mptcp: sockopt: add TCP_INQ test option Geliang Tang
2026-07-10  8:59 ` [PATCH mptcp-next v6 03/10] selftests: mptcp: sockopt: use unix socket instead of pipe Geliang Tang
2026-07-10  8:59 ` [PATCH mptcp-next v6 04/10] selftests: mptcp: sockopt: pass echo length over unixfd Geliang Tang
2026-07-10  8:59 ` [PATCH mptcp-next v6 05/10] selftests: mptcp: sockopt: set FIONREAD ioctl Geliang Tang
2026-07-10  8:59 ` [PATCH mptcp-next v6 06/10] selftests: mptcp: sockopt: add huge data transfer tests Geliang Tang
2026-07-10  8:59 ` [PATCH mptcp-next v6 07/10] selftests: mptcp: sockopt: add wait_for_ack helper Geliang Tang
2026-07-10  8:59 ` [PATCH mptcp-next v6 08/10] selftests: mptcp: sockopt: use recvmsg instead of read Geliang Tang
2026-07-10  8:59 ` [PATCH mptcp-next v6 09/10] selftests: mptcp: sockopt: add get_tcp_inq helper Geliang Tang
2026-07-10  8:59 ` [PATCH mptcp-next v6 10/10] selftests: mptcp: sockopt: replace mptcp_inq with sockopt Geliang Tang
2026-07-10 11:30 ` [PATCH mptcp-next v6 00/10] selftests: consolidate TCP_INQ testing into sockopt MPTCP CI

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox