[PATCH net-next v3 4/5] selftests: net: test IPV6_FL_F_REFLECT

Marcelo Mendes Spessoto Junior <[email protected]>
Newsgroups org.kernel.vger.linux-kselftest,org.kernel.vger.linux-kernel,org.kernel.vger.netdev
Message-ID <[email protected]>
According to the source code, flowlabel_consistency must be
deactivated for the IPV6_FL_F_REFLECT flag to work. Since
ipv6_flowlabel_mgr now runs in its own network namespace, do this
directly from the test binary. Attempt to disable
net.ipv6.flowlabel_consistency and skip the reflect test if that
fails. A disabled flowlabel_consistency does not affect the remaining
features being tested on the file, and failing to disable is not fatal
and skips the reflect test only.

The previously defined tcp_listen and tcp_connect helpers were reused,
since the connection flow required for REFLECT validation is very
similar to REMOTE.

Signed-off-by: Marcelo Mendes Spessoto Junior <[email protected]>
---
 .../selftests/net/ipv6_flowlabel_mgr.c        | 66 +++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/tools/testing/selftests/net/ipv6_flowlabel_mgr.c b/tools/testing/selftests/net/ipv6_flowlabel_mgr.c
index f8d8b09b9d86..d32150abd8ff 100644
--- a/tools/testing/selftests/net/ipv6_flowlabel_mgr.c
+++ b/tools/testing/selftests/net/ipv6_flowlabel_mgr.c
@@ -6,6 +6,7 @@
 #include <arpa/inet.h>
 #include <error.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <limits.h>
 #include <linux/in6.h>
 #include <net/if.h>
@@ -168,6 +169,23 @@ static void tcp_connect(int listener, uint32_t flowlabel,
 	*accepted = afd;
 }
 
+static bool disable_flowlabel_consistency(void)
+{
+	int fd;
+
+	fd = open("/proc/sys/net/ipv6/flowlabel_consistency", O_WRONLY);
+	if (fd == -1)
+		return false;
+
+	if (write(fd, "0", 1) != 1) {
+		close(fd);
+		return false;
+	}
+	close(fd);
+
+	return true;
+}
+
 static void run_tests(int fd)
 {
 	int wstatus;
@@ -307,6 +325,54 @@ static void run_tests(int fd)
 		close(remote_cfd);
 		close(remote_listener);
 	}
+
+	if (!disable_flowlabel_consistency()) {
+		fprintf(stderr,
+			"[INFO] skip REFLECT: cannot disable net.ipv6.flowlabel_consistency\n");
+	} else {
+		struct in6_flowlabel_req reflect_query = {
+			.flr_action = IPV6_FL_A_GET,
+		};
+		struct in6_flowlabel_req reflect_off = {
+			.flr_action = IPV6_FL_A_PUT,
+			.flr_flags = IPV6_FL_F_REFLECT,
+		};
+		struct in6_flowlabel_req reflect_on = {
+			.flr_action = IPV6_FL_A_GET,
+			.flr_flags = IPV6_FL_F_REFLECT,
+		};
+		socklen_t reflect_query_len = sizeof(reflect_query);
+		int reflect_listener = tcp_listen();
+		int reflect_cfd, reflect_afd;
+
+		explain("Enable REFLECT on listener before client connects");
+		expect_pass(setsockopt(reflect_listener, SOL_IPV6,
+				       IPV6_FLOWLABEL_MGR, &reflect_on,
+				       sizeof(reflect_on)));
+
+		tcp_connect(reflect_listener, 8, &reflect_cfd, &reflect_afd);
+
+		explain("accepted socket's label should be reflected");
+		expect_pass(getsockopt(reflect_afd, SOL_IPV6,
+				       IPV6_FLOWLABEL_MGR, &reflect_query,
+				       &reflect_query_len));
+		if (ntohl(reflect_query.flr_label) != 8)
+			error(1, 0, "unexpected reflected flowlabel %u",
+			      ntohl(reflect_query.flr_label));
+
+		explain("PUT+REFLECT disables reflection on accepted socket");
+		expect_pass(setsockopt(reflect_afd, SOL_IPV6,
+				       IPV6_FLOWLABEL_MGR, &reflect_off,
+				       sizeof(reflect_off)));
+		explain("cannot disable reflection twice");
+		expect_fail(setsockopt(reflect_afd, SOL_IPV6,
+				       IPV6_FLOWLABEL_MGR, &reflect_off,
+				       sizeof(reflect_off)));
+
+		close(reflect_afd);
+		close(reflect_cfd);
+		close(reflect_listener);
+	}
 }
 
 static void setup(void)
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.