MPTCP Linux Development
 help / color / mirror / Atom feed
* [RFC PATCH mptcp-next v15 0/5] mptcp: Fast Open Mechanism
@ 2022-11-06 15:24 Dmytro Shytyi
  2022-11-06 15:24 ` [RFC PATCH mptcp-next v15 1/5] mptcp: introduce MSG_FASTOPEN flag Dmytro Shytyi
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Dmytro Shytyi @ 2022-11-06 15:24 UTC (permalink / raw)
  To: mptcp; +Cc: Dmytro Shytyi

These patches focus on the Initiator and partially on Listener side.
The next options in userspace are available:
a) sendto(..., ..., ..., MSG_FASTOPEN, ..., ...);
b) setsockopt(..., SOL_TCP, TCP_FASTOPEN, ..., ...);

These patches implement Appendix-B of RFC8684 (MPTFO).

We would like to credit Paulo Abeni, Mat Martineau, Matthieu Baerts and
Benjamin Hesmans for advices and ideas that improved these patches.

Signed-off-by: Dmytro Shytyi <dmytro@shytyi.net>
---
v14 -> v15:
 - Reduce code size to perform MPTFO selftests. Reuse run_tests_lo().
 - In v15 proposed change of selftests introduce a reproducible issue.

Observed behavior: 
# INFO: with MPTFO start
# ns2 MPTCP -> ns1 (10.0.1.1:10054      ) MPTCP (duration    81ms) [ OK ]
# ns2 MPTCP -> ns1 (10.0.1.1:10055      ) MPTCP (duration    85ms) [ FAIL ] file received by server does not match (in, out):
# -rw------- 1 root root 4561948 Nov  6 14:44 /tmp/tmp.9LKqAENkkp
# Trailing bytes are:
# MPTCP_TEST_FILE_END_MARKER
# -rw------- 1 root root 4560528 Nov  6 14:46 /tmp/tmp.sZoeneg8ix
# Trailing bytes are:
# MPTCP_TEST_FILE_END_MARKER

Analysis:
- It seems like at the second round when data supposed to be sent in SYN, output data misses first 1420 bytes, that should be a part of the [Syn] packet. 
- With local tests (without selftest) the server in userspace receives the data in the SYN during the second round.
- To confirm that data is sent in SYN, the tcpdump was launched during tests (context of tests with tcpdump: in func sock_connect_mptcp the var was changed: char wbuf[8192] to char wbuf[511] for observavility purposes.
Output of pcap is presented below.
root@9a011dab3a59:/mnt/mptcp_net-next/tools/testing/selftests/net/mptcp# tcpdump -r 635ee290-Fz3fsx-ns2-ns1-MPTCP-MPTCP-10.0.1.1-10042-listener.pcap | grep -w "[S]"
reading from file 635ee290-Fz3fsx-ns2-ns1-MPTCP-MPTCP-10.0.1.1-10042-listener.pcap, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 65535
20:51:50.770789 sit0  In  IP 10.0.1.2.32944 > 10.0.1.1.10042: Flags [S], seq 980486723, win 64240, options [mss 1460,sackOK,TS val 2478157679 ecr 0,nop,wscale 7,tfo  cookiereq,nop,nop,mptcp capable v1], length 0
20:51:50.770807 sit0  Out IP 10.0.1.1.10042 > 10.0.1.2.32944: Flags [S.], seq 1788401934, ack 980486724, win 65160, options [mss 1460,nop,nop,sackOK,nop,wscale 7,tfo  cookie de367be85d45564d,nop,nop,mptcp capable v1 {0x2b02096a5416249e}], length 0
root@9a011dab3a59:/mnt/mptcp_net-next/tools/testing/selftests/net/mptcp# tcpdump -r 635ee290-Fz3fsx-ns2-ns1-MPTCP-MPTCP-10.0.1.1-10043-listener.pcap | grep -w "[S]"
reading from file 635ee290-Fz3fsx-ns2-ns1-MPTCP-MPTCP-10.0.1.1-10043-listener.pcap, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 65535
20:51:53.766945 sit0  In  IP 10.0.1.2.50620 > 10.0.1.1.10043: Flags [S], seq 831892394:831892905, win 64240, options [mss 1460,sackOK,TS val 2478160675 ecr 0,nop,wscale 7,tfo  cookie de367be85d45564d,nop,nop,mptcp capable v1], length 511
20:51:53.766965 sit0  Out IP 10.0.1.1.10043 > 10.0.1.2.50620: Flags [S.], seq 4054084662, ack 831892906, win 65160, options [mss 1460,sackOK,TS val 1954362321 ecr 2478160675,nop,wscale 7,mptcp capable v1 {0x7bf8471b32013c7d}], length 0
root@9a011dab3a59:/mnt/mptcp_net-next/tools/testing/selftests/net/mptcp# tcpdump -r 635ee290-Fz3fsx-ns2-ns1-MPTCP-MPTCP-10.0.1.1-10044-listener.pcap | grep -w "[S]"
reading from file 635ee290-Fz3fsx-ns2-ns1-MPTCP-MPTCP-10.0.1.1-10044-listener.pcap, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 65535
20:51:57.084750 sit0  In  IP 10.0.1.2.43624 > 10.0.1.1.10044: Flags [S], seq 835270974:835271485, win 64240, options [mss 1460,sackOK,TS val 2478163993 ecr 0,nop,wscale 7,tfo  cookie de367be85d45564d,nop,nop,mptcp capable v1], length 511
20:51:57.084772 sit0  Out IP 10.0.1.1.10044 > 10.0.1.2.43624: Flags [S.], seq 650287874, ack 835271486, win 65160, options [mss 1460,sackOK,TS val 1954365639 ecr 2478163993,nop,wscale 7,mptcp capable v1 {0x7b3cb5cf253aec1b}], length 0

---

Dmytro Shytyi (5):
  mptcp: introduce MSG_FASTOPEN flag
  mptcp: implement delayed seq generation for passive fastopen
  mptcp: add subflow_v(4,6)_send_synack()
  mptcp: add TCP_FASTOPEN sock option
  selftests: mptcp: mptfo Initiator/Listener

 net/mptcp/Makefile                            |   2 +-
 net/mptcp/fastopen.c                          |  66 ++++++++++
 net/mptcp/options.c                           |   5 +
 net/mptcp/protocol.c                          |  20 +--
 net/mptcp/protocol.h                          |  18 +++
 net/mptcp/sockopt.c                           |   5 +-
 net/mptcp/subflow.c                           |  42 ++++++
 .../selftests/net/mptcp/mptcp_connect.c       | 121 +++++++++++++-----
 .../selftests/net/mptcp/mptcp_connect.sh      |  21 +++
 9 files changed, 253 insertions(+), 47 deletions(-)
 create mode 100644 net/mptcp/fastopen.c

-- 
2.34.1



^ permalink raw reply	[flat|nested] 11+ messages in thread
* [RFC PATCH mptcp-next v14 5/5] selftests: mptcp: mptfo Initiator/Listener
@ 2022-10-10 22:18 Dmytro Shytyi
  2022-10-11  0:01 ` selftests: mptcp: mptfo Initiator/Listener: Tests Results MPTCP CI
  0 siblings, 1 reply; 11+ messages in thread
From: Dmytro Shytyi @ 2022-10-10 22:18 UTC (permalink / raw)
  To: mptcp; +Cc: Dmytro Shytyi

This patch adds the selftests support for mptfo in mptcp_connect.c,.sh
We introduce mptfo option, that sets "TCP_FASTOPEN" + "MSG_FASTOPEN"
We call sendto() instead of connect().

Signed-off-by: Dmytro Shytyi <dmytro@shytyi.net>
---
 .../selftests/net/mptcp/mptcp_connect.c       | 140 +++++++++++++-----
 .../selftests/net/mptcp/mptcp_connect.sh      |  77 ++++++++++
 2 files changed, 184 insertions(+), 33 deletions(-)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c
index e54653ea2ed4..fdb934eb97ec 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_connect.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c
@@ -83,6 +83,7 @@ struct cfg_cmsg_types {
 
 struct cfg_sockopt_types {
 	unsigned int transparent:1;
+	unsigned int mptfo:1;
 };
 
 struct tcp_inq_state {
@@ -90,6 +91,7 @@ struct tcp_inq_state {
 	bool expect_eof;
 };
 
+static size_t do_write(const int fd, char *buf, const size_t len);
 static struct tcp_inq_state tcp_inq;
 
 static struct cfg_cmsg_types cfg_cmsg_types;
@@ -232,6 +234,22 @@ static void set_transparent(int fd, int pf)
 	}
 }
 
+static void set_mptfo(int fd, int pf)
+{
+	int qlen = 25;
+
+	switch (pf) {
+	case AF_INET:
+		if (-1 == setsockopt(fd, 6, TCP_FASTOPEN, &qlen, sizeof(qlen)))
+			perror("TCP_FASTOPEN");
+		break;
+	case AF_INET6:
+		if (-1 == setsockopt(fd, 6, TCP_FASTOPEN, &qlen, sizeof(qlen)))
+			perror("TCP_FASTOPEN");
+		break;
+	}
+}
+
 static int do_ulp_so(int sock, const char *name)
 {
 	return setsockopt(sock, IPPROTO_TCP, TCP_ULP, name, strlen(name));
@@ -300,6 +318,9 @@ static int sock_listen_mptcp(const char * const listenaddr,
 		if (cfg_sockopt_types.transparent)
 			set_transparent(sock, pf);
 
+		if (cfg_sockopt_types.mptfo)
+			set_mptfo(sock, pf);
+
 		if (bind(sock, a->ai_addr, a->ai_addrlen) == 0)
 			break; /* success */
 
@@ -330,13 +351,18 @@ static int sock_listen_mptcp(const char * const listenaddr,
 
 static int sock_connect_mptcp(const char * const remoteaddr,
 			      const char * const port, int proto,
-			      struct addrinfo **peer)
+			      struct addrinfo **peer,
+			      int infd,
+			      unsigned int *woff)
 {
 	struct addrinfo hints = {
 		.ai_protocol = IPPROTO_TCP,
 		.ai_socktype = SOCK_STREAM,
 	};
 	struct addrinfo *a, *addr;
+	unsigned int wlen = 0;
+	int syn_copied = 0;
+	char wbuf[8192];
 	int sock = -1;
 
 	hints.ai_family = pf;
@@ -354,14 +380,33 @@ static int sock_connect_mptcp(const char * const remoteaddr,
 		if (cfg_mark)
 			set_mark(sock, cfg_mark);
 
-		if (connect(sock, a->ai_addr, a->ai_addrlen) == 0) {
-			*peer = a;
-			break; /* success */
-		}
+		if (cfg_sockopt_types.mptfo) {
+			if (wlen == 0)
+				wlen = read(infd, wbuf, sizeof(wbuf));
 
-		perror("connect()");
-		close(sock);
-		sock = -1;
+			syn_copied = sendto(sock, wbuf, wlen, MSG_FASTOPEN,
+					    a->ai_addr, a->ai_addrlen);
+			if (syn_copied) {
+				*woff = syn_copied;
+				*peer = a;
+				break; /* success */
+			}
+		} else {
+			if (connect(sock, a->ai_addr, a->ai_addrlen) == 0) {
+				*peer = a;
+				break; /* success */
+			}
+		}
+		if (cfg_sockopt_types.mptfo) {
+			perror("sendto()");
+			close(sock);
+			sock = -1;
+		} else {
+
+			perror("connect()");
+			close(sock);
+			sock = -1;
+		}
 	}
 
 	freeaddrinfo(addr);
@@ -571,13 +616,14 @@ static void shut_wr(int fd)
 	shutdown(fd, SHUT_WR);
 }
 
-static int copyfd_io_poll(int infd, int peerfd, int outfd, bool *in_closed_after_out)
+static int copyfd_io_poll(int infd, int peerfd, int outfd,
+			  bool *in_closed_after_out, unsigned int woff)
 {
 	struct pollfd fds = {
 		.fd = peerfd,
 		.events = POLLIN | POLLOUT,
 	};
-	unsigned int woff = 0, wlen = 0, total_wlen = 0, total_rlen = 0;
+	unsigned int wlen = 0, total_wlen = 0, total_rlen = 0;
 	char wbuf[8192];
 
 	set_nonblock(peerfd, true);
@@ -717,9 +763,9 @@ static int do_recvfile(int infd, int outfd)
 	return (int)r;
 }
 
-static int do_mmap(int infd, int outfd, unsigned int size)
+static int do_mmap(int infd, int outfd, unsigned int size, unsigned int syn_off)
 {
-	char *inbuf = mmap(NULL, size, PROT_READ, MAP_SHARED, infd, 0);
+	char *inbuf = mmap(NULL, size, PROT_READ, MAP_SHARED, infd, syn_off);
 	ssize_t ret = 0, off = 0;
 	size_t rem;
 
@@ -790,7 +836,7 @@ static int do_sendfile(int infd, int outfd, unsigned int count)
 }
 
 static int copyfd_io_mmap(int infd, int peerfd, int outfd,
-			  unsigned int size, bool *in_closed_after_out)
+			  unsigned int size, bool *in_closed_after_out, unsigned int woff)
 {
 	int err;
 
@@ -799,9 +845,9 @@ static int copyfd_io_mmap(int infd, int peerfd, int outfd,
 		if (err)
 			return err;
 
-		err = do_mmap(infd, peerfd, size);
+		err = do_mmap(infd, peerfd, size, 0);
 	} else {
-		err = do_mmap(infd, peerfd, size);
+		err = do_mmap(infd, peerfd, size - woff, woff);
 		if (err)
 			return err;
 
@@ -839,7 +885,7 @@ static int copyfd_io_sendfile(int infd, int peerfd, int outfd,
 	return err;
 }
 
-static int copyfd_io(int infd, int peerfd, int outfd, bool close_peerfd)
+static int copyfd_io(int infd, int peerfd, int outfd, bool close_peerfd, unsigned int woff)
 {
 	bool in_closed_after_out = false;
 	struct timespec start, end;
@@ -851,14 +897,14 @@ static int copyfd_io(int infd, int peerfd, int outfd, bool close_peerfd)
 
 	switch (cfg_mode) {
 	case CFG_MODE_POLL:
-		ret = copyfd_io_poll(infd, peerfd, outfd, &in_closed_after_out);
+		ret = copyfd_io_poll(infd, peerfd, outfd, &in_closed_after_out, woff);
 		break;
 
 	case CFG_MODE_MMAP:
 		file_size = get_infd_size(infd);
 		if (file_size < 0)
 			return file_size;
-		ret = copyfd_io_mmap(infd, peerfd, outfd, file_size, &in_closed_after_out);
+		ret = copyfd_io_mmap(infd, peerfd, outfd, file_size, &in_closed_after_out, woff);
 		break;
 
 	case CFG_MODE_SENDFILE:
@@ -1033,7 +1079,7 @@ int main_loop_s(int listensock)
 
 		SOCK_TEST_TCPULP(remotesock, 0);
 
-		copyfd_io(fd, remotesock, 1, true);
+		copyfd_io(fd, remotesock, 1, true, 0);
 	} else {
 		perror("accept");
 		return 1;
@@ -1130,6 +1176,11 @@ static void parse_setsock_options(const char *name)
 		return;
 	}
 
+	if (strncmp(name, "MPTFO", len) == 0) {
+		cfg_sockopt_types.mptfo = 1;
+		return;
+	}
+
 	fprintf(stderr, "Unrecognized setsockopt option %s\n", name);
 	exit(1);
 }
@@ -1168,24 +1219,28 @@ int main_loop(void)
 {
 	int fd, ret, fd_in = 0;
 	struct addrinfo *peer;
+	unsigned int woff = 0;
 
-	/* listener is ready. */
-	fd = sock_connect_mptcp(cfg_host, cfg_port, cfg_sock_proto, &peer);
-	if (fd < 0)
-		return 2;
+	if (!cfg_sockopt_types.mptfo) {
+		/* listener is ready. */
+		fd = sock_connect_mptcp(cfg_host, cfg_port, cfg_sock_proto, &peer, NULL, NULL);
+		if (fd < 0)
+			return 2;
+	}
 
 again:
-	check_getpeername_connect(fd);
+	if (!cfg_sockopt_types.mptfo) {
+		check_getpeername_connect(fd);
 
-	SOCK_TEST_TCPULP(fd, cfg_sock_proto);
-
-	if (cfg_rcvbuf)
-		set_rcvbuf(fd, cfg_rcvbuf);
-	if (cfg_sndbuf)
-		set_sndbuf(fd, cfg_sndbuf);
-	if (cfg_cmsg_types.cmsg_enabled)
-		apply_cmsg_types(fd, &cfg_cmsg_types);
+		SOCK_TEST_TCPULP(fd, cfg_sock_proto);
 
+		if (cfg_rcvbuf)
+			set_rcvbuf(fd, cfg_rcvbuf);
+		if (cfg_sndbuf)
+			set_sndbuf(fd, cfg_sndbuf);
+		if (cfg_cmsg_types.cmsg_enabled)
+			apply_cmsg_types(fd, &cfg_cmsg_types);
+	}
 	if (cfg_input) {
 		fd_in = open(cfg_input, O_RDONLY);
 		if (fd < 0)
@@ -1193,7 +1248,26 @@ int main_loop(void)
 	}
 
 	/* close the client socket open only if we are not going to reconnect */
-	ret = copyfd_io(fd_in, fd, 1, 0);
+
+	if (cfg_sockopt_types.mptfo) {
+		/* sendto() instead of connect */
+		fd = sock_connect_mptcp(cfg_host, cfg_port, cfg_sock_proto, &peer, fd_in, &woff);
+		if (fd < 0)
+			return 2;
+	}
+	if (cfg_sockopt_types.mptfo) {
+		check_getpeername_connect(fd);
+
+		SOCK_TEST_TCPULP(fd, cfg_sock_proto);
+
+		if (cfg_rcvbuf)
+			set_rcvbuf(fd, cfg_rcvbuf);
+		if (cfg_sndbuf)
+			set_sndbuf(fd, cfg_sndbuf);
+		if (cfg_cmsg_types.cmsg_enabled)
+			apply_cmsg_types(fd, &cfg_cmsg_types);
+	}
+	ret = copyfd_io(fd_in, fd, 1, 0, woff);
 	if (ret)
 		return ret;
 
diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.sh b/tools/testing/selftests/net/mptcp/mptcp_connect.sh
index 621af6895f4d..d2328f94d1df 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_connect.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_connect.sh
@@ -677,6 +677,58 @@ run_tests()
 	run_tests_lo $1 $2 $3 0
 }
 
+run_test_mptfo(){
+
+	local listener_ns="$1"
+	local connector_ns="$2"
+	local connect_addr="$3"
+	local loopback="$4"
+	local extra_args="$5"
+	local msg="$6"
+	local lret=0
+
+	ip netns exec "$listener_ns" sysctl -q net.ipv4.tcp_fastopen=2
+	ip netns exec "$connector_ns" sysctl -q net.ipv4.tcp_fastopen=1
+
+	# skip if test programs are running inside same netns for subsequent runs.
+	if [ $loopback -eq 0 ] && [ ${listener_ns} = ${connector_ns} ]; then
+		return 0
+	fi
+
+	# skip if we don't want v6
+	if ! $ipv6 && is_v6 "${connect_addr}"; then
+		return 0
+	fi
+
+	local local_addr
+	if is_v6 "${connect_addr}"; then
+		local_addr="::"
+	else
+		local_addr="0.0.0.0"
+	fi
+
+
+
+	TEST_COUNT=10000
+	do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP \
+		    ${connect_addr} ${local_addr} "${extra_args}"
+	lret=$?
+
+	if [ $lret -ne 0 ]; then
+		echo "FAIL: $msg, mptcp connection error" 1>&2
+		ret=$lret
+		return 1
+	fi
+
+	echo "PASS: $msg"
+
+
+	ip netns exec "$listener_ns" sysctl -q net.ipv4.tcp_fastopen=0
+	ip netns exec "$connector_ns" sysctl -q net.ipv4.tcp_fastopen=0
+	return 0
+
+}
+
 run_test_transparent()
 {
 	local connect_addr="$1"
@@ -906,6 +958,31 @@ run_test_transparent 10.0.3.1 "tproxy ipv4"
 run_test_transparent dead:beef:3::1 "tproxy ipv6"
 stop_if_error "Tests with tproxy have failed"
 
+# MPTFO (MultiPath TCP Fatopen tests)
+
+for sender in $ns1 $ns2 $ns3 $ns4;do
+	run_test_mptfo "$ns1" $sender 10.0.1.1 0 "-o MPTFO" "mptfoIPv4"
+	run_test_mptfo "$ns1" $sender dead:beef:1::1 0 "-o MPTFO" "mptfoIPv6"
+
+	run_test_mptfo "$ns2" $sender 10.0.1.2 0 "-o MPTFO" "mptfoIPv4"
+	run_test_mptfo "$ns2" $sender dead:beef:1::2 0 "-o MPTFO" "mptfoIPv6"
+	run_test_mptfo "$ns2" $sender 10.0.2.1 0 "-o MPTFO" "mptfoIPv4"
+	run_test_mptfo "$ns2" $sender dead:beef:2::1 0 "-o MPTFO" "mptfoIPv6"
+
+	run_test_mptfo "$ns3" $sender 10.0.2.2 0 "-o MPTFO" "mptfoIPv4"
+	run_test_mptfo "$ns3" $sender dead:beef:2::2 0 "-o MPTFO" "mptfoIPv6"
+	run_test_mptfo "$ns3" $sender 10.0.3.2 0 "-o MPTFO" "mptfoIPv4"
+	run_test_mptfo "$ns3" $sender dead:beef:3::2 0 "-o MPTFO" "mptfoIPv6"
+
+	run_test_mptfo "$ns4" $sender 10.0.3.1 0 "-o MPTFO" "mptfoIPv4"
+	run_test_mptfo "$ns4" $sender dead:beef:3::1 0 "-o MPTFO" "mptfoIPv6"
+
+	stop_if_error "Tests with $sender as a sender have failed"
+done
+#run_test_mptfo 10.0.3.1 "mptfoIPv4"
+#run_test_mptfo dead:beef:3::1 "mptfoIPv6"
+#stop_if_error "Tests with MPTFO have failed"
+
 run_tests_disconnect
 
 display_time
-- 
2.34.1



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

end of thread, other threads:[~2022-11-10 18:58 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-11-06 15:24 [RFC PATCH mptcp-next v15 0/5] mptcp: Fast Open Mechanism Dmytro Shytyi
2022-11-06 15:24 ` [RFC PATCH mptcp-next v15 1/5] mptcp: introduce MSG_FASTOPEN flag Dmytro Shytyi
2022-11-06 15:24 ` [RFC PATCH mptcp-next v15 2/5] mptcp: implement delayed seq generation for passive fastopen Dmytro Shytyi
2022-11-06 15:24 ` [RFC PATCH mptcp-next v15 3/5] mptcp: add subflow_v(4,6)_send_synack() Dmytro Shytyi
2022-11-06 15:24 ` [RFC PATCH mptcp-next v15 4/5] mptcp: add TCP_FASTOPEN sock option Dmytro Shytyi
2022-11-06 15:24 ` [RFC PATCH mptcp-next v15 5/5] selftests: mptcp: mptfo Initiator/Listener Dmytro Shytyi
2022-11-06 17:10   ` selftests: mptcp: mptfo Initiator/Listener: Tests Results MPTCP CI
2022-11-06 20:50   ` [RFC PATCH mptcp-next v15 5/5] selftests: mptcp: mptfo Initiator/Listener Dmytro Shytyi
2022-11-07 15:47   ` Paolo Abeni
2022-11-10 18:58 ` [RFC PATCH mptcp-next v15 0/5] mptcp: Fast Open Mechanism Matthieu Baerts
  -- strict thread matches above, loose matches on Subject: below --
2022-10-10 22:18 [RFC PATCH mptcp-next v14 5/5] selftests: mptcp: mptfo Initiator/Listener Dmytro Shytyi
2022-10-11  0:01 ` selftests: mptcp: mptfo Initiator/Listener: Tests Results MPTCP CI

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