Skip to content

Commit e70b366

Browse files
htbeginKernel Patches Daemon
authored and
Kernel Patches Daemon
committed
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 <[email protected]>
1 parent 9b29dd9 commit e70b366

File tree

2 files changed

+143
-0
lines changed

2 files changed

+143
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#define _GNU_SOURCE
3+
#include <stdbool.h>
4+
#include <test_progs.h>
5+
#include "htab_lookup.skel.h"
6+
7+
struct htab_op_ctx {
8+
int fd;
9+
int loop;
10+
unsigned int entries;
11+
bool stop;
12+
};
13+
14+
static void *htab_lookup_fn(void *arg)
15+
{
16+
struct htab_op_ctx *ctx = arg;
17+
int i = 0;
18+
19+
while (i++ < ctx->loop && !ctx->stop) {
20+
unsigned int j;
21+
22+
for (j = 0; j < ctx->entries; j++) {
23+
unsigned long key = j, value;
24+
int err;
25+
26+
err = bpf_map_lookup_elem(ctx->fd, &key, &value);
27+
if (err) {
28+
ctx->stop = true;
29+
return (void *)(long)err;
30+
}
31+
}
32+
}
33+
34+
return NULL;
35+
}
36+
37+
static void *htab_update_fn(void *arg)
38+
{
39+
struct htab_op_ctx *ctx = arg;
40+
int i = 0;
41+
42+
while (i++ < ctx->loop && !ctx->stop) {
43+
unsigned int j;
44+
45+
for (j = 0; j < ctx->entries; j++) {
46+
unsigned long key = j, value = j;
47+
int err;
48+
49+
err = bpf_map_update_elem(ctx->fd, &key, &value, BPF_EXIST);
50+
if (err) {
51+
if (err == -ENOMEM)
52+
continue;
53+
ctx->stop = true;
54+
return (void *)(long)err;
55+
}
56+
}
57+
}
58+
59+
return NULL;
60+
}
61+
62+
static int setup_htab(int fd, unsigned int entries)
63+
{
64+
unsigned int i;
65+
66+
for (i = 0; i < entries; i++) {
67+
unsigned long key = i, value = i;
68+
int err;
69+
70+
err = bpf_map_update_elem(fd, &key, &value, 0);
71+
if (!ASSERT_OK(err, "init update"))
72+
return -1;
73+
}
74+
75+
return 0;
76+
}
77+
78+
void test_htab_lookup(void)
79+
{
80+
unsigned int i, wr_nr = 2, rd_nr = 8;
81+
pthread_t tids[wr_nr + rd_nr];
82+
struct htab_lookup *skel;
83+
struct htab_op_ctx ctx;
84+
int err;
85+
86+
skel = htab_lookup__open_and_load();
87+
if (!ASSERT_OK_PTR(skel, "htab_lookup__open_and_load"))
88+
return;
89+
90+
ctx.fd = bpf_map__fd(skel->maps.htab);
91+
ctx.loop = 50;
92+
ctx.stop = false;
93+
ctx.entries = 64;
94+
95+
err = setup_htab(ctx.fd, ctx.entries);
96+
if (err)
97+
goto destroy;
98+
99+
memset(tids, 0, sizeof(tids));
100+
for (i = 0; i < wr_nr; i++) {
101+
err = pthread_create(&tids[i], NULL, htab_update_fn, &ctx);
102+
if (!ASSERT_OK(err, "pthread_create")) {
103+
ctx.stop = true;
104+
goto reap;
105+
}
106+
}
107+
for (i = 0; i < rd_nr; i++) {
108+
err = pthread_create(&tids[i + wr_nr], NULL, htab_lookup_fn, &ctx);
109+
if (!ASSERT_OK(err, "pthread_create")) {
110+
ctx.stop = true;
111+
goto reap;
112+
}
113+
}
114+
115+
reap:
116+
for (i = 0; i < wr_nr + rd_nr; i++) {
117+
void *ret = NULL;
118+
char desc[32];
119+
120+
if (!tids[i])
121+
continue;
122+
123+
snprintf(desc, sizeof(desc), "thread %u", i + 1);
124+
err = pthread_join(tids[i], &ret);
125+
ASSERT_OK(err, desc);
126+
ASSERT_EQ(ret, NULL, desc);
127+
}
128+
destroy:
129+
htab_lookup__destroy(skel);
130+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#include <linux/bpf.h>
3+
#include <bpf/bpf_helpers.h>
4+
5+
char _license[] SEC("license") = "GPL";
6+
7+
struct {
8+
__uint(type, BPF_MAP_TYPE_HASH);
9+
__uint(max_entries, 64);
10+
__type(key, unsigned long);
11+
__type(value, unsigned long);
12+
__uint(map_flags, BPF_F_NO_PREALLOC);
13+
} htab SEC(".maps");

0 commit comments

Comments
 (0)