On Sat, Oct 18, 2025 at 10:21:24PM +0800, Menglong Dong wrote:

SNIP

> +static void test_fsession_reattach(void)
> +{
> +     struct fsession_test *skel = NULL;
> +     int err, prog_fd;
> +     LIBBPF_OPTS(bpf_test_run_opts, topts);
> +
> +     skel = fsession_test__open_and_load();
> +     if (!ASSERT_OK_PTR(skel, "fsession_test__open_and_load"))
> +             goto cleanup;
> +
> +     /* First attach */
> +     err = fsession_test__attach(skel);
> +     if (!ASSERT_OK(err, "fsession_first_attach"))
> +             goto cleanup;
> +
> +     /* Trigger test function calls */
> +     prog_fd = bpf_program__fd(skel->progs.test1);
> +     err = bpf_prog_test_run_opts(prog_fd, &topts);
> +     if (!ASSERT_OK(err, "test_run_opts err"))
> +             return;

goto cleanup

> +     if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
> +             return;

goto cleanup

> +
> +     /* Verify first call */
> +     ASSERT_EQ(skel->bss->test1_entry_called, 1, "test1_entry_first");
> +     ASSERT_EQ(skel->bss->test1_exit_called, 1, "test1_exit_first");
> +
> +     /* Detach */
> +     fsession_test__detach(skel);
> +
> +     /* Reset counters */
> +     memset(skel->bss, 0, sizeof(*skel->bss));
> +
> +     /* Second attach */
> +     err = fsession_test__attach(skel);
> +     if (!ASSERT_OK(err, "fsession_second_attach"))
> +             goto cleanup;
> +
> +     err = bpf_prog_test_run_opts(prog_fd, &topts);
> +     if (!ASSERT_OK(err, "test_run_opts err"))
> +             return;

goto cleanup

> +     if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
> +             return;

goto cleanup

> +
> +     /* Verify second call */
> +     ASSERT_EQ(skel->bss->test1_entry_called, 1, "test1_entry_second");
> +     ASSERT_EQ(skel->bss->test1_exit_called, 1, "test1_exit_second");
> +
> +cleanup:
> +     fsession_test__destroy(skel);
> +}
> +
> +void test_fsession_test(void)
> +{
> +#if !defined(__x86_64__)
> +     test__skip();
> +     return;
> +#endif
> +     if (test__start_subtest("fsession_basic"))
> +             test_fsession_basic();
> +     if (test__start_subtest("fsession_reattach"))
> +             test_fsession_reattach();
> +}
> diff --git a/tools/testing/selftests/bpf/progs/fsession_test.c 
> b/tools/testing/selftests/bpf/progs/fsession_test.c
> new file mode 100644
> index 000000000000..cce2b32f7c2c
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/progs/fsession_test.c
> @@ -0,0 +1,178 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2025 ChinaTelecom */
> +#include <vmlinux.h>
> +#include <bpf/bpf_helpers.h>
> +#include <bpf/bpf_tracing.h>
> +
> +char _license[] SEC("license") = "GPL";
> +
> +__u64 test1_entry_result = 0;
> +__u64 test1_exit_result = 0;
> +__u64 test1_entry_called = 0;
> +__u64 test1_exit_called = 0;
> +
> +SEC("fsession/bpf_fentry_test1")
> +int BPF_PROG(test1, int a)
> +{

I guess we can access return argument directly but it makes sense only
for exit session program, or we could use bpf_get_func_ret

jirka


> +     bool is_exit = bpf_tracing_is_exit(ctx);
> +
> +     if (!is_exit) {
> +             /* This is entry */
> +             test1_entry_called = 1;
> +             test1_entry_result = a == 1;
> +             return 0; /* Return 0 to allow exit to be called */
> +     }
> +
> +     /* This is exit */
> +     test1_exit_called = 1;
> +     test1_exit_result = a == 1;
> +     return 0;
> +}
> +
> +__u64 test2_entry_result = 0;
> +__u64 test2_exit_result = 0;
> +__u64 test2_entry_called = 0;
> +__u64 test2_exit_called = 0;
> +

SNIP

Reply via email to