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

Michal Luczaj
2025-09-05T11:12:17Z

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