mptcp.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [PATCH mptcp-next v2 00/10] selftests: cover more MPTCP socket options
@ 2025-08-21  8:54 Geliang Tang
  2025-08-21  8:54 ` [PATCH mptcp-next v2 01/10] selftests: mptcp: sockopt: improve test output clarity Geliang Tang
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: Geliang Tang @ 2025-08-21  8:54 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

v2:
 - IP_FREEBIND/IPV6_FREEBIND are set in do_getsockopt_transparent, fix
   it.
 - Use "for" loops in mptcp_sockopt.sh.
 - Move "add IP_TOS socket option test" out of this set.
 - some cleanups.

This series significantly expands MPTCP socket option test coverage
by adding validation for 10 more socket options:

1. SO_REUSEADDR/SO_REUSEPORT - Test socket reuse capabilities
2. SO_BINDTODEVICE/SO_BINDTOIFINDEX - Validate interface binding
3. IP_TOS - Verify Type of Service handling
4. IP_FREEBIND - Test free address binding
5. IP_TRANSPARENT - Validate transparent proxying
6. IP_BIND_ADDRESS_NO_PORT - Test deferred port binding
7. IP_LOCAL_PORT_RANGE - Check local port range restriction
8. IPV6_V6ONLY - Verify IPv6-only sockets

Each commit systematically adds:
- Setsockopt/getsockopt operations in mptcp_sockopt.c
- Dedicated test cases in mptcp_sockopt.sh
- IPv4 and IPv6 coverage
- Error handling and edge case validation

The new tests verify that MPTCP correctly propagates socket options to
subflows and maintains consistent behavior across address families.

Link: https://github.com/multipath-tcp/mptcp_net-next/issues/525

Geliang Tang (10):
  selftests: mptcp: sockopt: improve test output clarity
  selftests: mptcp: sockopt: add SO_REUSEADDR test helper
  selftests: mptcp: sockopt: add SO_REUSEPORT test
  selftests: mptcp: sockopt: add SO_BINDTODEVICE test
  selftests: mptcp: sockopt: add SO_BINDTOIFINDEX test
  selftests: mptcp: sockopt: add IP_FREEBIND tests
  selftests: mptcp: sockopt: add IP_TRANSPARENT tests
  selftests: mptcp: sockopt: add IP_BIND_ADDRESS_NO_PORT test
  selftests: mptcp: sockopt: add IP_LOCAL_PORT_RANGE test
  selftests: mptcp: sockopt: add IPV6_V6ONLY test

 .../selftests/net/mptcp/mptcp_sockopt.c       | 257 +++++++++++++++++-
 .../selftests/net/mptcp/mptcp_sockopt.sh      |  37 ++-
 2 files changed, 282 insertions(+), 12 deletions(-)

-- 
2.48.1


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

* [PATCH mptcp-next v2 01/10] selftests: mptcp: sockopt: improve test output clarity
  2025-08-21  8:54 [PATCH mptcp-next v2 00/10] selftests: cover more MPTCP socket options Geliang Tang
@ 2025-08-21  8:54 ` Geliang Tang
  2025-08-21  8:54 ` [PATCH mptcp-next v2 02/10] selftests: mptcp: sockopt: add SO_REUSEADDR test helper Geliang Tang
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Geliang Tang @ 2025-08-21  8:54 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

Refine test output to print detailed titles for SOL_MPTCP socket option
tests in both IPv4 and IPv6 contexts. This enhances readability and
distinctly separates v4/v6 results. The output now explicitly labels
each test phase and result, making failures easier to identify.

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

diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
index 418a903c3a4d..003d218defa8 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
@@ -261,28 +261,37 @@ do_mptcp_sockopt_tests()
 	ip netns exec "$ns_sbox" ./mptcp_sockopt
 	lret=$?
 
-	print_title "SOL_MPTCP sockopt v4"
+	mptcp_lib_print_info "sockopt v4"
 	if [ $lret -ne 0 ]; then
-		mptcp_lib_pr_fail
+		mptcp_lib_pr_fail "sockopt v4"
 		mptcp_lib_result_fail "sockopt v4"
 		ret=$lret
 		return
 	fi
-	mptcp_lib_pr_ok
-	mptcp_lib_result_pass "sockopt v4"
+
+	for opt in "SOL_MPTCP"; do
+		print_title "$opt sockopt v4"
+		mptcp_lib_pr_ok
+		mptcp_lib_result_pass "$opt sockopt v4"
+	done
 
 	ip netns exec "$ns_sbox" ./mptcp_sockopt -6
 	lret=$?
 
-	print_title "SOL_MPTCP sockopt v6"
+	mptcp_lib_print_info "sockopt v6"
 	if [ $lret -ne 0 ]; then
-		mptcp_lib_pr_fail
+		mptcp_lib_pr_fail "sockopt v6"
 		mptcp_lib_result_fail "sockopt v6"
 		ret=$lret
 		return
 	fi
-	mptcp_lib_pr_ok
-	mptcp_lib_result_pass "sockopt v6"
+
+	for opt in "SOL_MPTCP"; do
+		print_title "$opt sockopt v6"
+		mptcp_lib_pr_ok
+		mptcp_lib_result_pass "$opt sockopt v6"
+	done
+
 }
 
 run_tests()
@@ -329,6 +338,8 @@ do_tcpinq_tests()
 		return
 	fi
 
+	mptcp_lib_print_info "sockopt TCP_INQ"
+
 	local args
 	for args in "-t tcp" "-r tcp"; do
 		do_tcpinq_test $args
-- 
2.48.1


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

* [PATCH mptcp-next v2 02/10] selftests: mptcp: sockopt: add SO_REUSEADDR test helper
  2025-08-21  8:54 [PATCH mptcp-next v2 00/10] selftests: cover more MPTCP socket options Geliang Tang
  2025-08-21  8:54 ` [PATCH mptcp-next v2 01/10] selftests: mptcp: sockopt: improve test output clarity Geliang Tang
@ 2025-08-21  8:54 ` Geliang Tang
  2025-08-21  8:54 ` [PATCH mptcp-next v2 03/10] selftests: mptcp: sockopt: add SO_REUSEPORT test Geliang Tang
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Geliang Tang @ 2025-08-21  8:54 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

Introduce helper functions to set and verify the SO_REUSEADDR socket
option. This includes:
- do_setsockopt_reuseaddr() to set the option
- do_getsockopt_reuseaddr() to validate the value
- Integration into IPv4/IPv6 test flows
- Explicit result reporting in the test script

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 .../selftests/net/mptcp/mptcp_sockopt.c       | 34 ++++++++++++++++---
 .../selftests/net/mptcp/mptcp_sockopt.sh      |  7 ++--
 2 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index e934dd26a59d..a91709aeca06 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -182,6 +182,19 @@ static void xgetaddrinfo(const char *node, const char *service,
 	}
 }
 
+static void do_setsockopt_reuseaddr(int fd)
+{
+	int one = 1;
+
+	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)))
+		perror("setsockopt(SO_REUSEADDR)");
+}
+
+static void do_setsockopts(int fd)
+{
+	do_setsockopt_reuseaddr(fd);
+}
+
 static int sock_listen_mptcp(const char * const listenaddr,
 			     const char * const port)
 {
@@ -195,7 +208,6 @@ static int sock_listen_mptcp(const char * const listenaddr,
 	hints.ai_family = pf;
 
 	struct addrinfo *a, *addr;
-	int one = 1;
 
 	xgetaddrinfo(listenaddr, port, &hints, &addr);
 	hints.ai_family = pf;
@@ -205,9 +217,7 @@ static int sock_listen_mptcp(const char * const listenaddr,
 		if (sock < 0)
 			continue;
 
-		if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one,
-				     sizeof(one)))
-			perror("setsockopt");
+		do_setsockopts(sock);
 
 		if (bind(sock, a->ai_addr, a->ai_addrlen) == 0)
 			break; /* success */
@@ -246,6 +256,8 @@ static int sock_connect_mptcp(const char * const remoteaddr,
 		if (sock < 0)
 			continue;
 
+		do_setsockopts(sock);
+
 		if (connect(sock, a->ai_addr, a->ai_addrlen) == 0)
 			break; /* success */
 
@@ -554,6 +566,18 @@ static void do_getsockopt_mptcp_full_info(struct so_state *s, int fd)
 	assert(!memcmp(&sfinfo->addrs, &s->addrs, sizeof(struct mptcp_subflow_addrs)));
 }
 
+static void do_getsockopt_reuseaddr(int fd)
+{
+	socklen_t len;
+	int reuse;
+
+	len = sizeof(reuse);
+	if (getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, &len))
+		perror("getsockopt(SO_REUSEADDR)");
+
+	assert(reuse == 1);
+}
+
 static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 {
 	do_getsockopt_mptcp_info(s, fd, w);
@@ -564,6 +588,8 @@ static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 
 	if (r)
 		do_getsockopt_mptcp_full_info(s, fd);
+
+	do_getsockopt_reuseaddr(fd);
 }
 
 static void connect_one_server(int fd, int pipefd)
diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
index 003d218defa8..da6c261275ec 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
@@ -269,7 +269,8 @@ do_mptcp_sockopt_tests()
 		return
 	fi
 
-	for opt in "SOL_MPTCP"; do
+	for opt in "SOL_MPTCP" \
+		   "SO_REUSEADDR"; do
 		print_title "$opt sockopt v4"
 		mptcp_lib_pr_ok
 		mptcp_lib_result_pass "$opt sockopt v4"
@@ -286,12 +287,12 @@ do_mptcp_sockopt_tests()
 		return
 	fi
 
-	for opt in "SOL_MPTCP"; do
+	for opt in "SOL_MPTCP" \
+		   "SO_REUSEADDR"; do
 		print_title "$opt sockopt v6"
 		mptcp_lib_pr_ok
 		mptcp_lib_result_pass "$opt sockopt v6"
 	done
-
 }
 
 run_tests()
-- 
2.48.1


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

* [PATCH mptcp-next v2 03/10] selftests: mptcp: sockopt: add SO_REUSEPORT test
  2025-08-21  8:54 [PATCH mptcp-next v2 00/10] selftests: cover more MPTCP socket options Geliang Tang
  2025-08-21  8:54 ` [PATCH mptcp-next v2 01/10] selftests: mptcp: sockopt: improve test output clarity Geliang Tang
  2025-08-21  8:54 ` [PATCH mptcp-next v2 02/10] selftests: mptcp: sockopt: add SO_REUSEADDR test helper Geliang Tang
@ 2025-08-21  8:54 ` Geliang Tang
  2025-08-21  8:54 ` [PATCH mptcp-next v2 04/10] selftests: mptcp: sockopt: add SO_BINDTODEVICE test Geliang Tang
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Geliang Tang @ 2025-08-21  8:54 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

Implement comprehensive testing for the SO_REUSEPORT socket option:
- Setsockopt and getsockopt helpers for SO_REUSEPORT
- Verification of the set value
- Integration into both client/server workflows
- IPv4 and IPv6 test coverage

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 .../selftests/net/mptcp/mptcp_sockopt.c       | 23 +++++++++++++++++++
 .../selftests/net/mptcp/mptcp_sockopt.sh      |  4 ++--
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index a91709aeca06..816d71706f7d 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -190,9 +190,18 @@ static void do_setsockopt_reuseaddr(int fd)
 		perror("setsockopt(SO_REUSEADDR)");
 }
 
+static void do_setsockopt_reuseport(int fd)
+{
+	int one = 1;
+
+	if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)))
+		perror("setsockopt(SO_REUSEPORT)");
+}
+
 static void do_setsockopts(int fd)
 {
 	do_setsockopt_reuseaddr(fd);
+	do_setsockopt_reuseport(fd);
 }
 
 static int sock_listen_mptcp(const char * const listenaddr,
@@ -578,6 +587,18 @@ static void do_getsockopt_reuseaddr(int fd)
 	assert(reuse == 1);
 }
 
+static void do_getsockopt_reuseport(int fd)
+{
+	socklen_t len;
+	int reuse;
+
+	len = sizeof(reuse);
+	if (getsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &reuse, &len))
+		perror("getsockopt(SO_REUSEPORT)");
+
+	assert(reuse == 1);
+}
+
 static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 {
 	do_getsockopt_mptcp_info(s, fd, w);
@@ -590,6 +611,8 @@ static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 		do_getsockopt_mptcp_full_info(s, fd);
 
 	do_getsockopt_reuseaddr(fd);
+
+	do_getsockopt_reuseport(fd);
 }
 
 static void connect_one_server(int fd, int pipefd)
diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
index da6c261275ec..1c357ed757d6 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
@@ -270,7 +270,7 @@ do_mptcp_sockopt_tests()
 	fi
 
 	for opt in "SOL_MPTCP" \
-		   "SO_REUSEADDR"; do
+		   "SO_REUSEADDR" "SO_REUSEPORT"; do
 		print_title "$opt sockopt v4"
 		mptcp_lib_pr_ok
 		mptcp_lib_result_pass "$opt sockopt v4"
@@ -288,7 +288,7 @@ do_mptcp_sockopt_tests()
 	fi
 
 	for opt in "SOL_MPTCP" \
-		   "SO_REUSEADDR"; do
+		   "SO_REUSEADDR" "SO_REUSEPORT"; do
 		print_title "$opt sockopt v6"
 		mptcp_lib_pr_ok
 		mptcp_lib_result_pass "$opt sockopt v6"
-- 
2.48.1


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

* [PATCH mptcp-next v2 04/10] selftests: mptcp: sockopt: add SO_BINDTODEVICE test
  2025-08-21  8:54 [PATCH mptcp-next v2 00/10] selftests: cover more MPTCP socket options Geliang Tang
                   ` (2 preceding siblings ...)
  2025-08-21  8:54 ` [PATCH mptcp-next v2 03/10] selftests: mptcp: sockopt: add SO_REUSEPORT test Geliang Tang
@ 2025-08-21  8:54 ` Geliang Tang
  2025-08-21  8:54 ` [PATCH mptcp-next v2 05/10] selftests: mptcp: sockopt: add SO_BINDTOIFINDEX test Geliang Tang
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Geliang Tang @ 2025-08-21  8:54 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

Add tests for the SO_BINDTODEVICE socket option:
- Binds sockets to the loopback device ("lo")
- Verifies the binding via getsockopt
- Includes IPv4 and IPv6 test cases
- Reports results explicitly in the test script

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 .../selftests/net/mptcp/mptcp_sockopt.c       | 25 +++++++++++++++++++
 .../selftests/net/mptcp/mptcp_sockopt.sh      |  6 +++--
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index 816d71706f7d..df4f85f129f7 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -23,6 +23,7 @@
 
 #include <netdb.h>
 #include <netinet/in.h>
+#include <net/if.h>
 
 #include <linux/tcp.h>
 
@@ -198,10 +199,20 @@ static void do_setsockopt_reuseport(int fd)
 		perror("setsockopt(SO_REUSEPORT)");
 }
 
+static void do_setsockopt_bindtodevice(int fd)
+{
+	const char *interface = "lo";
+
+	if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
+		       interface, strlen(interface)))
+		perror("setsockopt(SO_BINDTODEVICE)");
+}
+
 static void do_setsockopts(int fd)
 {
 	do_setsockopt_reuseaddr(fd);
 	do_setsockopt_reuseport(fd);
+	do_setsockopt_bindtodevice(fd);
 }
 
 static int sock_listen_mptcp(const char * const listenaddr,
@@ -599,6 +610,18 @@ static void do_getsockopt_reuseport(int fd)
 	assert(reuse == 1);
 }
 
+static void do_getsockopt_bindtodevice(int fd)
+{
+	char ifname[IFNAMSIZ] = { 0 };
+	socklen_t len;
+
+	len = sizeof(ifname);
+	if (getsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname, &len))
+		die_perror("getsockopt(SO_BINDTODEVICE)");
+
+	assert(!memcmp(ifname, "lo", len));
+}
+
 static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 {
 	do_getsockopt_mptcp_info(s, fd, w);
@@ -613,6 +636,8 @@ static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 	do_getsockopt_reuseaddr(fd);
 
 	do_getsockopt_reuseport(fd);
+
+	do_getsockopt_bindtodevice(fd);
 }
 
 static void connect_one_server(int fd, int pipefd)
diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
index 1c357ed757d6..44342ce6fd16 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
@@ -270,7 +270,8 @@ do_mptcp_sockopt_tests()
 	fi
 
 	for opt in "SOL_MPTCP" \
-		   "SO_REUSEADDR" "SO_REUSEPORT"; do
+		   "SO_REUSEADDR" "SO_REUSEPORT" \
+		   "SO_BINDTODEVICE"; do
 		print_title "$opt sockopt v4"
 		mptcp_lib_pr_ok
 		mptcp_lib_result_pass "$opt sockopt v4"
@@ -288,7 +289,8 @@ do_mptcp_sockopt_tests()
 	fi
 
 	for opt in "SOL_MPTCP" \
-		   "SO_REUSEADDR" "SO_REUSEPORT"; do
+		   "SO_REUSEADDR" "SO_REUSEPORT" \
+		   "SO_BINDTODEVICE"; do
 		print_title "$opt sockopt v6"
 		mptcp_lib_pr_ok
 		mptcp_lib_result_pass "$opt sockopt v6"
-- 
2.48.1


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

* [PATCH mptcp-next v2 05/10] selftests: mptcp: sockopt: add SO_BINDTOIFINDEX test
  2025-08-21  8:54 [PATCH mptcp-next v2 00/10] selftests: cover more MPTCP socket options Geliang Tang
                   ` (3 preceding siblings ...)
  2025-08-21  8:54 ` [PATCH mptcp-next v2 04/10] selftests: mptcp: sockopt: add SO_BINDTODEVICE test Geliang Tang
@ 2025-08-21  8:54 ` Geliang Tang
  2025-08-21  8:54 ` [PATCH mptcp-next v2 06/10] selftests: mptcp: sockopt: add IP_FREEBIND tests Geliang Tang
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Geliang Tang @ 2025-08-21  8:54 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

Implement tests for the SO_BINDTOIFINDEX socket option:
- Uses ioctl to get the loopback interface index
- Sets the option to bind to "lo"
- Validates the bound index via getsockopt
- Supports both IPv4 and IPv6

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 .../selftests/net/mptcp/mptcp_sockopt.c       | 41 +++++++++++++++++++
 .../selftests/net/mptcp/mptcp_sockopt.sh      |  4 +-
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index df4f85f129f7..25456e540cad 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>
@@ -208,11 +209,36 @@ static void do_setsockopt_bindtodevice(int fd)
 		perror("setsockopt(SO_BINDTODEVICE)");
 }
 
+static int get_ifindex(int fd, const char *ifname)
+{
+	struct ifreq ifr;
+
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+
+	if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
+		perror("ioctl");
+		return -1;
+	}
+
+	return ifr.ifr_ifindex;
+}
+
+static void do_setsockopt_bindtoifindex(int fd)
+{
+	int ifindex = get_ifindex(fd, "lo");
+
+	if (setsockopt(fd, SOL_SOCKET, SO_BINDTOIFINDEX,
+		       &ifindex, sizeof(ifindex)))
+		perror("setsockopt(SO_BINDTOIFINDEX)");
+}
+
 static void do_setsockopts(int fd)
 {
 	do_setsockopt_reuseaddr(fd);
 	do_setsockopt_reuseport(fd);
 	do_setsockopt_bindtodevice(fd);
+	do_setsockopt_bindtoifindex(fd);
 }
 
 static int sock_listen_mptcp(const char * const listenaddr,
@@ -622,6 +648,19 @@ static void do_getsockopt_bindtodevice(int fd)
 	assert(!memcmp(ifname, "lo", len));
 }
 
+static void do_getsockopt_bindtoifindex(int fd)
+{
+	socklen_t len;
+	int ifindex;
+
+	len = sizeof(ifindex);
+	if (getsockopt(fd, SOL_SOCKET, SO_BINDTOIFINDEX,
+		       &ifindex, &len))
+		die_perror("getsockopt(SO_BINDTOIFINDEX)");
+
+	assert(ifindex == get_ifindex(fd, "lo"));
+}
+
 static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 {
 	do_getsockopt_mptcp_info(s, fd, w);
@@ -638,6 +677,8 @@ static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 	do_getsockopt_reuseport(fd);
 
 	do_getsockopt_bindtodevice(fd);
+
+	do_getsockopt_bindtoifindex(fd);
 }
 
 static void connect_one_server(int fd, int pipefd)
diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
index 44342ce6fd16..7f2effd82af8 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
@@ -271,7 +271,7 @@ do_mptcp_sockopt_tests()
 
 	for opt in "SOL_MPTCP" \
 		   "SO_REUSEADDR" "SO_REUSEPORT" \
-		   "SO_BINDTODEVICE"; do
+		   "SO_BINDTODEVICE" "SO_BINDTOIFINDEX"; do
 		print_title "$opt sockopt v4"
 		mptcp_lib_pr_ok
 		mptcp_lib_result_pass "$opt sockopt v4"
@@ -290,7 +290,7 @@ do_mptcp_sockopt_tests()
 
 	for opt in "SOL_MPTCP" \
 		   "SO_REUSEADDR" "SO_REUSEPORT" \
-		   "SO_BINDTODEVICE"; do
+		   "SO_BINDTODEVICE" "SO_BINDTOIFINDEX"; do
 		print_title "$opt sockopt v6"
 		mptcp_lib_pr_ok
 		mptcp_lib_result_pass "$opt sockopt v6"
-- 
2.48.1


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

* [PATCH mptcp-next v2 06/10] selftests: mptcp: sockopt: add IP_FREEBIND tests
  2025-08-21  8:54 [PATCH mptcp-next v2 00/10] selftests: cover more MPTCP socket options Geliang Tang
                   ` (4 preceding siblings ...)
  2025-08-21  8:54 ` [PATCH mptcp-next v2 05/10] selftests: mptcp: sockopt: add SO_BINDTOIFINDEX test Geliang Tang
@ 2025-08-21  8:54 ` Geliang Tang
  2025-08-21  8:54 ` [PATCH mptcp-next v2 07/10] selftests: mptcp: sockopt: add IP_TRANSPARENT tests Geliang Tang
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Geliang Tang @ 2025-08-21  8:54 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

Add tests for IP_FREEBIND (IPv4) and IPV6_FREEBIND (IPv6):
- Setsockopt helpers to enable FREEBIND
- Getsockopt validation of the enabled state
- Test integration for both address families
- Script result reporting

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

diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index 25456e540cad..e9ef908dc270 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -233,12 +233,23 @@ static void do_setsockopt_bindtoifindex(int fd)
 		perror("setsockopt(SO_BINDTOIFINDEX)");
 }
 
+static void do_setsockopt_freebind(int fd)
+{
+	int optname = (pf == AF_INET ? IP_FREEBIND : IPV6_FREEBIND);
+	int level = (pf == AF_INET ? SOL_IP : SOL_IPV6);
+	int enable = 1;
+
+	if (setsockopt(fd, level, optname, &enable, sizeof(enable)))
+		perror("setsockopt(IP(V6)_FREEBIND)");
+}
+
 static void do_setsockopts(int fd)
 {
 	do_setsockopt_reuseaddr(fd);
 	do_setsockopt_reuseport(fd);
 	do_setsockopt_bindtodevice(fd);
 	do_setsockopt_bindtoifindex(fd);
+	do_setsockopt_freebind(fd);
 }
 
 static int sock_listen_mptcp(const char * const listenaddr,
@@ -661,6 +672,20 @@ static void do_getsockopt_bindtoifindex(int fd)
 	assert(ifindex == get_ifindex(fd, "lo"));
 }
 
+static void do_getsockopt_freebind(int fd)
+{
+	int optname = (pf == AF_INET ? IP_FREEBIND : IPV6_FREEBIND);
+	int level = (pf == AF_INET ? SOL_IP : SOL_IPV6);
+	socklen_t len;
+	int enable;
+
+	len = sizeof(enable);
+	if (getsockopt(fd, level, optname, &enable, &len))
+		die_perror("getsockopt(IP(V6)_FREEBIND)");
+
+	assert(enable == 1);
+}
+
 static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 {
 	do_getsockopt_mptcp_info(s, fd, w);
@@ -679,6 +704,8 @@ static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 	do_getsockopt_bindtodevice(fd);
 
 	do_getsockopt_bindtoifindex(fd);
+
+	do_getsockopt_freebind(fd);
 }
 
 static void connect_one_server(int fd, int pipefd)
diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
index 7f2effd82af8..193f4d4dc41a 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
@@ -271,7 +271,8 @@ do_mptcp_sockopt_tests()
 
 	for opt in "SOL_MPTCP" \
 		   "SO_REUSEADDR" "SO_REUSEPORT" \
-		   "SO_BINDTODEVICE" "SO_BINDTOIFINDEX"; do
+		   "SO_BINDTODEVICE" "SO_BINDTOIFINDEX" \
+		   "IP_FREEBIND"; do
 		print_title "$opt sockopt v4"
 		mptcp_lib_pr_ok
 		mptcp_lib_result_pass "$opt sockopt v4"
@@ -290,7 +291,8 @@ do_mptcp_sockopt_tests()
 
 	for opt in "SOL_MPTCP" \
 		   "SO_REUSEADDR" "SO_REUSEPORT" \
-		   "SO_BINDTODEVICE" "SO_BINDTOIFINDEX"; do
+		   "SO_BINDTODEVICE" "SO_BINDTOIFINDEX" \
+		   "IPV6_FREEBIND"; do
 		print_title "$opt sockopt v6"
 		mptcp_lib_pr_ok
 		mptcp_lib_result_pass "$opt sockopt v6"
-- 
2.48.1


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

* [PATCH mptcp-next v2 07/10] selftests: mptcp: sockopt: add IP_TRANSPARENT tests
  2025-08-21  8:54 [PATCH mptcp-next v2 00/10] selftests: cover more MPTCP socket options Geliang Tang
                   ` (5 preceding siblings ...)
  2025-08-21  8:54 ` [PATCH mptcp-next v2 06/10] selftests: mptcp: sockopt: add IP_FREEBIND tests Geliang Tang
@ 2025-08-21  8:54 ` Geliang Tang
  2025-08-21  8:54 ` [PATCH mptcp-next v2 08/10] selftests: mptcp: sockopt: add IP_BIND_ADDRESS_NO_PORT test Geliang Tang
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Geliang Tang @ 2025-08-21  8:54 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

Implement tests for transparent socket options:
- IP_TRANSPARENT (IPv4) and IPV6_TRANSPARENT (IPv6)
- Setsockopt and getsockopt helpers
- State verification after setting
- IPv4/IPv6 coverage in test script

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 .../selftests/net/mptcp/mptcp_sockopt.c       | 27 +++++++++++++++++++
 .../selftests/net/mptcp/mptcp_sockopt.sh      |  4 +--
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index e9ef908dc270..ccc072005118 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -243,6 +243,16 @@ static void do_setsockopt_freebind(int fd)
 		perror("setsockopt(IP(V6)_FREEBIND)");
 }
 
+static void do_setsockopt_transparent(int fd)
+{
+	int optname = (pf == AF_INET ? IP_TRANSPARENT : IPV6_TRANSPARENT);
+	int level = (pf == AF_INET ? SOL_IP : SOL_IPV6);
+	int enable = 1;
+
+	if (setsockopt(fd, level, optname, &enable, sizeof(enable)))
+		perror("setsockopt(IP(V6)_TRANSPARENT)");
+}
+
 static void do_setsockopts(int fd)
 {
 	do_setsockopt_reuseaddr(fd);
@@ -250,6 +260,7 @@ static void do_setsockopts(int fd)
 	do_setsockopt_bindtodevice(fd);
 	do_setsockopt_bindtoifindex(fd);
 	do_setsockopt_freebind(fd);
+	do_setsockopt_transparent(fd);
 }
 
 static int sock_listen_mptcp(const char * const listenaddr,
@@ -686,6 +697,20 @@ static void do_getsockopt_freebind(int fd)
 	assert(enable == 1);
 }
 
+static void do_getsockopt_transparent(int fd)
+{
+	int optname = (pf == AF_INET ? IP_TRANSPARENT : IPV6_TRANSPARENT);
+	int level = (pf == AF_INET ? SOL_IP : SOL_IPV6);
+	socklen_t len;
+	int enable;
+
+	len = sizeof(enable);
+	if (getsockopt(fd, level, optname, &enable, &len))
+		die_perror("getsockopt(IP(V6)_TRANSPARENT)");
+
+	assert(enable == 1);
+}
+
 static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 {
 	do_getsockopt_mptcp_info(s, fd, w);
@@ -706,6 +731,8 @@ static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 	do_getsockopt_bindtoifindex(fd);
 
 	do_getsockopt_freebind(fd);
+
+	do_getsockopt_transparent(fd);
 }
 
 static void connect_one_server(int fd, int pipefd)
diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
index 193f4d4dc41a..da02769fbb2b 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
@@ -272,7 +272,7 @@ do_mptcp_sockopt_tests()
 	for opt in "SOL_MPTCP" \
 		   "SO_REUSEADDR" "SO_REUSEPORT" \
 		   "SO_BINDTODEVICE" "SO_BINDTOIFINDEX" \
-		   "IP_FREEBIND"; do
+		   "IP_FREEBIND" "IP_TRANSPARENT"; do
 		print_title "$opt sockopt v4"
 		mptcp_lib_pr_ok
 		mptcp_lib_result_pass "$opt sockopt v4"
@@ -292,7 +292,7 @@ do_mptcp_sockopt_tests()
 	for opt in "SOL_MPTCP" \
 		   "SO_REUSEADDR" "SO_REUSEPORT" \
 		   "SO_BINDTODEVICE" "SO_BINDTOIFINDEX" \
-		   "IPV6_FREEBIND"; do
+		   "IPV6_FREEBIND" "IPV6_TRANSPARENT"; do
 		print_title "$opt sockopt v6"
 		mptcp_lib_pr_ok
 		mptcp_lib_result_pass "$opt sockopt v6"
-- 
2.48.1


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

* [PATCH mptcp-next v2 08/10] selftests: mptcp: sockopt: add IP_BIND_ADDRESS_NO_PORT test
  2025-08-21  8:54 [PATCH mptcp-next v2 00/10] selftests: cover more MPTCP socket options Geliang Tang
                   ` (6 preceding siblings ...)
  2025-08-21  8:54 ` [PATCH mptcp-next v2 07/10] selftests: mptcp: sockopt: add IP_TRANSPARENT tests Geliang Tang
@ 2025-08-21  8:54 ` Geliang Tang
  2025-08-21  8:54 ` [PATCH mptcp-next v2 09/10] selftests: mptcp: sockopt: add IP_LOCAL_PORT_RANGE test Geliang Tang
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Geliang Tang @ 2025-08-21  8:54 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

Add tests for the IP_BIND_ADDRESS_NO_PORT socket option:
- Enables the option via setsockopt
- Verifies the enabled state via getsockopt
- Includes tests for both IPv4 and IPv6
- Updates test script output

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 .../selftests/net/mptcp/mptcp_sockopt.c       | 25 +++++++++++++++++++
 .../selftests/net/mptcp/mptcp_sockopt.sh      |  6 +++--
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index ccc072005118..ca1a40492aa4 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -253,6 +253,15 @@ static void do_setsockopt_transparent(int fd)
 		perror("setsockopt(IP(V6)_TRANSPARENT)");
 }
 
+static void do_setsockopt_bind_address_no_port(int fd)
+{
+	int enable = 1;
+
+	if (setsockopt(fd, SOL_IP, IP_BIND_ADDRESS_NO_PORT, &enable,
+		       sizeof(enable)))
+		perror("setsockopt(IP_BIND_ADDRESS_NO_PORT)");
+}
+
 static void do_setsockopts(int fd)
 {
 	do_setsockopt_reuseaddr(fd);
@@ -261,6 +270,7 @@ static void do_setsockopts(int fd)
 	do_setsockopt_bindtoifindex(fd);
 	do_setsockopt_freebind(fd);
 	do_setsockopt_transparent(fd);
+	do_setsockopt_bind_address_no_port(fd);
 }
 
 static int sock_listen_mptcp(const char * const listenaddr,
@@ -711,6 +721,19 @@ static void do_getsockopt_transparent(int fd)
 	assert(enable == 1);
 }
 
+static void do_getsockopt_bind_address_no_port(int fd)
+{
+	socklen_t len;
+	int enable;
+
+	len = sizeof(enable);
+	if (getsockopt(fd, SOL_IP, IP_BIND_ADDRESS_NO_PORT,
+		       &enable, &len))
+		die_perror("getsockopt(IP_TRANSPARENT)");
+
+	assert(enable == 1);
+}
+
 static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 {
 	do_getsockopt_mptcp_info(s, fd, w);
@@ -733,6 +756,8 @@ static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 	do_getsockopt_freebind(fd);
 
 	do_getsockopt_transparent(fd);
+
+	do_getsockopt_bind_address_no_port(fd);
 }
 
 static void connect_one_server(int fd, int pipefd)
diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
index da02769fbb2b..3756b537e2a6 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
@@ -272,7 +272,8 @@ do_mptcp_sockopt_tests()
 	for opt in "SOL_MPTCP" \
 		   "SO_REUSEADDR" "SO_REUSEPORT" \
 		   "SO_BINDTODEVICE" "SO_BINDTOIFINDEX" \
-		   "IP_FREEBIND" "IP_TRANSPARENT"; do
+		   "IP_FREEBIND" "IP_TRANSPARENT" \
+		   "IP_BIND_ADDRESS_NO_PORT"; do
 		print_title "$opt sockopt v4"
 		mptcp_lib_pr_ok
 		mptcp_lib_result_pass "$opt sockopt v4"
@@ -292,7 +293,8 @@ do_mptcp_sockopt_tests()
 	for opt in "SOL_MPTCP" \
 		   "SO_REUSEADDR" "SO_REUSEPORT" \
 		   "SO_BINDTODEVICE" "SO_BINDTOIFINDEX" \
-		   "IPV6_FREEBIND" "IPV6_TRANSPARENT"; do
+		   "IPV6_FREEBIND" "IPV6_TRANSPARENT" \
+		   "IP_BIND_ADDRESS_NO_PORT"; do
 		print_title "$opt sockopt v6"
 		mptcp_lib_pr_ok
 		mptcp_lib_result_pass "$opt sockopt v6"
-- 
2.48.1


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

* [PATCH mptcp-next v2 09/10] selftests: mptcp: sockopt: add IP_LOCAL_PORT_RANGE test
  2025-08-21  8:54 [PATCH mptcp-next v2 00/10] selftests: cover more MPTCP socket options Geliang Tang
                   ` (7 preceding siblings ...)
  2025-08-21  8:54 ` [PATCH mptcp-next v2 08/10] selftests: mptcp: sockopt: add IP_BIND_ADDRESS_NO_PORT test Geliang Tang
@ 2025-08-21  8:54 ` Geliang Tang
  2025-08-21  8:54 ` [PATCH mptcp-next v2 10/10] selftests: mptcp: sockopt: add IPV6_V6ONLY test Geliang Tang
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Geliang Tang @ 2025-08-21  8:54 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

Add tests for IP_LOCAL_PORT_RANGE:
- Sets port range to 30000-31000
- Verifies the range via getsockopt
- Covers both IPv4 and IPv6
- Reports results in test script

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 .../selftests/net/mptcp/mptcp_sockopt.c       | 25 +++++++++++++++++++
 .../selftests/net/mptcp/mptcp_sockopt.sh      |  6 +++--
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index ca1a40492aa4..25074e5b4eaa 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -262,6 +262,15 @@ static void do_setsockopt_bind_address_no_port(int fd)
 		perror("setsockopt(IP_BIND_ADDRESS_NO_PORT)");
 }
 
+static void do_setsockopt_local_port_range(int fd)
+{
+	uint32_t port_range = (31000 << 16 | 30000); // [30000 - 31000]
+
+	if (setsockopt(fd, SOL_IP, IP_LOCAL_PORT_RANGE, &port_range,
+		       sizeof(port_range)))
+		perror("setsockopt(IP_LOCAL_PORT_RANGE)");
+}
+
 static void do_setsockopts(int fd)
 {
 	do_setsockopt_reuseaddr(fd);
@@ -271,6 +280,7 @@ static void do_setsockopts(int fd)
 	do_setsockopt_freebind(fd);
 	do_setsockopt_transparent(fd);
 	do_setsockopt_bind_address_no_port(fd);
+	do_setsockopt_local_port_range(fd);
 }
 
 static int sock_listen_mptcp(const char * const listenaddr,
@@ -734,6 +744,19 @@ static void do_getsockopt_bind_address_no_port(int fd)
 	assert(enable == 1);
 }
 
+static void do_getsockopt_local_port_range(int fd)
+{
+	uint32_t port_range;
+	socklen_t len;
+
+	len = sizeof(port_range);
+	if (getsockopt(fd, SOL_IP, IP_LOCAL_PORT_RANGE,
+		       &port_range, &len))
+		die_perror("getsockopt(IP_LOCAL_PORT_RANGE)");
+
+	assert(port_range == (31000 << 16 | 30000));
+}
+
 static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 {
 	do_getsockopt_mptcp_info(s, fd, w);
@@ -758,6 +781,8 @@ static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 	do_getsockopt_transparent(fd);
 
 	do_getsockopt_bind_address_no_port(fd);
+
+	do_getsockopt_local_port_range(fd);
 }
 
 static void connect_one_server(int fd, int pipefd)
diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
index 3756b537e2a6..2016adde1553 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
@@ -273,7 +273,8 @@ do_mptcp_sockopt_tests()
 		   "SO_REUSEADDR" "SO_REUSEPORT" \
 		   "SO_BINDTODEVICE" "SO_BINDTOIFINDEX" \
 		   "IP_FREEBIND" "IP_TRANSPARENT" \
-		   "IP_BIND_ADDRESS_NO_PORT"; do
+		   "IP_BIND_ADDRESS_NO_PORT" \
+		   "IP_LOCAL_PORT_RANGE"; do
 		print_title "$opt sockopt v4"
 		mptcp_lib_pr_ok
 		mptcp_lib_result_pass "$opt sockopt v4"
@@ -294,7 +295,8 @@ do_mptcp_sockopt_tests()
 		   "SO_REUSEADDR" "SO_REUSEPORT" \
 		   "SO_BINDTODEVICE" "SO_BINDTOIFINDEX" \
 		   "IPV6_FREEBIND" "IPV6_TRANSPARENT" \
-		   "IP_BIND_ADDRESS_NO_PORT"; do
+		   "IP_BIND_ADDRESS_NO_PORT" \
+		   "IP_LOCAL_PORT_RANGE"; do
 		print_title "$opt sockopt v6"
 		mptcp_lib_pr_ok
 		mptcp_lib_result_pass "$opt sockopt v6"
-- 
2.48.1


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

* [PATCH mptcp-next v2 10/10] selftests: mptcp: sockopt: add IPV6_V6ONLY test
  2025-08-21  8:54 [PATCH mptcp-next v2 00/10] selftests: cover more MPTCP socket options Geliang Tang
                   ` (8 preceding siblings ...)
  2025-08-21  8:54 ` [PATCH mptcp-next v2 09/10] selftests: mptcp: sockopt: add IP_LOCAL_PORT_RANGE test Geliang Tang
@ 2025-08-21  8:54 ` Geliang Tang
  2025-08-21  9:57 ` [PATCH mptcp-next v2 00/10] selftests: cover more MPTCP socket options Matthieu Baerts
  2025-08-21 11:21 ` MPTCP CI
  11 siblings, 0 replies; 13+ messages in thread
From: Geliang Tang @ 2025-08-21  8:54 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

From: Geliang Tang <tanggeliang@kylinos.cn>

Add IPv6-specific testing for IPV6_V6ONLY:
- Enables the option and verifies its state
- Restricted to IPv6 sockets
- Reports results in the test script

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 .../selftests/net/mptcp/mptcp_sockopt.c       | 30 +++++++++++++++++++
 .../selftests/net/mptcp/mptcp_sockopt.sh      |  3 +-
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index 25074e5b4eaa..9bbe2e56351f 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -271,6 +271,18 @@ static void do_setsockopt_local_port_range(int fd)
 		perror("setsockopt(IP_LOCAL_PORT_RANGE)");
 }
 
+static void do_setsockopt_v6only(int fd)
+{
+	int v6only = 1;
+
+	if (pf != AF_INET6)
+		return;
+
+	if (setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, &v6only,
+		       sizeof(v6only)))
+		perror("setsockopt(IPV6_V6ONLY)");
+}
+
 static void do_setsockopts(int fd)
 {
 	do_setsockopt_reuseaddr(fd);
@@ -281,6 +293,7 @@ static void do_setsockopts(int fd)
 	do_setsockopt_transparent(fd);
 	do_setsockopt_bind_address_no_port(fd);
 	do_setsockopt_local_port_range(fd);
+	do_setsockopt_v6only(fd);
 }
 
 static int sock_listen_mptcp(const char * const listenaddr,
@@ -757,6 +770,21 @@ static void do_getsockopt_local_port_range(int fd)
 	assert(port_range == (31000 << 16 | 30000));
 }
 
+static void do_getsockopt_v6only(int fd)
+{
+	socklen_t len;
+	int v6only;
+
+	if (pf != AF_INET6)
+		return;
+
+	len = sizeof(v6only);
+	if (getsockopt(fd, SOL_IPV6, IPV6_V6ONLY, &v6only, &len))
+		die_perror("getsockopt(IPV6_V6ONLY)");
+
+	assert(v6only == 1);
+}
+
 static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 {
 	do_getsockopt_mptcp_info(s, fd, w);
@@ -783,6 +811,8 @@ static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
 	do_getsockopt_bind_address_no_port(fd);
 
 	do_getsockopt_local_port_range(fd);
+
+	do_getsockopt_v6only(fd);
 }
 
 static void connect_one_server(int fd, int pipefd)
diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
index 2016adde1553..356911077451 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
@@ -296,7 +296,8 @@ do_mptcp_sockopt_tests()
 		   "SO_BINDTODEVICE" "SO_BINDTOIFINDEX" \
 		   "IPV6_FREEBIND" "IPV6_TRANSPARENT" \
 		   "IP_BIND_ADDRESS_NO_PORT" \
-		   "IP_LOCAL_PORT_RANGE"; do
+		   "IP_LOCAL_PORT_RANGE" \
+		   "IPV6_V6ONLY"; do
 		print_title "$opt sockopt v6"
 		mptcp_lib_pr_ok
 		mptcp_lib_result_pass "$opt sockopt v6"
-- 
2.48.1


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

* Re: [PATCH mptcp-next v2 00/10] selftests: cover more MPTCP socket options
  2025-08-21  8:54 [PATCH mptcp-next v2 00/10] selftests: cover more MPTCP socket options Geliang Tang
                   ` (9 preceding siblings ...)
  2025-08-21  8:54 ` [PATCH mptcp-next v2 10/10] selftests: mptcp: sockopt: add IPV6_V6ONLY test Geliang Tang
@ 2025-08-21  9:57 ` Matthieu Baerts
  2025-08-21 11:21 ` MPTCP CI
  11 siblings, 0 replies; 13+ messages in thread
From: Matthieu Baerts @ 2025-08-21  9:57 UTC (permalink / raw)
  To: Geliang Tang, mptcp; +Cc: Geliang Tang

Hi Geliang,

Thank you for looking at that!

On 21/08/2025 10:54, Geliang Tang wrote:
> From: Geliang Tang <tanggeliang@kylinos.cn>
> 
> v2:
>  - IP_FREEBIND/IPV6_FREEBIND are set in do_getsockopt_transparent, fix
>    it.
>  - Use "for" loops in mptcp_sockopt.sh.
>  - Move "add IP_TOS socket option test" out of this set.
>  - some cleanups.
> 
> This series significantly expands MPTCP socket option test coverage
> by adding validation for 10 more socket options:
> 
> 1. SO_REUSEADDR/SO_REUSEPORT - Test socket reuse capabilities
> 2. SO_BINDTODEVICE/SO_BINDTOIFINDEX - Validate interface binding
> 3. IP_TOS - Verify Type of Service handling
> 4. IP_FREEBIND - Test free address binding
> 5. IP_TRANSPARENT - Validate transparent proxying
> 6. IP_BIND_ADDRESS_NO_PORT - Test deferred port binding
> 7. IP_LOCAL_PORT_RANGE - Check local port range restriction
> 8. IPV6_V6ONLY - Verify IPv6-only sockets
> 
> Each commit systematically adds:
> - Setsockopt/getsockopt operations in mptcp_sockopt.c
> - Dedicated test cases in mptcp_sockopt.sh
> - IPv4 and IPv6 coverage
> - Error handling and edge case validation
> 
> The new tests verify that MPTCP correctly propagates socket options to
> subflows and maintains consistent behavior across address families.

I don't know if the last sentence is correct: if I'm not mistaken, it
looks like the new code "only" set and get some socket options, no?

If yes, that's not enough to me to verify a socket option is doing the
expected job. I think it might even be better not to include such code
giving a false sentiment of "it's fully tested" (+ more code to
maintain). All these options are supposed to affect the behaviour
somehow: a test should then mainly validate that, and check this
behaviour is similar to TCP.

In other words, such tests should be similar to what you did with
TCP_MAXSEG in Packetdrill:

  https://github.com/multipath-tcp/packetdrill/pull/161

I think that when validating a new socket options, the following should
be checked:

 - Comparison with TCP: the behaviour should be as closed as possible
 - set/get before and after the connection
 - behaviour on the client and server side
 - important: checking the new expected behaviour

Checking all this should probably be easier with Packetdrill, especially
to validate a behavioural change. But it might not be always possible,
or best suited, like with IP_BIND_ADDRESS_NO_PORT and
IP_LOCAL_PORT_RANGE which are "properly" tested in:

  tools/testing/selftests/net/mptcp/ip_local_port_range.c

What do you think?

Cheers,
Matt
-- 
Sponsored by the NGI0 Core fund.


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

* Re: [PATCH mptcp-next v2 00/10] selftests: cover more MPTCP socket options
  2025-08-21  8:54 [PATCH mptcp-next v2 00/10] selftests: cover more MPTCP socket options Geliang Tang
                   ` (10 preceding siblings ...)
  2025-08-21  9:57 ` [PATCH mptcp-next v2 00/10] selftests: cover more MPTCP socket options Matthieu Baerts
@ 2025-08-21 11:21 ` MPTCP CI
  11 siblings, 0 replies; 13+ messages in thread
From: MPTCP CI @ 2025-08-21 11:21 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: Success! ✅
- KVM Validation: debug: Unstable: 3 failed test(s): packetdrill_syscalls selftest_mptcp_connect_checksum selftest_mptcp_join 🔴
- 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/17122626757

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


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] 13+ messages in thread

end of thread, other threads:[~2025-08-21 11:22 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-21  8:54 [PATCH mptcp-next v2 00/10] selftests: cover more MPTCP socket options Geliang Tang
2025-08-21  8:54 ` [PATCH mptcp-next v2 01/10] selftests: mptcp: sockopt: improve test output clarity Geliang Tang
2025-08-21  8:54 ` [PATCH mptcp-next v2 02/10] selftests: mptcp: sockopt: add SO_REUSEADDR test helper Geliang Tang
2025-08-21  8:54 ` [PATCH mptcp-next v2 03/10] selftests: mptcp: sockopt: add SO_REUSEPORT test Geliang Tang
2025-08-21  8:54 ` [PATCH mptcp-next v2 04/10] selftests: mptcp: sockopt: add SO_BINDTODEVICE test Geliang Tang
2025-08-21  8:54 ` [PATCH mptcp-next v2 05/10] selftests: mptcp: sockopt: add SO_BINDTOIFINDEX test Geliang Tang
2025-08-21  8:54 ` [PATCH mptcp-next v2 06/10] selftests: mptcp: sockopt: add IP_FREEBIND tests Geliang Tang
2025-08-21  8:54 ` [PATCH mptcp-next v2 07/10] selftests: mptcp: sockopt: add IP_TRANSPARENT tests Geliang Tang
2025-08-21  8:54 ` [PATCH mptcp-next v2 08/10] selftests: mptcp: sockopt: add IP_BIND_ADDRESS_NO_PORT test Geliang Tang
2025-08-21  8:54 ` [PATCH mptcp-next v2 09/10] selftests: mptcp: sockopt: add IP_LOCAL_PORT_RANGE test Geliang Tang
2025-08-21  8:54 ` [PATCH mptcp-next v2 10/10] selftests: mptcp: sockopt: add IPV6_V6ONLY test Geliang Tang
2025-08-21  9:57 ` [PATCH mptcp-next v2 00/10] selftests: cover more MPTCP socket options Matthieu Baerts
2025-08-21 11:21 ` MPTCP CI

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).