bpf.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Yafang Shao <laoar.shao@gmail.com>
To: Philo Lu <lulie@linux.alibaba.com>
Cc: bpf@vger.kernel.org, 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, 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: Re: [PATCH bpf-next v1 3/3] selftests/bpf: add bpf relay map selftests
Date: Wed, 27 Dec 2023 21:42:56 +0800	[thread overview]
Message-ID: <CALOAHbDDx8K3qf623KOo-EYFksTRLgHOgDw0WcsZsrTXukO0fw@mail.gmail.com> (raw)
In-Reply-To: <20231227100130.84501-4-lulie@linux.alibaba.com>

On Wed, Dec 27, 2023 at 6:01 PM Philo Lu <lulie@linux.alibaba.com> wrote:
>
> 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");

fclose() is missed.

> +               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
>


-- 
Regards
Yafang

  reply	other threads:[~2023-12-27 13:43 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 ` [PATCH bpf-next v1 3/3] selftests/bpf: add bpf relay map selftests Philo Lu
2023-12-27 13:42   ` Yafang Shao [this message]
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=CALOAHbDDx8K3qf623KOo-EYFksTRLgHOgDw0WcsZsrTXukO0fw@mail.gmail.com \
    --to=laoar.shao@gmail.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=lulie@linux.alibaba.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).