[RFC bpf-next 2/2] selftests/bpf: add tests for Userspace Runtime Defined Tracepoints (URDT)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add tests that verify operation of URDT probes for both
the statically and dynamically-linked libbpf cases.

Ensure probe attach and auto-attach succeed, and argument counts,
cookies and argument values match expectations.

Signed-off-by: Alan Maguire <alan.maguire@xxxxxxxxxx>
---
 tools/testing/selftests/bpf/Makefile          |   2 +-
 tools/testing/selftests/bpf/prog_tests/urdt.c | 173 ++++++++++++++++++
 tools/testing/selftests/bpf/progs/test_urdt.c | 100 ++++++++++
 .../selftests/bpf/progs/test_urdt_shared.c    |  59 ++++++
 4 files changed, 333 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/urdt.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_urdt.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_urdt_shared.c

diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index fd15017ed3b1..d21acb95a3e1 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -39,7 +39,7 @@ CFLAGS += -g $(OPT_FLAGS) -rdynamic					\
 	  -I$(CURDIR) -I$(INCLUDE_DIR) -I$(GENDIR) -I$(LIBDIR)		\
 	  -I$(TOOLSINCDIR) -I$(APIDIR) -I$(OUTPUT)
 LDFLAGS += $(SAN_LDFLAGS)
-LDLIBS += $(LIBELF_LIBS) -lz -lrt -lpthread
+LDLIBS += $(LIBELF_LIBS) -lz -lrt -lpthread -ldl
 
 ifneq ($(LLVM),)
 # Silence some warnings when compiled with clang
diff --git a/tools/testing/selftests/bpf/prog_tests/urdt.c b/tools/testing/selftests/bpf/prog_tests/urdt.c
new file mode 100644
index 000000000000..725d064d78f2
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/urdt.c
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024, Oracle and/or its affiliates. */
+
+#include <test_progs.h>
+
+#include <dlfcn.h>
+
+#include "../sdt.h"
+
+#include "test_urdt.skel.h"
+#include "test_urdt_shared.skel.h"
+
+static volatile __u64 bla = 0xFEDCBA9876543210ULL;
+
+static void subtest_basic_urdt(void)
+{
+	LIBBPF_OPTS(bpf_urdt_opts, opts);
+	struct test_urdt *skel;
+	struct test_urdt__bss *bss;
+	long x = 1;
+	int y = 42;
+	int err;
+	int i;
+
+	skel = test_urdt__open_and_load();
+	if (!ASSERT_OK_PTR(skel, "skel_open"))
+		return;
+
+	bss = skel->bss;
+	bss->my_pid = getpid();
+
+	err = test_urdt__attach(skel);
+	if (!ASSERT_OK(err, "skel_attach"))
+		goto cleanup;
+
+	/* urdt0 won't be auto-attached */
+	opts.urdt_cookie = 0xcafedead;
+	opts.urdt_nargs = 0;
+	skel->links.urdt0 = bpf_program__attach_urdt(skel->progs.urdt0,
+						     0 /*self*/, "/proc/self/exe",
+						     "dyn", "urdt0", &opts);
+	if (!ASSERT_OK_PTR(skel->links.urdt0, "urdt0_link"))
+		goto cleanup;
+
+	BPF_URDT_PROBE0("dyn", "urdt0");
+
+	ASSERT_EQ(bss->urdt0_called, 1, "urdt0_called");
+
+	ASSERT_EQ(bss->urdt0_cookie, 0xcafedead, "urdt0_cookie");
+	ASSERT_EQ(bss->urdt0_arg_cnt, 0, "urdt0_arg_cnt");
+	ASSERT_EQ(bss->urdt0_arg_ret, -ENOENT, "urdt0_arg_ret");
+
+	BPF_URDT_PROBE3("dyn", "urdt3", x, y, &bla);
+
+	ASSERT_EQ(bss->urdt3_called, 1, "urdt3_called");
+	/* ensure the other 3-arg URDT probe does not trigger */
+	ASSERT_EQ(bss->urdt3alt_called, 0, "urdt3alt_notcalled");
+	/* auto-attached urdt3 gets default zero cookie value */
+	ASSERT_EQ(bss->urdt3_cookie, 0, "urdt3_cookie");
+	ASSERT_EQ(bss->urdt3_arg_cnt, 3, "urdt3_arg_cnt");
+
+	ASSERT_EQ(bss->urdt3_arg1, 1, "urdt3_arg1");
+	ASSERT_EQ(bss->urdt3_arg2, 42, "urdt3_arg2");
+	ASSERT_EQ((long)bss->urdt3_arg3, (long)&bla, "urdt3_arg3");
+
+	/* now call alternative 3-arg function, and make sure dyn/urdt3
+	 * does not trigger.
+	 */
+	BPF_URDT_PROBE3("dyn", "urdt3alt", y, &bla, x);
+
+	ASSERT_EQ(bss->urdt3alt_called, 1, "urdt3alt_called");
+	ASSERT_EQ(bss->urdt3_called, 1, "urdt3_notcalled");
+
+	ASSERT_EQ(bss->urdt3alt_arg1, 42, "urdt3alt_arg1");
+	ASSERT_EQ((long)bss->urdt3alt_arg2, (long)&bla, "urdt3_arg3");
+	ASSERT_EQ(bss->urdt3alt_arg3, 1, "urdt3alt_arg3");
+
+	BPF_URDT_PROBE11("dyn", "urdt11", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
+
+	ASSERT_EQ(bss->urdt11_called, 1, "urdt11_called");
+	ASSERT_EQ(bss->urdt3_called, 1, "urdt3_called");
+	for (i = 0; i < 11; i++)
+		ASSERT_EQ(bss->urdt11_args[i], i + 1, "urdt11_arg");
+
+cleanup:
+	test_urdt__destroy(skel);
+}
+
+#define LIBBPF_SO_PATH	"./tools/build/libbpf/libbpf.so"
+
+/* verify shared object attach/firing works for libbpf.so */
+static void subtest_shared_urdt(void)
+{
+	LIBBPF_OPTS(bpf_urdt_opts, opts);
+	struct test_urdt_shared *skel;
+	void *dlh;
+	void (*probe0)(const char *provider, const char *probe);
+	void (*probe4)(const char *provider, const char *probe, long arg1, long arg2,
+		       long arg3, long arg4);
+	struct test_urdt_shared__bss *bss;
+	long x = 1;
+	int y = 42;
+	int z = 3;
+	int err;
+
+	skel = test_urdt_shared__open_and_load();
+	if (!ASSERT_OK_PTR(skel, "skel_open"))
+		return;
+	bss = skel->bss;
+	bss->my_pid = getpid();
+
+	err = test_urdt_shared__attach(skel);
+	if (!ASSERT_OK(err, "skel_attach"))
+		goto cleanup;
+
+	/* urdt0 won't be auto-attached */
+	opts.urdt_cookie = 0xcafedead;
+	opts.urdt_nargs = 0;
+	skel->links.urdt0 = bpf_program__attach_urdt(skel->progs.urdt0,
+						     -1 /* all */,
+						     LIBBPF_SO_PATH,
+						     "dyn", "urdt0", &opts);
+	if (!ASSERT_OK_PTR(skel->links.urdt0, "urdt0_link"))
+		goto cleanup;
+
+	/* test_progs is statically linked with libbpf, so we need to dlopen/dlsym
+	 * probe firing functions in the shared object we have attached to in order
+	 * to trigger probe firing.  If a program is dynamically linked to libbpf
+	 * for probe firing, this won't be needed, but we want to make sure this
+	 * mode of operation works as it will likely be the common case.
+	 */
+	dlh = dlopen(LIBBPF_SO_PATH, RTLD_NOW);
+	if (!ASSERT_NEQ(dlh, NULL, "dlopen"))
+		goto cleanup;
+	probe0 = dlsym(dlh, "bpf_urdt__probe0");
+	if (!ASSERT_NEQ(probe0, NULL, "dlsym_probe0"))
+		goto cleanup;
+	probe4 = dlsym(dlh, "bpf_urdt__probe4");
+	if (!ASSERT_NEQ(probe4, NULL, "dlsym_probe4"))
+		goto cleanup;
+
+	probe0("dyn", "urdt0");
+
+	ASSERT_EQ(bss->urdt0_called, 1, "urdt0_called");
+
+	ASSERT_EQ(bss->urdt0_cookie, 0xcafedead, "urdt0_cookie");
+	ASSERT_EQ(bss->urdt0_arg_cnt, 0, "urdt0_arg_cnt");
+	ASSERT_EQ(bss->urdt0_arg_ret, -ENOENT, "urdt0_arg_ret");
+
+	probe4("dyn", "urdt4", (long)x, (long)y, (long)z, (long)&bla);
+
+	ASSERT_EQ(bss->urdt4_called, 1, "urdt4_called");
+	/* auto-attached urdt4 gets default zero cookie value */
+	ASSERT_EQ(bss->urdt4_cookie, 0, "urdt4_cookie");
+	ASSERT_EQ(bss->urdt4_arg_cnt, 4, "urdt4_arg_cnt");
+
+	ASSERT_EQ(bss->urdt4_arg1, 1, "urdt4_arg1");
+	ASSERT_EQ(bss->urdt4_arg2, 42, "urdt4_arg2");
+	ASSERT_EQ(bss->urdt4_arg3, 3, "urdt4_arg3");
+	ASSERT_EQ((long)bss->urdt4_arg4, (long)&bla, "urdt4_arg4");
+cleanup:
+	if (dlh)
+		dlclose(dlh);
+	test_urdt_shared__destroy(skel);
+}
+
+void test_urdt(void)
+{
+	if (test__start_subtest("basic"))
+		subtest_basic_urdt();
+	if (test__start_subtest("shared"))
+		subtest_shared_urdt();
+}
diff --git a/tools/testing/selftests/bpf/progs/test_urdt.c b/tools/testing/selftests/bpf/progs/test_urdt.c
new file mode 100644
index 000000000000..82d5fbdc5744
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_urdt.c
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024, Oracle and/or its affiliates. */
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/urdt.bpf.h>
+
+int my_pid;
+
+int urdt0_called;
+int urdt0_cookie;
+int urdt0_arg_cnt;
+int urdt0_arg_ret;
+
+SEC("urdt")
+int BPF_URDT(urdt0)
+{
+	long tmp;
+
+	if (my_pid != (bpf_get_current_pid_tgid() >> 32))
+		return 0;
+
+	__sync_fetch_and_add(&urdt0_called, 1);
+
+	urdt0_cookie = bpf_urdt_cookie(ctx);
+	urdt0_arg_cnt = bpf_urdt_arg_cnt(ctx);
+	/* should return -ENOENT for any arg_num */
+	urdt0_arg_ret = bpf_usdt_arg(ctx, bpf_get_prandom_u32(), &tmp);
+	return 0;
+}
+
+int urdt3_called;
+int urdt3_cookie;
+int urdt3_arg_cnt;
+long urdt3_arg1;
+int urdt3_arg2;
+__u64 *urdt3_arg3;
+
+SEC("urdt//proc/self/exe:3:dyn:urdt3")
+int BPF_URDT(urdt3, long x, int y, __u64 *bla)
+{
+	if (my_pid != (bpf_get_current_pid_tgid() >> 32))
+		return 0;
+
+	__sync_fetch_and_add(&urdt3_called, 1);
+
+	__sync_fetch_and_add(&urdt3_cookie, bpf_urdt_cookie(ctx));
+	__sync_fetch_and_add(&urdt3_arg_cnt, bpf_urdt_arg_cnt(ctx));
+
+	__sync_fetch_and_add(&urdt3_arg1, x);
+	__sync_fetch_and_add(&urdt3_arg2, y);
+	__sync_fetch_and_add(&urdt3_arg3, bla);
+
+	return 0;
+}
+
+int urdt3alt_called;
+int urdt3alt_cookie;
+int urdt3alt_arg1;
+__u64 *urdt3alt_arg2;
+long urdt3alt_arg3;
+
+SEC("urdt//proc/self/exe:3:dyn:urdt3alt")
+int BPF_URDT(urdt3alt, int y, __u64 *bla, long x)
+{
+	__sync_fetch_and_add(&urdt3alt_called, 1);
+
+	__sync_fetch_and_add(&urdt3alt_cookie, bpf_urdt_cookie(ctx));
+
+	__sync_fetch_and_add(&urdt3alt_arg1, y);
+	__sync_fetch_and_add(&urdt3alt_arg2, bla);
+	__sync_fetch_and_add(&urdt3alt_arg3, x);
+
+	return 0;
+}
+
+int urdt11_called;
+int urdt11_args[11];
+
+SEC("urdt//proc/self/exe:11:dyn:urdt11")
+int BPF_URDT(urdt11, int arg1, int arg2, int arg3, int arg4, int arg5,
+	     int arg6, int arg7, int arg8, int arg9, int arg10, int arg11)
+{
+	__sync_fetch_and_add(&urdt11_called, 1);
+	__sync_fetch_and_add(&urdt11_args[0], arg1);
+	__sync_fetch_and_add(&urdt11_args[1], arg2);
+	__sync_fetch_and_add(&urdt11_args[2], arg3);
+	__sync_fetch_and_add(&urdt11_args[3], arg4);
+	__sync_fetch_and_add(&urdt11_args[4], arg5);
+	__sync_fetch_and_add(&urdt11_args[5], arg6);
+	__sync_fetch_and_add(&urdt11_args[6], arg7);
+	__sync_fetch_and_add(&urdt11_args[7], arg8);
+	__sync_fetch_and_add(&urdt11_args[8], arg9);
+	__sync_fetch_and_add(&urdt11_args[9], arg10);
+	__sync_fetch_and_add(&urdt11_args[10], arg11);
+
+	return 0;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/test_urdt_shared.c b/tools/testing/selftests/bpf/progs/test_urdt_shared.c
new file mode 100644
index 000000000000..2cdb181f73bd
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_urdt_shared.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024, Oracle and/or its affiliates. */
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/urdt.bpf.h>
+
+int my_pid;
+
+int urdt0_called;
+int urdt0_cookie;
+int urdt0_arg_cnt;
+int urdt0_arg_ret;
+
+SEC("urdt")
+int BPF_URDT(urdt0)
+{
+	long tmp;
+
+	if (my_pid != (bpf_get_current_pid_tgid() >> 32))
+		return 0;
+
+	__sync_fetch_and_add(&urdt0_called, 1);
+
+	urdt0_cookie = bpf_urdt_cookie(ctx);
+	urdt0_arg_cnt = bpf_urdt_arg_cnt(ctx);
+	/* should return -ENOENT for any arg_num */
+	urdt0_arg_ret = bpf_usdt_arg(ctx, bpf_get_prandom_u32(), &tmp);
+	return 0;
+}
+
+int urdt4_called;
+int urdt4_cookie;
+int urdt4_arg_cnt;
+long urdt4_arg1;
+int urdt4_arg2;
+int urdt4_arg3;
+__u64 *urdt4_arg4;
+
+SEC("urdt/./tools/build/libbpf/libbpf.so:4:dyn:urdt4")
+int BPF_URDT(urdt4, long x, int y, int z, __u64 *bla)
+{
+	if (my_pid != (bpf_get_current_pid_tgid() >> 32))
+		return 0;
+
+	__sync_fetch_and_add(&urdt4_called, 1);
+
+	__sync_fetch_and_add(&urdt4_cookie, bpf_urdt_cookie(ctx));
+	__sync_fetch_and_add(&urdt4_arg_cnt, bpf_urdt_arg_cnt(ctx));
+
+	__sync_fetch_and_add(&urdt4_arg1, x);
+	__sync_fetch_and_add(&urdt4_arg2, y);
+	__sync_fetch_and_add(&urdt4_arg3, z);
+	__sync_fetch_and_add(&urdt4_arg4, bla);
+
+	return 0;
+}
+
+char _license[] SEC("license") = "GPL";
-- 
2.39.3





[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux