Thread (8 messages) flat view 8 messages, 3 authors, 12h ago
HOTtoday

Revision v3 of 3 in this series.

Revisions (3)
  1. v1 [diff vs current]
  2. v2 [diff vs current]
  3. v3 current

[PATCH net-next v3 2/5] selftests: net: test IPV6_FL_F_REMOTE

From: Marcelo Mendes Spessoto Junior <hidden>
Date: 2026-08-07 22:10:03
Also in: linux-kselftest, lkml
Subsystem: kernel selftest framework, networking [general], the rest · Maintainers: Shuah Khan, Shuah Khan, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds

This flag retrieves the flow label seen by the socket at connection
setup via a getsockopt query. Therefore, the validation of this flag
requires a brief connection setup (source code for flow label shows
it must be TCP).

The simple TCP connection logic was wrapped inside two simple helpers,
because there are other uncovered features of flow label mgr that
could benefit from it (such as IPV6_FL_F_REFLECT).

Signed-off-by: Marcelo Mendes Spessoto Junior <redacted>
---
 .../selftests/net/ipv6_flowlabel_mgr.c        | 88 +++++++++++++++++++
 1 file changed, 88 insertions(+)
diff --git a/tools/testing/selftests/net/ipv6_flowlabel_mgr.c b/tools/testing/selftests/net/ipv6_flowlabel_mgr.c
index ec187890a1ed..51541e792257 100644
--- a/tools/testing/selftests/net/ipv6_flowlabel_mgr.c
+++ b/tools/testing/selftests/net/ipv6_flowlabel_mgr.c
@@ -24,6 +24,9 @@
 #ifndef IPV6_FLOWLABEL_MGR
 #define IPV6_FLOWLABEL_MGR	32
 #endif
+#ifndef IPV6_FLOWINFO_SEND
+#define IPV6_FLOWINFO_SEND	33
+#endif
 
 /* from net/ipv6/ip6_flowlabel.c */
 #define FL_MIN_LINGER		6
@@ -101,6 +104,67 @@ static int flowlabel_renew(int fd, uint32_t label, uint8_t share,
 	return setsockopt(fd, SOL_IPV6, IPV6_FLOWLABEL_MGR, &req, sizeof(req));
 }
 
+static struct sockaddr_in6 loopback_addr(void)
+{
+	struct sockaddr_in6 addr = {
+		.sin6_family	= AF_INET6,
+		.sin6_addr	= IN6ADDR_LOOPBACK_INIT,
+		.sin6_port	= htons(8888),
+	};
+
+	return addr;
+}
+
+static int tcp_listen(void)
+{
+	struct sockaddr_in6 addr = loopback_addr();
+	const int one = 1;
+	int fd;
+
+	fd = socket(PF_INET6, SOCK_STREAM, 0);
+	if (fd == -1)
+		error(1, errno, "socket listener");
+	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)))
+		error(1, errno, "setsockopt SO_REUSEADDR");
+	if (bind(fd, (void *)&addr, sizeof(addr)))
+		error(1, errno, "bind");
+	if (listen(fd, 1))
+		error(1, errno, "listen");
+
+	return fd;
+}
+
+static void tcp_connect(int listener, uint32_t flowlabel,
+			int *client, int *accepted)
+{
+	struct sockaddr_in6 addr = loopback_addr();
+	const int one = 1;
+	int cfd, afd;
+
+	cfd = socket(PF_INET6, SOCK_STREAM, 0);
+	if (cfd == -1)
+		error(1, errno, "socket client");
+
+	if (flowlabel_get(cfd, flowlabel, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE))
+		error(1, errno, "flowlabel_get");
+	if (setsockopt(cfd, SOL_IPV6, IPV6_FLOWINFO_SEND, &one, sizeof(one)))
+		error(1, errno, "setsockopt flowinfo_send");
+	addr.sin6_flowinfo = htonl(flowlabel);
+
+	if (connect(cfd, (void *)&addr, sizeof(addr)))
+		error(1, errno, "connect");
+
+	afd = accept(listener, NULL, NULL);
+	if (afd == -1)
+		error(1, errno, "accept");
+
+	if (flowlabel_put(cfd, flowlabel))
+		error(1, errno, "flowlabel_put");
+
+	*client = cfd;
+	*accepted = afd;
+}
+
 static void run_tests(int fd)
 {
 	int wstatus;
@@ -216,6 +280,30 @@ static void run_tests(int fd)
 						IPV6_FL_F_CREATE),
 				  EPERM);
 	}
+
+	{
+		struct in6_flowlabel_req freq = {
+			.flr_action = IPV6_FL_A_GET,
+			.flr_flags = IPV6_FL_F_REMOTE,
+		};
+		int remote_listener = tcp_listen();
+		socklen_t freq_len = sizeof(freq);
+		int remote_cfd, remote_afd;
+
+		explain("Prepare TCP SYN for REMOTE flag validation");
+		tcp_connect(remote_listener, 7, &remote_cfd, &remote_afd);
+
+		explain("Query for label sent by client with IPV6_FL_F_REMOTE");
+		expect_pass(getsockopt(remote_afd, SOL_IPV6, IPV6_FLOWLABEL_MGR,
+				       &freq, &freq_len));
+		if (ntohl(freq.flr_label) != 7)
+			error(1, 0, "unexpected remote flowlabel %u",
+			      ntohl(freq.flr_label));
+
+		close(remote_afd);
+		close(remote_cfd);
+		close(remote_listener);
+	}
 }
 
 static void parse_opts(int argc, char **argv)
-- 
2.55.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help