Make the tests for multi program sk_lookup semantics use bpf_prog_run_array. This simplifies the test a bit and adds coverage to the new libbpf function. Signed-off-by: Lorenz Bauer <lmb@xxxxxxxxxxxxxx> --- .../selftests/bpf/prog_tests/sk_lookup.c | 100 ++++++++++++------ 1 file changed, 65 insertions(+), 35 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/sk_lookup.c b/tools/testing/selftests/bpf/prog_tests/sk_lookup.c index 9ff0412e1fd3..a8e4a2044170 100644 --- a/tools/testing/selftests/bpf/prog_tests/sk_lookup.c +++ b/tools/testing/selftests/bpf/prog_tests/sk_lookup.c @@ -267,6 +267,17 @@ static int recv_byte(int fd) return 0; } +static __u64 socket_cookie(int fd) +{ + __u64 cookie; + socklen_t cookie_len = sizeof(cookie); + + if (CHECK(getsockopt(fd, SOL_SOCKET, SO_COOKIE, &cookie, &cookie_len) < 0, + "getsockopt(SO_COOKIE)", "%s\n", strerror(errno))) + return 0; + return cookie; +} + static int tcp_recv_send(int server_fd) { char buf[1]; @@ -1128,17 +1139,27 @@ struct test_multi_prog { struct bpf_program *prog2; struct bpf_map *redir_map; struct bpf_map *run_map; - int expect_errno; + enum sk_action result; struct inet_addr listen_at; + bool redirect; }; static void run_multi_prog_lookup(const struct test_multi_prog *t) { - struct sockaddr_storage dst = {}; - int map_fd, server_fd, client_fd; - struct bpf_link *link1, *link2; + int map_fd, server_fd; + struct bpf_sk_lookup ctx = {}; int prog_idx, done, err; + __u32 prog_fds[2]; + DECLARE_LIBBPF_OPTS(bpf_test_run_opts, opts, + .ctx_in = &ctx, + .ctx_size_in = sizeof(ctx), + .ctx_out = &ctx, + .ctx_size_out = sizeof(ctx), + ); + + prog_fds[0] = bpf_program__fd(t->prog1); + prog_fds[1] = bpf_program__fd(t->prog2); map_fd = bpf_map__fd(t->run_map); done = 0; @@ -1151,33 +1172,37 @@ static void run_multi_prog_lookup(const struct test_multi_prog *t) if (CHECK(err, "bpf_map_update_elem", "failed\n")) return; - link1 = attach_lookup_prog(t->prog1); - if (!link1) - return; - link2 = attach_lookup_prog(t->prog2); - if (!link2) - goto out_unlink1; - server_fd = make_server(SOCK_STREAM, t->listen_at.ip, t->listen_at.port, NULL); if (server_fd < 0) - goto out_unlink2; + return; err = update_lookup_map(t->redir_map, SERVER_A, server_fd); if (err) - goto out_close_server; - - client_fd = make_socket(SOCK_STREAM, EXT_IP4, EXT_PORT, &dst); - if (client_fd < 0) - goto out_close_server; - - err = connect(client_fd, (void *)&dst, inetaddr_len(&dst)); - if (CHECK(err && !t->expect_errno, "connect", - "unexpected error %d\n", errno)) - goto out_close_client; - if (CHECK(err && t->expect_errno && errno != t->expect_errno, - "connect", "unexpected error %d\n", errno)) - goto out_close_client; + goto out; + + ctx.family = AF_INET; + ctx.protocol = IPPROTO_TCP; + + err = bpf_prog_test_run_array(prog_fds, ARRAY_SIZE(prog_fds), &opts); + if (CHECK(err, "test_run_array", "failed with error %d\n", errno)) + goto out; + + if (CHECK(opts.retval != t->result, "test_run", "unexpected result %d\n", opts.retval)) + goto out; + + if (t->redirect) { + __u64 cookie = socket_cookie(server_fd); + + if (!cookie) + goto out; + + if (CHECK(ctx.cookie != cookie, "redirect", + "selected sk:%llu instead of sk:%llu\n", ctx.cookie, cookie)) + goto out; + } else if (CHECK(ctx.cookie, "redirect", "selected unexpected sk:%llu\n", ctx.cookie)) { + goto out; + } done = 0; prog_idx = PROG1; @@ -1191,14 +1216,8 @@ static void run_multi_prog_lookup(const struct test_multi_prog *t) CHECK(err, "bpf_map_lookup_elem", "failed\n"); CHECK(!done, "bpf_map_lookup_elem", "PROG2 !done\n"); -out_close_client: - close(client_fd); -out_close_server: +out: close(server_fd); -out_unlink2: - bpf_link__destroy(link2); -out_unlink1: - bpf_link__destroy(link1); } static void test_multi_prog_lookup(struct test_sk_lookup *skel) @@ -1209,57 +1228,68 @@ static void test_multi_prog_lookup(struct test_sk_lookup *skel) .prog1 = skel->progs.multi_prog_pass1, .prog2 = skel->progs.multi_prog_pass2, .listen_at = { EXT_IP4, EXT_PORT }, + .result = SK_PASS, }, { .desc = "multi prog - drop, drop", .prog1 = skel->progs.multi_prog_drop1, .prog2 = skel->progs.multi_prog_drop2, .listen_at = { EXT_IP4, EXT_PORT }, - .expect_errno = ECONNREFUSED, + .result = SK_DROP, }, { .desc = "multi prog - pass, drop", .prog1 = skel->progs.multi_prog_pass1, .prog2 = skel->progs.multi_prog_drop2, .listen_at = { EXT_IP4, EXT_PORT }, - .expect_errno = ECONNREFUSED, + .result = SK_DROP, }, { .desc = "multi prog - drop, pass", .prog1 = skel->progs.multi_prog_drop1, .prog2 = skel->progs.multi_prog_pass2, .listen_at = { EXT_IP4, EXT_PORT }, - .expect_errno = ECONNREFUSED, + .result = SK_DROP, }, { .desc = "multi prog - pass, redir", .prog1 = skel->progs.multi_prog_pass1, .prog2 = skel->progs.multi_prog_redir2, .listen_at = { INT_IP4, INT_PORT }, + .result = SK_PASS, + .redirect = true, }, { .desc = "multi prog - redir, pass", .prog1 = skel->progs.multi_prog_redir1, .prog2 = skel->progs.multi_prog_pass2, .listen_at = { INT_IP4, INT_PORT }, + .result = SK_PASS, + .redirect = true, }, { .desc = "multi prog - drop, redir", .prog1 = skel->progs.multi_prog_drop1, .prog2 = skel->progs.multi_prog_redir2, .listen_at = { INT_IP4, INT_PORT }, + .result = SK_PASS, + .redirect = true, }, { .desc = "multi prog - redir, drop", .prog1 = skel->progs.multi_prog_redir1, .prog2 = skel->progs.multi_prog_drop2, .listen_at = { INT_IP4, INT_PORT }, + .result = SK_PASS, + .redirect = true, }, { .desc = "multi prog - redir, redir", .prog1 = skel->progs.multi_prog_redir1, .prog2 = skel->progs.multi_prog_redir2, .listen_at = { INT_IP4, INT_PORT }, + .result = SK_PASS, + .redirect = true, }, }; struct test_multi_prog *t; -- 2.27.0