[PATCH bpf-next v1 3/3] selftests/bpf: add bpf relay map selftests

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

 



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@xxxxxxxxxxxxxxxxx>
---
 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





[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