[PATCH bpf-next 5/5] selftests/bpf: sockmap_redir: Support no-redirect SK_DROP/SK_PASS

Michal Luczaj posted 5 patches 4 days, 10 hours ago
[PATCH bpf-next 5/5] selftests/bpf: sockmap_redir: Support no-redirect SK_DROP/SK_PASS
Posted by Michal Luczaj 4 days, 10 hours ago
Add tests that make the BPF programs skip the actual redirect and
immediately return SK_DROP/SK_PASS.

Suggested-by: Jiayuan Chen <mrpre@163.com>
Signed-off-by: Michal Luczaj <mhal@rbox.co>
---
 .../selftests/bpf/prog_tests/sockmap_redir.c       | 74 +++++++++++++++++++---
 1 file changed, 65 insertions(+), 9 deletions(-)

diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_redir.c b/tools/testing/selftests/bpf/prog_tests/sockmap_redir.c
index f89df1ca1174800d801f221a819b099abf911450..4c752000bbd8c84684b2df81eb389be953d8ba02 100644
--- a/tools/testing/selftests/bpf/prog_tests/sockmap_redir.c
+++ b/tools/testing/selftests/bpf/prog_tests/sockmap_redir.c
@@ -18,6 +18,10 @@
  * AF_UNIX, SOCK_DGRAM
  * AF_VSOCK, SOCK_STREAM
  * AF_VSOCK, SOCK_SEQPACKET
+ *	x
+ * SK_REDIRECT
+ * SK_DROP
+ * SK_PASS
  */
 
 #include <errno.h>
@@ -65,6 +69,10 @@
  */
 #define UNSUPPORTED_RACY_VERD	_BITUL(1)
 
+/* Mark for an immediate SK_DROP/SK_PASS, i.e. BPF program will not redirect.
+ */
+#define NO_REDIRECT		_BITUL(2)
+
 enum prog_type {
 	SK_MSG_EGRESS,
 	SK_MSG_INGRESS,
@@ -154,8 +162,9 @@ static void fail_recv(const char *prefix, int fd, int more_flags)
 		FAIL("%s: unexpected success: retval=%zd", prefix, n);
 }
 
-static void handle_unsupported(int sd_send, int sd_peer, int sd_in, int sd_out,
-			       int sd_recv, int map_verd, int status)
+static void handle_unsupported(int sd_send, int send_flags, int sd_peer,
+			       int sd_in, int sd_out, int sd_recv,
+			       int map_verd, int status)
 {
 	unsigned int drop, pass;
 	char recv_buf;
@@ -171,7 +180,7 @@ static void handle_unsupported(int sd_send, int sd_peer, int sd_in, int sd_out,
 		goto get_verdict;
 	}
 
-	if (pass != 0) {
+	if (pass && !(status & NO_REDIRECT)) {
 		FAIL("unsupported: wanted verdict pass 0, have %u", pass);
 		return;
 	}
@@ -237,14 +246,14 @@ static void test_send_recv(int sd_send, int send_flags, int sd_peer, int sd_in,
 		FAIL("incomplete send");
 	if (n < 0) {
 		/* sk_msg redirect combo not supported? */
-		if (status & SUPPORTED || errno != EACCES)
+		if (errno != EACCES)
 			FAIL_ERRNO("send");
 		goto out;
 	}
 
-	if (!(status & SUPPORTED)) {
-		handle_unsupported(sd_send, sd_peer, sd_in, sd_out, sd_recv,
-				   maps->verd, status);
+	if (!(status & SUPPORTED) || (status & NO_REDIRECT)) {
+		handle_unsupported(sd_send, send_flags, sd_peer, sd_in, sd_out,
+				   sd_recv, maps->verd, status);
 		goto out;
 	}
 
@@ -326,9 +335,10 @@ static int is_redir_supported(enum prog_type type, const char *in,
 static int get_support_status(enum prog_type type, const char *in,
 			      const char *out)
 {
-	int status = is_redir_supported(type, in, out);
+	int status = in ? is_redir_supported(type, in, out) : 0;
 
-	if (type == SK_SKB_INGRESS && strstarts(out, "v_"))
+	if ((type == SK_SKB_INGRESS || type == SK_SKB_EGRESS) &&
+	    strstarts(out, "v_"))
 		status |= UNSUPPORTED_RACY_VERD;
 
 	return status;
@@ -370,6 +380,41 @@ static void test_redir(enum bpf_map_type type, struct redir_spec *redir,
 		       status);
 }
 
+static void test_verdict(enum bpf_map_type type, struct redir_spec *redir,
+			 struct maps *maps, struct socket_spec *s_in,
+			 enum sk_action action)
+{
+	int fd_in, fd_out, fd_send, fd_peer, fd_recv, flags, status;
+	char s[MAX_TEST_NAME];
+	const char *s_str;
+
+	fd_in = s_in->in[0];
+	fd_out = s_in->in[1];
+	fd_send = s_in->in[redir->idx_send];
+	fd_peer = s_in->in[redir->idx_send ^ 1];
+	fd_recv = s_in->in[redir->idx_send ^ 1];
+	flags = s_in->send_flags;
+
+	s_str = socket_kind_to_str(fd_in);
+	status = get_support_status(redir->prog_type, NULL, s_str);
+	status |= NO_REDIRECT;
+
+	snprintf(s, sizeof(s),
+		 "%-4s %-17s %-7s %-5s%6s",
+		 /* hash sk_skb-to-ingress u_str pass (OOB) */
+		 type == BPF_MAP_TYPE_SOCKMAP ? "map" : "hash",
+		 redir->name,
+		 s_str,
+		 action == SK_PASS ? "pass" : "drop",
+		 flags & MSG_OOB ? "(OOB)" : "");
+
+	if (!test__start_subtest(s))
+		return;
+
+	test_send_recv(fd_send, flags, fd_peer, fd_in, fd_out, fd_recv, maps,
+		       status);
+}
+
 static void test_sockets(enum bpf_map_type type, struct redir_spec *redir,
 			 struct maps *maps, int *skel_redir_type)
 {
@@ -413,6 +458,17 @@ static void test_sockets(enum bpf_map_type type, struct redir_spec *redir,
 			test_redir(type, redir, maps, in, out);
 		}
 	}
+
+	/* No redirect: SK_DROP */
+	*skel_redir_type = __MAX_BPF_MAP_TYPE + SK_DROP;
+	for (s = sockets; s < sockets + ARRAY_SIZE(sockets); s++)
+		test_verdict(type, redir, maps, s, SK_DROP);
+
+	/* No redirect: SK_PASS */
+	*skel_redir_type = __MAX_BPF_MAP_TYPE + SK_PASS;
+	for (s = sockets; s < sockets + ARRAY_SIZE(sockets); s++)
+		test_verdict(type, redir, maps, s, SK_PASS);
+
 out:
 	while (--s >= sockets)
 		socket_spec_close(s);

-- 
2.50.1