All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexei Starovoitov <alexei.starovoitov@gmail.com>
To: davem@davemloft.net
Cc: daniel@iogearbox.net, andrii@kernel.org, netdev@vger.kernel.org,
	bpf@vger.kernel.org, kernel-team@fb.com
Subject: [PATCH bpf-next 3/3] selftests/bpf: Add bpf_timer test.
Date: Wed, 26 May 2021 21:02:59 -0700	[thread overview]
Message-ID: <20210527040259.77823-4-alexei.starovoitov@gmail.com> (raw)
In-Reply-To: <20210527040259.77823-1-alexei.starovoitov@gmail.com>

From: Alexei Starovoitov <ast@kernel.org>

Add bpf_timer test that creates two timers. One in hash map and another global
timer in bss. It let global timer expire once and then re-arms it for 35
seconds. Then arms and re-arms hash timer 10 times and at the last invocation
cancels global timer.

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
---
 .../testing/selftests/bpf/prog_tests/timer.c  | 47 ++++++++++
 tools/testing/selftests/bpf/progs/timer.c     | 85 +++++++++++++++++++
 2 files changed, 132 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/timer.c
 create mode 100644 tools/testing/selftests/bpf/progs/timer.c

diff --git a/tools/testing/selftests/bpf/prog_tests/timer.c b/tools/testing/selftests/bpf/prog_tests/timer.c
new file mode 100644
index 000000000000..7be2aeba2dad
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/timer.c
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2021 Facebook */
+#include <test_progs.h>
+#include "timer.skel.h"
+
+static int timer(struct timer *timer_skel)
+{
+	int err, prog_fd;
+	__u32 duration = 0, retval;
+
+	err = timer__attach(timer_skel);
+	if (!ASSERT_OK(err, "timer_attach"))
+		return err;
+
+	ASSERT_EQ(timer_skel->data->callback_check, 52, "callback_check1");
+
+	prog_fd = bpf_program__fd(timer_skel->progs.test1);
+	err = bpf_prog_test_run(prog_fd, 1, NULL, 0,
+				NULL, NULL, &retval, &duration);
+	ASSERT_OK(err, "test_run");
+	ASSERT_EQ(retval, 0, "test_run");
+	timer__detach(timer_skel);
+
+	usleep(50 * 1000); /* 10 msecs should be enough, but give it extra */
+	/* check that timer_cb1() was executed 10 times */
+	ASSERT_EQ(timer_skel->data->callback_check, 42, "callback_check2");
+
+	/* check that timer_cb2() was executed once */
+	ASSERT_EQ(timer_skel->bss->bss_data, 15, "bss_data");
+
+	return 0;
+}
+
+void test_timer(void)
+{
+	struct timer *timer_skel = NULL;
+	int err;
+
+	timer_skel = timer__open_and_load();
+	if (!ASSERT_OK_PTR(timer_skel, "timer_skel_load"))
+		goto cleanup;
+
+	err = timer(timer_skel);
+	ASSERT_OK(err, "timer");
+cleanup:
+	timer__destroy(timer_skel);
+}
diff --git a/tools/testing/selftests/bpf/progs/timer.c b/tools/testing/selftests/bpf/progs/timer.c
new file mode 100644
index 000000000000..d20672cf61d6
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/timer.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2021 Facebook */
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include "bpf_tcp_helpers.h"
+
+char _license[] SEC("license") = "GPL";
+struct map_elem {
+	int counter;
+	struct bpf_timer timer;
+};
+
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 1000);
+	__type(key, int);
+	__type(value, struct map_elem);
+} hmap SEC(".maps");
+
+__u64 bss_data;
+struct bpf_timer global_timer;
+
+__u64 callback_check = 52;
+
+static int timer_cb1(void *map, int *key, __u64 *data)
+{
+	/* increment the same bss variable twice */
+	bss_data += 5;
+	data[0] += 10; /* &data[1] == &bss_data */
+	/* note data[1] access will be rejected by the verifier,
+	 * since &data[1] points to the &global_timer.
+	 */
+
+	/* rearm self to be called again in ~35 seconds */
+	bpf_timer_start(&global_timer, 1ull << 35);
+	return 0;
+}
+
+SEC("fentry/bpf_fentry_test1")
+int BPF_PROG(test1, int a)
+{
+	bpf_timer_init(&global_timer, timer_cb1, 0);
+	bpf_timer_start(&global_timer, 0 /* call timer_cb1 asap */);
+	return 0;
+}
+
+static int timer_cb2(void *map, int *key, struct map_elem *val)
+{
+	callback_check--;
+	if (--val->counter)
+		/* re-arm the timer again to execute after 1 msec */
+		bpf_timer_start(&val->timer, 1000);
+	else {
+		/* cancel global_timer otherwise bpf_fentry_test1 prog
+		 * will stay alive forever.
+		 */
+		bpf_timer_cancel(&global_timer);
+		bpf_timer_cancel(&val->timer);
+	}
+	return 0;
+}
+
+int bpf_timer_test(void)
+{
+	struct map_elem *val;
+	int key = 0;
+
+	val = bpf_map_lookup_elem(&hmap, &key);
+	if (val) {
+		bpf_timer_init(&val->timer, timer_cb2, 0);
+		bpf_timer_start(&val->timer, 1000);
+	}
+	return 0;
+}
+
+SEC("fentry/bpf_fentry_test2")
+int BPF_PROG(test2, int a, int b)
+{
+	struct map_elem val = {};
+	int key = 0;
+
+	val.counter = 10; /* number of times to trigger timer_cb1 */
+	bpf_map_update_elem(&hmap, &key, &val, 0);
+	return bpf_timer_test();
+}
-- 
2.30.2


      parent reply	other threads:[~2021-05-27  4:03 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-27  4:02 [PATCH bpf-next 0/3] bpf: Introduce BPF timers Alexei Starovoitov
2021-05-27  4:02 ` [PATCH bpf-next 1/3] bpf: Introduce bpf_timer Alexei Starovoitov
2021-05-27 16:57   ` Toke Høiland-Jørgensen
2021-06-02  1:46     ` Alexei Starovoitov
2021-06-02 22:21       ` Toke Høiland-Jørgensen
2021-06-03  1:58         ` Alexei Starovoitov
2021-06-03 10:59           ` Toke Høiland-Jørgensen
2021-06-03 17:21             ` Andrii Nakryiko
2021-06-02 22:08   ` Andrii Nakryiko
2021-06-03  1:53     ` Alexei Starovoitov
2021-06-03 17:10       ` Andrii Nakryiko
2021-06-04  1:12         ` Alexei Starovoitov
2021-06-04  4:17           ` Andrii Nakryiko
2021-06-04 18:16             ` Alexei Starovoitov
2021-05-27  4:02 ` [PATCH bpf-next 2/3] bpf: Add verifier checks for bpf_timer Alexei Starovoitov
2021-06-02 22:34   ` Andrii Nakryiko
2021-06-02 22:38     ` Andrii Nakryiko
2021-06-03  2:04     ` Alexei Starovoitov
2021-06-03 17:35       ` Andrii Nakryiko
2021-05-27  4:02 ` Alexei Starovoitov [this message]

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=20210527040259.77823-4-alexei.starovoitov@gmail.com \
    --to=alexei.starovoitov@gmail.com \
    --cc=andrii@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=davem@davemloft.net \
    --cc=kernel-team@fb.com \
    --cc=netdev@vger.kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.