Skip to content

Commit a260a6b

Browse files
yonghong-songkernel-patches-bot
authored andcommitted
selftests/bpf: add arraymap test for bpf_for_each_map_elem() helper
A test is added for arraymap and percpu arraymap. The test also exercises the early return for the helper which does not traverse all elements. $ ./test_progs -n 45 #45/1 hash_map:OK #45/2 array_map:OK #45 for_each:OK Summary: 1/2 PASSED, 0 SKIPPED, 0 FAILED Signed-off-by: Yonghong Song <[email protected]>
1 parent 961ca70 commit a260a6b

File tree

2 files changed

+119
-0
lines changed

2 files changed

+119
-0
lines changed

tools/testing/selftests/bpf/prog_tests/for_each.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <test_progs.h>
44
#include <network_helpers.h>
55
#include "for_each_hash_map_elem.skel.h"
6+
#include "for_each_array_map_elem.skel.h"
67

78
static unsigned int duration;
89

@@ -67,8 +68,65 @@ static void test_hash_map(void)
6768
for_each_hash_map_elem__destroy(skel);
6869
}
6970

71+
static void test_array_map(void)
72+
{
73+
__u32 key, num_cpus, max_entries, retval;
74+
int i, arraymap_fd, percpu_map_fd, err;
75+
struct for_each_array_map_elem *skel;
76+
__u64 *percpu_valbuf = NULL;
77+
__u64 val, expected_total;
78+
79+
skel = for_each_array_map_elem__open_and_load();
80+
if (CHECK(!skel, "for_each_array_map_elem__open_and_load",
81+
"skeleton open_and_load failed\n"))
82+
return;
83+
84+
arraymap_fd = bpf_map__fd(skel->maps.arraymap);
85+
expected_total = 0;
86+
max_entries = bpf_map__max_entries(skel->maps.arraymap);
87+
for (i = 0; i < max_entries; i++) {
88+
key = i;
89+
val = i + 1;
90+
/* skip the last iteration for expected total */
91+
if (i != max_entries - 1)
92+
expected_total += val;
93+
err = bpf_map_update_elem(arraymap_fd, &key, &val, BPF_ANY);
94+
if (CHECK(err, "map_update", "map_update failed\n"))
95+
goto out;
96+
}
97+
98+
num_cpus = bpf_num_possible_cpus();
99+
percpu_map_fd = bpf_map__fd(skel->maps.percpu_map);
100+
percpu_valbuf = malloc(sizeof(__u64) * num_cpus);
101+
if (!ASSERT_OK_PTR(percpu_valbuf, "percpu_valbuf"))
102+
goto out;
103+
104+
key = 0;
105+
for (i = 0; i < num_cpus; i++)
106+
percpu_valbuf[i] = i + 1;
107+
err = bpf_map_update_elem(percpu_map_fd, &key, percpu_valbuf, BPF_ANY);
108+
if (CHECK(err, "percpu_map_update", "map_update failed\n"))
109+
goto out;
110+
111+
err = bpf_prog_test_run(bpf_program__fd(skel->progs.test_pkt_access),
112+
1, &pkt_v4, sizeof(pkt_v4), NULL, NULL,
113+
&retval, &duration);
114+
if (CHECK(err || retval, "ipv4", "err %d errno %d retval %d\n",
115+
err, errno, retval))
116+
goto out;
117+
118+
ASSERT_EQ(skel->bss->arraymap_output, expected_total, "array_output");
119+
ASSERT_EQ(skel->bss->cpu + 1, skel->bss->percpu_val, "percpu_val");
120+
121+
out:
122+
free(percpu_valbuf);
123+
for_each_array_map_elem__destroy(skel);
124+
}
125+
70126
void test_for_each(void)
71127
{
72128
if (test__start_subtest("hash_map"))
73129
test_hash_map();
130+
if (test__start_subtest("array_map"))
131+
test_array_map();
74132
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2021 Facebook */
3+
#include "vmlinux.h"
4+
#include <bpf/bpf_helpers.h>
5+
6+
char _license[] SEC("license") = "GPL";
7+
8+
struct {
9+
__uint(type, BPF_MAP_TYPE_ARRAY);
10+
__uint(max_entries, 3);
11+
__type(key, __u32);
12+
__type(value, __u64);
13+
} arraymap SEC(".maps");
14+
15+
struct {
16+
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
17+
__uint(max_entries, 1);
18+
__type(key, __u32);
19+
__type(value, __u64);
20+
} percpu_map SEC(".maps");
21+
22+
struct callback_ctx {
23+
int output;
24+
};
25+
26+
static __u64
27+
check_array_elem(struct bpf_map *map, __u32 *key, __u64 *val,
28+
struct callback_ctx *data)
29+
{
30+
data->output += *val;
31+
if (*key == 1)
32+
return 1; /* stop the iteration */
33+
return 0;
34+
}
35+
36+
__u32 cpu = 0;
37+
__u64 percpu_val = 0;
38+
39+
static __u64
40+
check_percpu_elem(struct bpf_map *map, __u32 *key, __u64 *val,
41+
struct callback_ctx *data)
42+
{
43+
cpu = bpf_get_smp_processor_id();
44+
percpu_val = *val;
45+
return 0;
46+
}
47+
48+
u32 arraymap_output = 0;
49+
50+
SEC("classifier/")
51+
int test_pkt_access(struct __sk_buff *skb)
52+
{
53+
struct callback_ctx data;
54+
55+
data.output = 0;
56+
bpf_for_each_map_elem(&arraymap, check_array_elem, &data, 0);
57+
arraymap_output = data.output;
58+
59+
bpf_for_each_map_elem(&percpu_map, check_percpu_elem, (void *)0, 0);
60+
return 0;
61+
}

0 commit comments

Comments
 (0)