bpf.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Philo Lu <lulie@linux.alibaba.com>
To: bpf@vger.kernel.org
Cc: ast@kernel.org, daniel@iogearbox.net, john.fastabend@gmail.com,
	andrii@kernel.org, martin.lau@linux.dev, song@kernel.org,
	yonghong.song@linux.dev, kpsingh@kernel.org, sdf@google.com,
	haoluo@google.com, jolsa@kernel.org, mykolal@fb.com,
	shuah@kernel.org, joannelkoong@gmail.com, laoar.shao@gmail.com,
	kuifeng@meta.com, houtao@huaweicloud.com, shung-hsi.yu@suse.com,
	xuanzhuo@linux.alibaba.com, dust.li@linux.alibaba.com,
	alibuda@linux.alibaba.com, guwen@linux.alibaba.com,
	hengqi@linux.alibaba.com
Subject: [PATCH bpf-next v1 3/3] selftests/bpf: add bpf relay map selftests
Date: Wed, 27 Dec 2023 18:01:30 +0800	[thread overview]
Message-ID: <20231227100130.84501-4-lulie@linux.alibaba.com> (raw)
In-Reply-To: <20231227100130.84501-1-lulie@linux.alibaba.com>

The operations of relay map create, update_elem, and output are tested.
The test is borrowed from ringbuf tests, where 2 samples are written
into the relay channel, and we get the samples by reading the files.
Overwriting mode is also tested, where the size of relay buffer equals
sample size and just the last sample can be seen.

Signed-off-by: Philo Lu <lulie@linux.alibaba.com>
---
 tools/include/uapi/linux/bpf.h                |   7 +
 tools/testing/selftests/bpf/Makefile          |   2 +-
 tools/testing/selftests/bpf/config            |   1 +
 .../selftests/bpf/prog_tests/relay_map.c      | 197 ++++++++++++++++++
 .../selftests/bpf/progs/test_relay_map.c      |  69 ++++++
 5 files changed, 275 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/relay_map.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_relay_map.c

diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 7f24d898efbb..1e545bfe701f 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -951,6 +951,7 @@ enum bpf_map_type {
 	BPF_MAP_TYPE_BLOOM_FILTER,
 	BPF_MAP_TYPE_USER_RINGBUF,
 	BPF_MAP_TYPE_CGRP_STORAGE,
+	BPF_MAP_TYPE_RELAY,
 };
 
 /* Note that tracing related programs such as
@@ -1330,6 +1331,9 @@ enum {
 
 /* Get path from provided FD in BPF_OBJ_PIN/BPF_OBJ_GET commands */
 	BPF_F_PATH_FD		= (1U << 14),
+
+/* Enable overwrite for relay map */
+	BPF_F_OVERWRITE		= (1U << 15),
 };
 
 /* Flags for BPF_PROG_QUERY. */
@@ -1401,6 +1405,9 @@ union bpf_attr {
 		 * BPF_MAP_TYPE_BLOOM_FILTER - the lowest 4 bits indicate the
 		 * number of hash functions (if 0, the bloom filter will default
 		 * to using 5 hash functions).
+		 *
+		 * BPF_MAP_TYPE_RELAY - the lowest 32 bits indicate the number of
+		 * relay subbufs (if 0, the number will be set to 8 by default).
 		 */
 		__u64	map_extra;
 	};
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 617ae55c3bb5..8cebb3810d50 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -427,7 +427,7 @@ LINKED_SKELS := test_static_linked.skel.h linked_funcs.skel.h		\
 LSKELS := fentry_test.c fexit_test.c fexit_sleep.c atomics.c 		\
 	trace_printk.c trace_vprintk.c map_ptr_kern.c 			\
 	core_kern.c core_kern_overflow.c test_ringbuf.c			\
-	test_ringbuf_map_key.c
+	test_ringbuf_map_key.c test_relay_map.c
 
 # Generate both light skeleton and libbpf skeleton for these
 LSKELS_EXTRA := test_ksyms_module.c test_ksyms_weak.c kfunc_call_test.c \
diff --git a/tools/testing/selftests/bpf/config b/tools/testing/selftests/bpf/config
index c125c441abc7..8de1adf587f0 100644
--- a/tools/testing/selftests/bpf/config
+++ b/tools/testing/selftests/bpf/config
@@ -87,3 +87,4 @@ CONFIG_VSOCKETS=y
 CONFIG_VXLAN=y
 CONFIG_XDP_SOCKETS=y
 CONFIG_XFRM_INTERFACE=y
+CONFIG_RELAY=y
diff --git a/tools/testing/selftests/bpf/prog_tests/relay_map.c b/tools/testing/selftests/bpf/prog_tests/relay_map.c
new file mode 100644
index 000000000000..bd9c1e62ca78
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/relay_map.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: GPL-2.0
+#define _GNU_SOURCE
+#include <linux/compiler.h>
+#include <linux/bpf.h>
+#include <sys/sysinfo.h>
+#include <test_progs.h>
+#include <sched.h>
+
+#include "test_relay_map.lskel.h"
+
+static int duration;
+
+/* file names in debugfs */
+static const char dirname[]		= "relay_map_selftest";
+static const char mapname[]		= "relay_map";
+static const char mapname_ow[]	= "relay_map_ow";
+struct relay_sample {
+	int pid;
+	int seq;
+	long value;
+	char comm[16];
+};
+
+static int sample_cnt;
+static int overwrite;
+
+static void process_sample(struct relay_sample *s)
+{
+	++sample_cnt;
+
+	switch (s->seq) {
+	case 0:
+		/* sample1 will not appear in overwrite mode */
+		CHECK(overwrite != 0, "overwrite_mode",
+		      "sample1 appears in overwrite mode\n");
+		CHECK(s->value != 333, "sample1_value", "exp %ld, got %ld\n",
+		      333L, s->value);
+		break;
+	case 1:
+		CHECK(s->value != 777, "sample2_value", "exp %ld, got %ld\n",
+		      777L, s->value);
+		break;
+	default:
+		break;
+	}
+}
+
+static int relaymap_read(const char *mapname)
+{
+	int cpu = libbpf_num_possible_cpus();
+	char name[NAME_MAX];
+	struct relay_sample data;
+	int maxloop;
+	FILE *fp;
+
+	for (int i = 0; i < cpu; ++i) {
+		sprintf(name, "/sys/kernel/debug/%s/%s%d", dirname, mapname, i);
+		fp = fopen(name, "r");
+		if (CHECK(!fp, "fopen", "relay file open failed\n"))
+			return -1;
+
+		maxloop = 0;
+		while (fread(&data, sizeof(data), 1, fp)) {
+			process_sample(&data);
+
+			/* just 2 samples output */
+			if (++maxloop > 2)
+				return -1;
+		}
+	}
+	return 0;
+}
+
+static struct test_relay_map_lskel *skel;
+
+static void trigger_samples(void)
+{
+	skel->bss->dropped = 0;
+	skel->bss->total = 0;
+	skel->bss->seq = 0;
+
+	/* trigger exactly two samples */
+	skel->bss->value = 333;
+	syscall(__NR_getpgid);
+	skel->bss->value = 777;
+	syscall(__NR_getpgid);
+}
+
+static void relaymap_subtest(void)
+{
+	int err, map_fd;
+
+	skel = test_relay_map_lskel__open();
+	if (CHECK(!skel, "skel_open", "skeleton open failed\n"))
+		return;
+
+	/* setup relay param */
+	skel->maps.relay_map.max_entries = 1024;
+
+	err = test_relay_map_lskel__load(skel);
+	if (CHECK(err, "skel_load", "skeleton load failed\n"))
+		goto cleanup;
+
+	/* only trigger BPF program for current process */
+	skel->bss->pid = getpid();
+
+	/* turn off overwrite */
+	skel->bss->overwrite_enable = 0;
+	overwrite = skel->bss->overwrite_enable;
+
+	err = test_relay_map_lskel__attach(skel);
+	if (CHECK(err, "skel_attach", "skeleton attachment failed: %d\n", err))
+		goto cleanup;
+
+	/* before file setup - output failed */
+	trigger_samples();
+	CHECK(skel->bss->dropped != 2, "err_dropped", "exp %ld, got %ld\n",
+	      0L, skel->bss->dropped);
+	CHECK(skel->bss->total != 2, "err_total", "exp %ld, got %ld\n",
+	      2L, skel->bss->total);
+
+	/* after file setup - output succ */
+	map_fd = skel->maps.relay_map.map_fd;
+	err = bpf_map_update_elem(map_fd, NULL, dirname, 0);
+	if (CHECK(err, "map_update", "map update failed: %d\n", err))
+		goto cleanup;
+	trigger_samples();
+	CHECK(skel->bss->dropped != 0, "err_dropped", "exp %ld, got %ld\n",
+	      0L, skel->bss->dropped);
+	CHECK(skel->bss->total != 2, "err_total", "exp %ld, got %ld\n",
+	      2L, skel->bss->total);
+
+	sample_cnt = 0;
+	err = relaymap_read(mapname);
+	CHECK(sample_cnt != 2, "sample_cnt", "exp %d samples, got %d\n",
+		   2, sample_cnt);
+
+	test_relay_map_lskel__detach(skel);
+cleanup:
+	test_relay_map_lskel__destroy(skel);
+}
+
+static void relaymap_overwrite_subtest(void)
+{
+	int err, map_fd;
+
+	skel = test_relay_map_lskel__open();
+	if (CHECK(!skel, "skel_open", "skeleton open failed\n"))
+		return;
+
+	/* To test overwrite mode, we create subbuf of one-sample size */
+	skel->maps.relay_map_ow.max_entries = sizeof(struct relay_sample);
+
+	err = test_relay_map_lskel__load(skel);
+	if (CHECK(err, "skel_load", "skeleton load failed\n"))
+		goto cleanup;
+
+	/* only trigger BPF program for current process */
+	skel->bss->pid = getpid();
+
+	/* turn on overwrite */
+	skel->bss->overwrite_enable = 1;
+	overwrite = skel->bss->overwrite_enable;
+
+	err = test_relay_map_lskel__attach(skel);
+	if (CHECK(err, "skel_attach", "skeleton attachment failed: %d\n", err))
+		goto cleanup;
+
+	map_fd = skel->maps.relay_map_ow.map_fd;
+	err = bpf_map_update_elem(map_fd, NULL, dirname, 0);
+	if (CHECK(err, "map_update", "map update failed: %d\n", err))
+		goto cleanup;
+	trigger_samples();
+	/* relay_write never fails whether overwriting or not */
+	CHECK(skel->bss->dropped != 0, "err_dropped", "exp %ld, got %ld\n",
+	      0L, skel->bss->dropped);
+	CHECK(skel->bss->total != 2, "err_total", "exp %ld, got %ld\n",
+	      2L, skel->bss->total);
+
+	/* 2 samples are output, but only the last (val=777) could be seen */
+	sample_cnt = 0;
+	err = relaymap_read(mapname_ow);
+	CHECK(sample_cnt != 1, "sample_cnt", "exp %d samples, got %d\n",
+		   1, sample_cnt);
+
+	test_relay_map_lskel__detach(skel);
+cleanup:
+	test_relay_map_lskel__destroy(skel);
+}
+
+void test_relaymap(void)
+{
+	if (test__start_subtest("relaymap"))
+		relaymap_subtest();
+	if (test__start_subtest("relaymap_overwrite"))
+		relaymap_overwrite_subtest();
+}
diff --git a/tools/testing/selftests/bpf/progs/test_relay_map.c b/tools/testing/selftests/bpf/progs/test_relay_map.c
new file mode 100644
index 000000000000..1adf1be8e125
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_relay_map.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <vmlinux.h>
+#include <bpf/bpf_helpers.h>
+#include "bpf_misc.h"
+
+char _license[] SEC("license") = "GPL";
+
+extern int bpf_relay_output(struct bpf_map *map, void *data,
+				      __u64 data__sz, __u32 flags) __ksym;
+
+struct relay_sample {
+	int pid;
+	int seq;
+	long value;
+	char comm[16];
+};
+
+struct {
+	__uint(type, BPF_MAP_TYPE_RELAY);
+	__uint(max_entries, 1024);
+} relay_map SEC(".maps");
+
+struct {
+	__uint(type, BPF_MAP_TYPE_RELAY);
+	__uint(map_flags, BPF_F_OVERWRITE);
+	__uint(max_entries, 1024);
+	__uint(map_extra, 1);
+} relay_map_ow SEC(".maps");
+
+/* inputs */
+int pid = 0;
+long value = 0;
+int overwrite_enable = 0;
+
+/* outputs */
+long total = 0;
+long dropped = 0;
+
+/* inner state */
+long seq = 0;
+
+SEC("fentry/" SYS_PREFIX "sys_getpgid")
+int test_bpf_relaymap(void *ctx)
+{
+	int cur_pid = bpf_get_current_pid_tgid() >> 32;
+	struct relay_sample sample;
+	int ret = 0;
+
+	if (cur_pid != pid)
+		return 0;
+
+	sample.pid = pid;
+	bpf_get_current_comm(sample.comm, sizeof(sample.comm));
+	sample.value = value;
+	sample.seq = seq++;
+	__sync_fetch_and_add(&total, 1);
+
+	if (overwrite_enable)
+		ret = bpf_relay_output((struct bpf_map *)&relay_map_ow,
+				      &sample, sizeof(sample), 0);
+	else
+		ret = bpf_relay_output((struct bpf_map *)&relay_map,
+				      &sample, sizeof(sample), 0);
+
+	if (ret)
+		__sync_fetch_and_add(&dropped, 1);
+
+	return 0;
+}
-- 
2.32.0.3.g01195cf9f


  parent reply	other threads:[~2023-12-27 10:01 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-12-27 10:01 [PATCH bpf-next v1 0/3] bpf: introduce BPF_MAP_TYPE_RELAY Philo Lu
2023-12-27 10:01 ` [PATCH bpf-next v1 1/3] bpf: implement relay map basis Philo Lu
2023-12-27 13:41   ` Yafang Shao
2023-12-27 10:01 ` [PATCH bpf-next v1 2/3] bpf: add bpf_relay_output kfunc Philo Lu
2023-12-27 14:23   ` Hou Tao
2023-12-27 18:07   ` Alexei Starovoitov
2023-12-27 10:01 ` Philo Lu [this message]
2023-12-27 13:42   ` [PATCH bpf-next v1 3/3] selftests/bpf: add bpf relay map selftests Yafang Shao
2023-12-27 18:02 ` [PATCH bpf-next v1 0/3] bpf: introduce BPF_MAP_TYPE_RELAY Alexei Starovoitov
2023-12-28 11:19   ` Philo Lu
2024-01-03 19:58     ` Alexei Starovoitov

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=20231227100130.84501-4-lulie@linux.alibaba.com \
    --to=lulie@linux.alibaba.com \
    --cc=alibuda@linux.alibaba.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=dust.li@linux.alibaba.com \
    --cc=guwen@linux.alibaba.com \
    --cc=haoluo@google.com \
    --cc=hengqi@linux.alibaba.com \
    --cc=houtao@huaweicloud.com \
    --cc=joannelkoong@gmail.com \
    --cc=john.fastabend@gmail.com \
    --cc=jolsa@kernel.org \
    --cc=kpsingh@kernel.org \
    --cc=kuifeng@meta.com \
    --cc=laoar.shao@gmail.com \
    --cc=martin.lau@linux.dev \
    --cc=mykolal@fb.com \
    --cc=sdf@google.com \
    --cc=shuah@kernel.org \
    --cc=shung-hsi.yu@suse.com \
    --cc=song@kernel.org \
    --cc=xuanzhuo@linux.alibaba.com \
    --cc=yonghong.song@linux.dev \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).