[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250204082848.13471-4-hotforest@gmail.com>
Date: Tue, 4 Feb 2025 16:28:48 +0800
From: Hou Tao <hotforest@...il.com>
To: bpf@...r.kernel.org,
rcu@...r.kernel.org
Cc: linux-kernel@...r.kernel.org,
Alexei Starovoitov <ast@...nel.org>,
Daniel Borkmann <daniel@...earbox.net>,
Andrii Nakryiko <andrii@...nel.org>,
Martin KaFai Lau <martin.lau@...ux.dev>,
Eduard Zingerman <eddyz87@...il.com>,
Song Liu <song@...nel.org>,
Yonghong Song <yonghong.song@...ux.dev>,
John Fastabend <john.fastabend@...il.com>,
KP Singh <kpsingh@...nel.org>,
Stanislav Fomichev <sdf@...ichev.me>,
Hao Luo <haoluo@...gle.com>,
Jiri Olsa <jolsa@...nel.org>,
"Paul E . McKenney" <paulmck@...nel.org>,
houtao1@...wei.com,
hotforest@...il.com
Subject: [PATCH bpf-next 3/3] selftests/bpf: Add test case for atomic htab update
Add a test case to verify the atomic update of existing element in hash
map. The test proceeds in three steps:
1) fill the map with keys in the range [0, 63]
2) create 8 threads to lookup these keys concurrently
3) create 2 threads to overwrite these keys concurrently
Without atomic update support, the lookup operation may return -ENOENT
error and the test will fail. After the atomic-update change, the lookup
operation will always return 0 and the test will succeed.
Signed-off-by: Hou Tao <hotforest@...il.com>
---
.../selftests/bpf/prog_tests/htab_lookup.c | 130 ++++++++++++++++++
.../testing/selftests/bpf/progs/htab_lookup.c | 13 ++
2 files changed, 143 insertions(+)
create mode 100644 tools/testing/selftests/bpf/prog_tests/htab_lookup.c
create mode 100644 tools/testing/selftests/bpf/progs/htab_lookup.c
diff --git a/tools/testing/selftests/bpf/prog_tests/htab_lookup.c b/tools/testing/selftests/bpf/prog_tests/htab_lookup.c
new file mode 100644
index 000000000000..ef9036827439
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/htab_lookup.c
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0
+#define _GNU_SOURCE
+#include <stdbool.h>
+#include <test_progs.h>
+#include "htab_lookup.skel.h"
+
+struct htab_op_ctx {
+ int fd;
+ int loop;
+ unsigned int entries;
+ bool stop;
+};
+
+static void *htab_lookup_fn(void *arg)
+{
+ struct htab_op_ctx *ctx = arg;
+ int i = 0;
+
+ while (i++ < ctx->loop && !ctx->stop) {
+ unsigned int j;
+
+ for (j = 0; j < ctx->entries; j++) {
+ unsigned long key = j, value;
+ int err;
+
+ err = bpf_map_lookup_elem(ctx->fd, &key, &value);
+ if (err) {
+ ctx->stop = true;
+ return (void *)(long)err;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static void *htab_update_fn(void *arg)
+{
+ struct htab_op_ctx *ctx = arg;
+ int i = 0;
+
+ while (i++ < ctx->loop && !ctx->stop) {
+ unsigned int j;
+
+ for (j = 0; j < ctx->entries; j++) {
+ unsigned long key = j, value = j;
+ int err;
+
+ err = bpf_map_update_elem(ctx->fd, &key, &value, BPF_EXIST);
+ if (err) {
+ if (err == -ENOMEM)
+ continue;
+ ctx->stop = true;
+ return (void *)(long)err;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static int setup_htab(int fd, unsigned int entries)
+{
+ unsigned int i;
+
+ for (i = 0; i < entries; i++) {
+ unsigned long key = i, value = i;
+ int err;
+
+ err = bpf_map_update_elem(fd, &key, &value, 0);
+ if (!ASSERT_OK(err, "init update"))
+ return -1;
+ }
+
+ return 0;
+}
+
+void test_htab_lookup(void)
+{
+ unsigned int i, wr_nr = 2, rd_nr = 8;
+ pthread_t tids[wr_nr + rd_nr];
+ struct htab_lookup *skel;
+ struct htab_op_ctx ctx;
+ int err;
+
+ skel = htab_lookup__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "htab_lookup__open_and_load"))
+ return;
+
+ ctx.fd = bpf_map__fd(skel->maps.htab);
+ ctx.loop = 50;
+ ctx.stop = false;
+ ctx.entries = 64;
+
+ err = setup_htab(ctx.fd, ctx.entries);
+ if (err)
+ goto destroy;
+
+ memset(tids, 0, sizeof(tids));
+ for (i = 0; i < wr_nr; i++) {
+ err = pthread_create(&tids[i], NULL, htab_update_fn, &ctx);
+ if (!ASSERT_OK(err, "pthread_create")) {
+ ctx.stop = true;
+ goto reap;
+ }
+ }
+ for (i = 0; i < rd_nr; i++) {
+ err = pthread_create(&tids[i + wr_nr], NULL, htab_lookup_fn, &ctx);
+ if (!ASSERT_OK(err, "pthread_create")) {
+ ctx.stop = true;
+ goto reap;
+ }
+ }
+
+reap:
+ for (i = 0; i < wr_nr + rd_nr; i++) {
+ void *ret = NULL;
+ char desc[32];
+
+ if (!tids[i])
+ continue;
+
+ snprintf(desc, sizeof(desc), "thread %u", i + 1);
+ err = pthread_join(tids[i], &ret);
+ ASSERT_OK(err, desc);
+ ASSERT_EQ(ret, NULL, desc);
+ }
+destroy:
+ htab_lookup__destroy(skel);
+}
diff --git a/tools/testing/selftests/bpf/progs/htab_lookup.c b/tools/testing/selftests/bpf/progs/htab_lookup.c
new file mode 100644
index 000000000000..baa30fa5b84f
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/htab_lookup.c
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+
+char _license[] SEC("license") = "GPL";
+
+struct {
+ __uint(type, BPF_MAP_TYPE_HASH);
+ __uint(max_entries, 64);
+ __type(key, unsigned long);
+ __type(value, unsigned long);
+ __uint(map_flags, BPF_F_NO_PREALLOC);
+} htab SEC(".maps");
--
2.48.1
Powered by blists - more mailing lists