diff mbox series

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

Message ID 20240131162003.962665-3-alan.maguire@oracle.com (mailing list archive)
State RFC
Delegated to: BPF
Headers show
Series libbpf Userspace Runtime-Defined Tracing (URDT) | expand

Checks

Context Check Description
netdev/tree_selection success Clearly marked for bpf-next, async
netdev/apply fail Patch does not apply to bpf-next
bpf/vmtest-bpf-next-PR fail PR summary
bpf/vmtest-bpf-next-VM_Test-0 success Logs for Lint
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-2 success Logs for Unittests
bpf/vmtest-bpf-next-VM_Test-3 success Logs for Validate matrix.py
bpf/vmtest-bpf-next-VM_Test-4 fail Logs for aarch64-gcc / build / build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-5 success Logs for aarch64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-6 success Logs for aarch64-gcc / test
bpf/vmtest-bpf-next-VM_Test-7 success Logs for aarch64-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-8 fail Logs for s390x-gcc / build / build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-9 success Logs for s390x-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-10 success Logs for s390x-gcc / test
bpf/vmtest-bpf-next-VM_Test-17 fail Logs for x86_64-llvm-17 / build / build for x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-11 success Logs for s390x-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-15 success Logs for x86_64-gcc / test
bpf/vmtest-bpf-next-VM_Test-12 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-14 success Logs for x86_64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-16 success Logs for x86_64-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-22 fail Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18 and -O2 optimization
bpf/vmtest-bpf-next-VM_Test-23 success Logs for x86_64-llvm-18 / test
bpf/vmtest-bpf-next-VM_Test-24 success Logs for x86_64-llvm-18 / veristat
bpf/vmtest-bpf-next-VM_Test-13 fail Logs for x86_64-gcc / build / build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-20 success Logs for x86_64-llvm-17 / veristat
bpf/vmtest-bpf-next-VM_Test-19 success Logs for x86_64-llvm-17 / test
bpf/vmtest-bpf-next-VM_Test-18 fail Logs for x86_64-llvm-17 / build-release / build for x86_64 with llvm-17 and -O2 optimization
bpf/vmtest-bpf-next-VM_Test-21 fail Logs for x86_64-llvm-18 / build / build for x86_64 with llvm-18

Commit Message

Alan Maguire Jan. 31, 2024, 4:20 p.m. UTC
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@oracle.com>
---
 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 mbox series

Patch

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";