Skip to content

Commit f3515b5

Browse files
borkmanndavem330
authored andcommitted
bpf: provide a generic macro for percpu values for selftests
To overcome bugs as described and fixed in 89087c4 ("bpf: Fix values type used in test_maps"), provide a generic BPF_DECLARE_PERCPU() and bpf_percpu() accessor macro for all percpu map values used in tests. Declaring variables works as follows (also works for structs): BPF_DECLARE_PERCPU(uint32_t, my_value); They can then be accessed normally as uint32_t type through: bpf_percpu(my_value, <cpu_nr>) For example: bpf_percpu(my_value, 0)++; Implicitly, we make sure that the passed type is allocated and aligned by gcc at least on a 8-byte boundary, so that it works together with the map lookup/update syscall for percpu maps. We use it as a usage example in test_maps, so that others are free to adapt this into their code when necessary. Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: Alexei Starovoitov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 43bcf70 commit f3515b5

File tree

2 files changed

+27
-17
lines changed

2 files changed

+27
-17
lines changed

tools/testing/selftests/bpf/bpf_util.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,11 @@ static inline unsigned int bpf_num_possible_cpus(void)
5454
return possible_cpus;
5555
}
5656

57+
#define __bpf_percpu_val_align __attribute__((__aligned__(8)))
58+
59+
#define BPF_DECLARE_PERCPU(type, name) \
60+
struct { type v; /* padding */ } __bpf_percpu_val_align \
61+
name[bpf_num_possible_cpus()]
62+
#define bpf_percpu(name, cpu) name[(cpu)].v
63+
5764
#endif /* __BPF_UTIL__ */

tools/testing/selftests/bpf/test_maps.c

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -137,20 +137,20 @@ static void test_hashmap_sizes(int task, void *data)
137137
static void test_hashmap_percpu(int task, void *data)
138138
{
139139
unsigned int nr_cpus = bpf_num_possible_cpus();
140-
long long value[nr_cpus];
140+
BPF_DECLARE_PERCPU(long, value);
141141
long long key, next_key, first_key;
142142
int expected_key_mask = 0;
143143
int fd, i;
144144

145145
fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_HASH, sizeof(key),
146-
sizeof(value[0]), 2, map_flags);
146+
sizeof(bpf_percpu(value, 0)), 2, map_flags);
147147
if (fd < 0) {
148148
printf("Failed to create hashmap '%s'!\n", strerror(errno));
149149
exit(1);
150150
}
151151

152152
for (i = 0; i < nr_cpus; i++)
153-
value[i] = i + 100;
153+
bpf_percpu(value, i) = i + 100;
154154

155155
key = 1;
156156
/* Insert key=1 element. */
@@ -170,8 +170,9 @@ static void test_hashmap_percpu(int task, void *data)
170170
/* Check that key=1 can be found. Value could be 0 if the lookup
171171
* was run from a different CPU.
172172
*/
173-
value[0] = 1;
174-
assert(bpf_map_lookup_elem(fd, &key, value) == 0 && value[0] == 100);
173+
bpf_percpu(value, 0) = 1;
174+
assert(bpf_map_lookup_elem(fd, &key, value) == 0 &&
175+
bpf_percpu(value, 0) == 100);
175176

176177
key = 2;
177178
/* Check that key=2 is not found. */
@@ -211,7 +212,7 @@ static void test_hashmap_percpu(int task, void *data)
211212
assert(bpf_map_lookup_elem(fd, &next_key, value) == 0);
212213

213214
for (i = 0; i < nr_cpus; i++)
214-
assert(value[i] == i + 100);
215+
assert(bpf_percpu(value, i) == i + 100);
215216

216217
key = next_key;
217218
}
@@ -296,34 +297,36 @@ static void test_arraymap(int task, void *data)
296297
static void test_arraymap_percpu(int task, void *data)
297298
{
298299
unsigned int nr_cpus = bpf_num_possible_cpus();
300+
BPF_DECLARE_PERCPU(long, values);
299301
int key, next_key, fd, i;
300-
long long values[nr_cpus];
301302

302303
fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
303-
sizeof(values[0]), 2, 0);
304+
sizeof(bpf_percpu(values, 0)), 2, 0);
304305
if (fd < 0) {
305306
printf("Failed to create arraymap '%s'!\n", strerror(errno));
306307
exit(1);
307308
}
308309

309310
for (i = 0; i < nr_cpus; i++)
310-
values[i] = i + 100;
311+
bpf_percpu(values, i) = i + 100;
311312

312313
key = 1;
313314
/* Insert key=1 element. */
314315
assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0);
315316

316-
values[0] = 0;
317+
bpf_percpu(values, 0) = 0;
317318
assert(bpf_map_update_elem(fd, &key, values, BPF_NOEXIST) == -1 &&
318319
errno == EEXIST);
319320

320321
/* Check that key=1 can be found. */
321-
assert(bpf_map_lookup_elem(fd, &key, values) == 0 && values[0] == 100);
322+
assert(bpf_map_lookup_elem(fd, &key, values) == 0 &&
323+
bpf_percpu(values, 0) == 100);
322324

323325
key = 0;
324326
/* Check that key=0 is also found and zero initialized. */
325327
assert(bpf_map_lookup_elem(fd, &key, values) == 0 &&
326-
values[0] == 0 && values[nr_cpus - 1] == 0);
328+
bpf_percpu(values, 0) == 0 &&
329+
bpf_percpu(values, nr_cpus - 1) == 0);
327330

328331
/* Check that key=2 cannot be inserted due to max_entries limit. */
329332
key = 2;
@@ -353,35 +356,35 @@ static void test_arraymap_percpu(int task, void *data)
353356
static void test_arraymap_percpu_many_keys(void)
354357
{
355358
unsigned int nr_cpus = bpf_num_possible_cpus();
359+
BPF_DECLARE_PERCPU(long, values);
356360
/* nr_keys is not too large otherwise the test stresses percpu
357361
* allocator more than anything else
358362
*/
359363
unsigned int nr_keys = 2000;
360-
long long values[nr_cpus];
361364
int key, fd, i;
362365

363366
fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
364-
sizeof(values[0]), nr_keys, 0);
367+
sizeof(bpf_percpu(values, 0)), nr_keys, 0);
365368
if (fd < 0) {
366369
printf("Failed to create per-cpu arraymap '%s'!\n",
367370
strerror(errno));
368371
exit(1);
369372
}
370373

371374
for (i = 0; i < nr_cpus; i++)
372-
values[i] = i + 10;
375+
bpf_percpu(values, i) = i + 10;
373376

374377
for (key = 0; key < nr_keys; key++)
375378
assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0);
376379

377380
for (key = 0; key < nr_keys; key++) {
378381
for (i = 0; i < nr_cpus; i++)
379-
values[i] = 0;
382+
bpf_percpu(values, i) = 0;
380383

381384
assert(bpf_map_lookup_elem(fd, &key, values) == 0);
382385

383386
for (i = 0; i < nr_cpus; i++)
384-
assert(values[i] == i + 10);
387+
assert(bpf_percpu(values, i) == i + 10);
385388
}
386389

387390
close(fd);

0 commit comments

Comments
 (0)