From: sdf@google.com
To: Aditi Ghag <aditi.ghag@isovalent.com>
Cc: bpf@vger.kernel.org, kafai@fb.com, edumazet@google.com
Subject: Re: [PATCH 2/2] selftests/bpf: Add tests for bpf_sock_destroy
Date: Mon, 19 Dec 2022 10:25:46 -0800 [thread overview]
Message-ID: <Y6CsqsH1JQmVWgNx@google.com> (raw)
In-Reply-To: <16c81434c64f1c2a5d10e06c7199cc4715e467a0.1671242108.git.aditi.ghag@isovalent.com>
On 12/17, Aditi Ghag wrote:
> The test cases for TCP and UDP mirror the
> intended usages of the helper.
> As the helper destroys sockets asynchronously,
> the tests have sleep invocation before validating
> if the sockets were destroyed by sending data.
> Also, while all the protocol specific helpers
> set `ECONNABORTED` error code on the destroyed sockets,
> only the TCP test case has the validation check. UDP
> sockets have an overriding error code from the disconnect
> call during abort.
> Signed-off-by: Aditi Ghag <aditi.ghag@isovalent.com>
> ---
> .../selftests/bpf/prog_tests/sock_destroy.c | 131 ++++++++++++++++++
> .../selftests/bpf/progs/sock_destroy_prog.c | 96 +++++++++++++
> 2 files changed, 227 insertions(+)
> create mode 100644 tools/testing/selftests/bpf/prog_tests/sock_destroy.c
> create mode 100644 tools/testing/selftests/bpf/progs/sock_destroy_prog.c
> diff --git a/tools/testing/selftests/bpf/prog_tests/sock_destroy.c
> b/tools/testing/selftests/bpf/prog_tests/sock_destroy.c
> new file mode 100644
> index 000000000000..b920f4501809
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/prog_tests/sock_destroy.c
> @@ -0,0 +1,131 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include <test_progs.h>
> +
> +#include "sock_destroy_prog.skel.h"
> +#include "network_helpers.h"
> +
> +#define ECONNABORTED 103
> +
> +static int duration;
> +
> +static void start_iter_sockets(struct bpf_program *prog)
> +{
> + struct bpf_link *link;
> + char buf[16] = {};
> + int iter_fd, len;
> +
> + link = bpf_program__attach_iter(prog, NULL);
> + if (!ASSERT_OK_PTR(link, "attach_iter"))
> + return;
> +
> + iter_fd = bpf_iter_create(bpf_link__fd(link));
> + if (!ASSERT_GE(iter_fd, 0, "create_iter"))
> + goto free_link;
> +
> + while ((len = read(iter_fd, buf, sizeof(buf))) > 0)
> + ;
> + CHECK(len < 0, "read", "read failed: %s\n", strerror(errno));
CHECK(s) are not super appealing in the new code, can you replace them
all with ASSERT(s) ? This should also let you drop 'duration' variable.
> +
> + close(iter_fd);
> +
> +free_link:
> + bpf_link__destroy(link);
> +}
> +
> +void test_tcp(struct sock_destroy_prog *skel)
> +{
> + int serv = -1, clien = -1, n = 0;
> +
> + serv = start_server(AF_INET6, SOCK_STREAM, NULL, 0, 0);
> + if (CHECK(serv < 0, "start_server", "failed to start server\n"))
> + goto cleanup_serv;
> +
> + clien = connect_to_fd(serv, 0);
> + if (CHECK(clien < 0, "connect_to_fd", "errno %d\n", errno))
> + goto cleanup_serv;
> +
> + serv = accept(serv, NULL, NULL);
> + if (CHECK(serv < 0, "accept", "errno %d\n", errno))
> + goto cleanup;
> +
> + n = send(clien, "t", 1, 0);
> + if (CHECK(n < 0, "client_send", "client failed to send on socket\n"))
> + goto cleanup;
> +
> + start_iter_sockets(skel->progs.iter_tcp6);
> +
> + // Sockets are destroyed asynchronously.
> + usleep(1000);
> + n = send(clien, "t", 1, 0);
That's racy. Do some kind of:
while (retries--) {
usleep(100);
n = send (...)
if (n < 0)
break;
}
ASSERT_LT(n, 0);
ASSERT_EQ(errno, ECONNABORTED);
> +
> + if (CHECK(n > 0, "client_send", "succeeded on destroyed socket\n"))
> + goto cleanup;
> + CHECK(errno != ECONNABORTED, "client_send", "unexpected error code on
> destroyed socket\n");
> +
> +
> +cleanup:
> + close(clien);
> +cleanup_serv:
> + close(serv);
> +}
> +
> +
> +void test_udp(struct sock_destroy_prog *skel)
> +{
> + int serv = -1, clien = -1, n = 0;
> +
> + serv = start_server(AF_INET6, SOCK_DGRAM, NULL, 0, 0);
> + if (CHECK(serv < 0, "start_server", "failed to start server\n"))
> + goto cleanup_serv;
> +
> + clien = connect_to_fd(serv, 0);
> + if (CHECK(clien < 0, "connect_to_fd", "errno %d\n", errno))
> + goto cleanup_serv;
> +
> + n = send(clien, "t", 1, 0);
> + if (CHECK(n < 0, "client_send", "client failed to send on socket\n"))
> + goto cleanup;
> +
> + start_iter_sockets(skel->progs.iter_udp6);
> +
> + // Sockets are destroyed asynchronously.
> + usleep(1000);
Same here.
> +
> + n = send(clien, "t", 1, 0);
> + if (CHECK(n > 0, "client_send", "succeeded on destroyed socket\n"))
> + goto cleanup;
> + // UDP sockets have an overriding error code after they are
> disconnected.
> +
> +
> +cleanup:
> + close(clien);
> +cleanup_serv:
> + close(serv);
> +}
> +
> +void test_sock_destroy(void)
> +{
> + int cgroup_fd = 0;
> + struct sock_destroy_prog *skel;
> +
> + skel = sock_destroy_prog__open_and_load();
> + if (!ASSERT_OK_PTR(skel, "skel_open"))
> + return;
> +
> + cgroup_fd = test__join_cgroup("/sock_destroy");
> + if (CHECK(cgroup_fd < 0, "join_cgroup", "cgroup creation failed\n"))
> + goto close_cgroup_fd;
> +
> + skel->links.sock_connect = bpf_program__attach_cgroup(
> + skel->progs.sock_connect, cgroup_fd);
> + if (!ASSERT_OK_PTR(skel->links.sock_connect, "prog_attach"))
> + goto close_cgroup_fd;
> +
> + test_tcp(skel);
> + test_udp(skel);
> +
> +
> +close_cgroup_fd:
> + close(cgroup_fd);
> + sock_destroy_prog__destroy(skel);
> +}
> diff --git a/tools/testing/selftests/bpf/progs/sock_destroy_prog.c
> b/tools/testing/selftests/bpf/progs/sock_destroy_prog.c
> new file mode 100644
> index 000000000000..ec566033f41f
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/progs/sock_destroy_prog.c
> @@ -0,0 +1,96 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include "vmlinux.h"
> +
> +#include <bpf/bpf_helpers.h>
> +
> +#define AF_INET6 10
> +
> +struct {
> + __uint(type, BPF_MAP_TYPE_ARRAY);
> + __uint(max_entries, 1);
> + __type(key, __u32);
> + __type(value, __u64);
> +} tcp_conn_sockets SEC(".maps");
> +
> +struct {
> + __uint(type, BPF_MAP_TYPE_ARRAY);
> + __uint(max_entries, 1);
> + __type(key, __u32);
> + __type(value, __u64);
> +} udp_conn_sockets SEC(".maps");
> +
> +SEC("cgroup/connect6")
> +int sock_connect(struct bpf_sock_addr *ctx)
> +{
> + int key = 0;
> + __u64 sock_cookie = 0;
> + __u32 keyc = 0;
> +
> + if (ctx->family != AF_INET6 || ctx->user_family != AF_INET6)
> + return 1;
> +
> + sock_cookie = bpf_get_socket_cookie(ctx);
> + if (ctx->protocol == IPPROTO_TCP)
> + bpf_map_update_elem(&tcp_conn_sockets, &key, &sock_cookie, 0);
> + else if (ctx->protocol == IPPROTO_UDP)
> + bpf_map_update_elem(&udp_conn_sockets, &keyc, &sock_cookie, 0);
> + else
> + return 1;
> +
> + return 1;
> +}
> +
> +SEC("iter/tcp")
> +int iter_tcp6(struct bpf_iter__tcp *ctx)
> +{
> + struct sock_common *sk_common = ctx->sk_common;
> + struct seq_file *seq = ctx->meta->seq;
> + __u64 sock_cookie = 0;
> + __u64 *val;
> + int key = 0;
> +
> + if (!sk_common)
> + return 0;
> +
> + if (sk_common->skc_family != AF_INET6)
> + return 0;
> +
> + sock_cookie = bpf_get_socket_cookie(sk_common);
> + val = bpf_map_lookup_elem(&tcp_conn_sockets, &key);
> +
> + if (!val)
> + return 0;
> +
> + if (sock_cookie == *val)
> + bpf_sock_destroy(sk_common);
> +
> + return 0;
> +}
> +
> +SEC("iter/udp")
> +int iter_udp6(struct bpf_iter__udp *ctx)
> +{
> + struct seq_file *seq = ctx->meta->seq;
> + struct udp_sock *udp_sk = ctx->udp_sk;
> + struct sock *sk = (struct sock *) udp_sk;
> + __u64 sock_cookie = 0;
> + int key = 0;
> + __u64 *val;
> +
> + if (!sk)
> + return 0;
> +
> + sock_cookie = bpf_get_socket_cookie(sk);
> + val = bpf_map_lookup_elem(&udp_conn_sockets, &key);
> +
> + if (!val)
> + return 0;
> +
> + if (sock_cookie == *val)
> + bpf_sock_destroy(sk);
> +
> + return 0;
> +}
> +
> +char _license[] SEC("license") = "GPL";
> --
> 2.34.1
next prev parent reply other threads:[~2022-12-19 18:25 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-12-17 1:57 [PATCH 0/2] bpf-next: Add socket destroy capability Aditi Ghag
2022-12-17 1:57 ` [PATCH 1/2] bpf: " Aditi Ghag
2022-12-19 18:22 ` sdf
2023-02-23 22:02 ` Aditi Ghag
2022-12-20 10:26 ` Alan Maguire
2023-02-23 22:12 ` Aditi Ghag
2022-12-22 5:08 ` Martin KaFai Lau
2022-12-22 10:10 ` Daniel Borkmann
2023-01-02 19:30 ` Aditi Ghag
[not found] ` <CACkfWH-qS3vaRA2uSoKUwGcwZZJe=Misaa0wsLw3R4JSYGUx3A@mail.gmail.com>
2023-01-04 2:37 ` Martin KaFai Lau
2023-02-23 22:05 ` Aditi Ghag
2022-12-17 1:57 ` [PATCH 2/2] selftests/bpf: Add tests for bpf_sock_destroy Aditi Ghag
2022-12-19 18:25 ` sdf [this message]
2023-02-23 22:24 ` Aditi Ghag
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Y6CsqsH1JQmVWgNx@google.com \
--to=sdf@google.com \
--cc=aditi.ghag@isovalent.com \
--cc=bpf@vger.kernel.org \
--cc=edumazet@google.com \
--cc=kafai@fb.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.