]>
Commit | Line | Data |
---|---|---|
5aa5bd14 DB |
1 | /* |
2 | * Testsuite for eBPF maps | |
3 | * | |
4 | * Copyright (c) 2014 PLUMgrid, http://plumgrid.com | |
5 | * Copyright (c) 2016 Facebook | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or | |
8 | * modify it under the terms of version 2 of the GNU General Public | |
9 | * License as published by the Free Software Foundation. | |
10 | */ | |
11 | ||
12 | #include <stdio.h> | |
13 | #include <unistd.h> | |
14 | #include <errno.h> | |
15 | #include <string.h> | |
16 | #include <assert.h> | |
17 | #include <stdlib.h> | |
18 | ||
19 | #include <sys/wait.h> | |
20 | #include <sys/resource.h> | |
21 | ||
22 | #include <linux/bpf.h> | |
23 | ||
10ecc728 | 24 | #include <bpf/bpf.h> |
5aa5bd14 | 25 | #include "bpf_sys.h" |
e00c7b21 | 26 | #include "bpf_util.h" |
5aa5bd14 DB |
27 | |
28 | static int map_flags; | |
29 | ||
30 | static void test_hashmap(int task, void *data) | |
31 | { | |
32 | long long key, next_key, value; | |
33 | int fd; | |
34 | ||
35 | fd = bpf_map_create(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), | |
36 | 2, map_flags); | |
37 | if (fd < 0) { | |
38 | printf("Failed to create hashmap '%s'!\n", strerror(errno)); | |
39 | exit(1); | |
40 | } | |
41 | ||
42 | key = 1; | |
43 | value = 1234; | |
44 | /* Insert key=1 element. */ | |
10ecc728 | 45 | assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); |
5aa5bd14 DB |
46 | |
47 | value = 0; | |
48 | /* BPF_NOEXIST means add new element if it doesn't exist. */ | |
10ecc728 | 49 | assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && |
5aa5bd14 DB |
50 | /* key=1 already exists. */ |
51 | errno == EEXIST); | |
52 | ||
53 | /* -1 is an invalid flag. */ | |
10ecc728 MS |
54 | assert(bpf_map_update_elem(fd, &key, &value, -1) == -1 && |
55 | errno == EINVAL); | |
5aa5bd14 DB |
56 | |
57 | /* Check that key=1 can be found. */ | |
e5ff7c40 | 58 | assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234); |
5aa5bd14 DB |
59 | |
60 | key = 2; | |
61 | /* Check that key=2 is not found. */ | |
e5ff7c40 | 62 | assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT); |
5aa5bd14 DB |
63 | |
64 | /* BPF_EXIST means update existing element. */ | |
10ecc728 | 65 | assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == -1 && |
5aa5bd14 DB |
66 | /* key=2 is not there. */ |
67 | errno == ENOENT); | |
68 | ||
69 | /* Insert key=2 element. */ | |
10ecc728 | 70 | assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0); |
5aa5bd14 DB |
71 | |
72 | /* key=1 and key=2 were inserted, check that key=0 cannot be | |
73 | * inserted due to max_entries limit. | |
74 | */ | |
75 | key = 0; | |
10ecc728 | 76 | assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && |
5aa5bd14 DB |
77 | errno == E2BIG); |
78 | ||
79 | /* Update existing element, though the map is full. */ | |
80 | key = 1; | |
10ecc728 | 81 | assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0); |
5aa5bd14 | 82 | key = 2; |
10ecc728 | 83 | assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); |
5aa5bd14 | 84 | key = 1; |
10ecc728 | 85 | assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); |
5aa5bd14 DB |
86 | |
87 | /* Check that key = 0 doesn't exist. */ | |
88 | key = 0; | |
e58383b8 | 89 | assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT); |
5aa5bd14 DB |
90 | |
91 | /* Iterate over two elements. */ | |
5f155c25 | 92 | assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 && |
5aa5bd14 | 93 | (next_key == 1 || next_key == 2)); |
5f155c25 | 94 | assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 && |
5aa5bd14 | 95 | (next_key == 1 || next_key == 2)); |
5f155c25 | 96 | assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 && |
5aa5bd14 DB |
97 | errno == ENOENT); |
98 | ||
99 | /* Delete both elements. */ | |
100 | key = 1; | |
e58383b8 | 101 | assert(bpf_map_delete_elem(fd, &key) == 0); |
5aa5bd14 | 102 | key = 2; |
e58383b8 MS |
103 | assert(bpf_map_delete_elem(fd, &key) == 0); |
104 | assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT); | |
5aa5bd14 DB |
105 | |
106 | key = 0; | |
107 | /* Check that map is empty. */ | |
5f155c25 | 108 | assert(bpf_map_get_next_key(fd, &key, &next_key) == -1 && |
5aa5bd14 DB |
109 | errno == ENOENT); |
110 | ||
111 | close(fd); | |
112 | } | |
113 | ||
114 | static void test_hashmap_percpu(int task, void *data) | |
115 | { | |
e00c7b21 | 116 | unsigned int nr_cpus = bpf_num_possible_cpus(); |
5aa5bd14 DB |
117 | long long value[nr_cpus]; |
118 | long long key, next_key; | |
119 | int expected_key_mask = 0; | |
120 | int fd, i; | |
121 | ||
122 | fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_HASH, sizeof(key), | |
123 | sizeof(value[0]), 2, map_flags); | |
124 | if (fd < 0) { | |
125 | printf("Failed to create hashmap '%s'!\n", strerror(errno)); | |
126 | exit(1); | |
127 | } | |
128 | ||
129 | for (i = 0; i < nr_cpus; i++) | |
130 | value[i] = i + 100; | |
131 | ||
132 | key = 1; | |
133 | /* Insert key=1 element. */ | |
134 | assert(!(expected_key_mask & key)); | |
10ecc728 | 135 | assert(bpf_map_update_elem(fd, &key, value, BPF_ANY) == 0); |
5aa5bd14 DB |
136 | expected_key_mask |= key; |
137 | ||
138 | /* BPF_NOEXIST means add new element if it doesn't exist. */ | |
10ecc728 | 139 | assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == -1 && |
5aa5bd14 DB |
140 | /* key=1 already exists. */ |
141 | errno == EEXIST); | |
142 | ||
143 | /* -1 is an invalid flag. */ | |
10ecc728 MS |
144 | assert(bpf_map_update_elem(fd, &key, value, -1) == -1 && |
145 | errno == EINVAL); | |
5aa5bd14 DB |
146 | |
147 | /* Check that key=1 can be found. Value could be 0 if the lookup | |
148 | * was run from a different CPU. | |
149 | */ | |
150 | value[0] = 1; | |
e5ff7c40 | 151 | assert(bpf_map_lookup_elem(fd, &key, value) == 0 && value[0] == 100); |
5aa5bd14 DB |
152 | |
153 | key = 2; | |
154 | /* Check that key=2 is not found. */ | |
e5ff7c40 | 155 | assert(bpf_map_lookup_elem(fd, &key, value) == -1 && errno == ENOENT); |
5aa5bd14 DB |
156 | |
157 | /* BPF_EXIST means update existing element. */ | |
10ecc728 | 158 | assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == -1 && |
5aa5bd14 DB |
159 | /* key=2 is not there. */ |
160 | errno == ENOENT); | |
161 | ||
162 | /* Insert key=2 element. */ | |
163 | assert(!(expected_key_mask & key)); | |
10ecc728 | 164 | assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == 0); |
5aa5bd14 DB |
165 | expected_key_mask |= key; |
166 | ||
167 | /* key=1 and key=2 were inserted, check that key=0 cannot be | |
168 | * inserted due to max_entries limit. | |
169 | */ | |
170 | key = 0; | |
10ecc728 | 171 | assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == -1 && |
5aa5bd14 DB |
172 | errno == E2BIG); |
173 | ||
174 | /* Check that key = 0 doesn't exist. */ | |
e58383b8 | 175 | assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT); |
5aa5bd14 DB |
176 | |
177 | /* Iterate over two elements. */ | |
5f155c25 | 178 | while (!bpf_map_get_next_key(fd, &key, &next_key)) { |
5aa5bd14 DB |
179 | assert((expected_key_mask & next_key) == next_key); |
180 | expected_key_mask &= ~next_key; | |
181 | ||
e5ff7c40 | 182 | assert(bpf_map_lookup_elem(fd, &next_key, value) == 0); |
5aa5bd14 DB |
183 | |
184 | for (i = 0; i < nr_cpus; i++) | |
185 | assert(value[i] == i + 100); | |
186 | ||
187 | key = next_key; | |
188 | } | |
189 | assert(errno == ENOENT); | |
190 | ||
191 | /* Update with BPF_EXIST. */ | |
192 | key = 1; | |
10ecc728 | 193 | assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == 0); |
5aa5bd14 DB |
194 | |
195 | /* Delete both elements. */ | |
196 | key = 1; | |
e58383b8 | 197 | assert(bpf_map_delete_elem(fd, &key) == 0); |
5aa5bd14 | 198 | key = 2; |
e58383b8 MS |
199 | assert(bpf_map_delete_elem(fd, &key) == 0); |
200 | assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT); | |
5aa5bd14 DB |
201 | |
202 | key = 0; | |
203 | /* Check that map is empty. */ | |
5f155c25 | 204 | assert(bpf_map_get_next_key(fd, &key, &next_key) == -1 && |
5aa5bd14 DB |
205 | errno == ENOENT); |
206 | ||
207 | close(fd); | |
208 | } | |
209 | ||
210 | static void test_arraymap(int task, void *data) | |
211 | { | |
212 | int key, next_key, fd; | |
213 | long long value; | |
214 | ||
215 | fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value), | |
216 | 2, 0); | |
217 | if (fd < 0) { | |
218 | printf("Failed to create arraymap '%s'!\n", strerror(errno)); | |
219 | exit(1); | |
220 | } | |
221 | ||
222 | key = 1; | |
223 | value = 1234; | |
224 | /* Insert key=1 element. */ | |
10ecc728 | 225 | assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); |
5aa5bd14 DB |
226 | |
227 | value = 0; | |
10ecc728 | 228 | assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && |
5aa5bd14 DB |
229 | errno == EEXIST); |
230 | ||
231 | /* Check that key=1 can be found. */ | |
e5ff7c40 | 232 | assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234); |
5aa5bd14 DB |
233 | |
234 | key = 0; | |
235 | /* Check that key=0 is also found and zero initialized. */ | |
e5ff7c40 | 236 | assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0); |
5aa5bd14 DB |
237 | |
238 | /* key=0 and key=1 were inserted, check that key=2 cannot be inserted | |
239 | * due to max_entries limit. | |
240 | */ | |
241 | key = 2; | |
10ecc728 | 242 | assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == -1 && |
5aa5bd14 DB |
243 | errno == E2BIG); |
244 | ||
245 | /* Check that key = 2 doesn't exist. */ | |
e5ff7c40 | 246 | assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT); |
5aa5bd14 DB |
247 | |
248 | /* Iterate over two elements. */ | |
5f155c25 | 249 | assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 && |
5aa5bd14 | 250 | next_key == 0); |
5f155c25 | 251 | assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 && |
5aa5bd14 | 252 | next_key == 1); |
5f155c25 | 253 | assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 && |
5aa5bd14 DB |
254 | errno == ENOENT); |
255 | ||
256 | /* Delete shouldn't succeed. */ | |
257 | key = 1; | |
e58383b8 | 258 | assert(bpf_map_delete_elem(fd, &key) == -1 && errno == EINVAL); |
5aa5bd14 DB |
259 | |
260 | close(fd); | |
261 | } | |
262 | ||
263 | static void test_arraymap_percpu(int task, void *data) | |
264 | { | |
e00c7b21 | 265 | unsigned int nr_cpus = bpf_num_possible_cpus(); |
5aa5bd14 DB |
266 | int key, next_key, fd, i; |
267 | long values[nr_cpus]; | |
268 | ||
269 | fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key), | |
270 | sizeof(values[0]), 2, 0); | |
271 | if (fd < 0) { | |
272 | printf("Failed to create arraymap '%s'!\n", strerror(errno)); | |
273 | exit(1); | |
274 | } | |
275 | ||
276 | for (i = 0; i < nr_cpus; i++) | |
277 | values[i] = i + 100; | |
278 | ||
279 | key = 1; | |
280 | /* Insert key=1 element. */ | |
10ecc728 | 281 | assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0); |
5aa5bd14 DB |
282 | |
283 | values[0] = 0; | |
10ecc728 | 284 | assert(bpf_map_update_elem(fd, &key, values, BPF_NOEXIST) == -1 && |
5aa5bd14 DB |
285 | errno == EEXIST); |
286 | ||
287 | /* Check that key=1 can be found. */ | |
e5ff7c40 | 288 | assert(bpf_map_lookup_elem(fd, &key, values) == 0 && values[0] == 100); |
5aa5bd14 DB |
289 | |
290 | key = 0; | |
291 | /* Check that key=0 is also found and zero initialized. */ | |
e5ff7c40 | 292 | assert(bpf_map_lookup_elem(fd, &key, values) == 0 && |
5aa5bd14 DB |
293 | values[0] == 0 && values[nr_cpus - 1] == 0); |
294 | ||
295 | /* Check that key=2 cannot be inserted due to max_entries limit. */ | |
296 | key = 2; | |
10ecc728 | 297 | assert(bpf_map_update_elem(fd, &key, values, BPF_EXIST) == -1 && |
5aa5bd14 DB |
298 | errno == E2BIG); |
299 | ||
300 | /* Check that key = 2 doesn't exist. */ | |
e5ff7c40 | 301 | assert(bpf_map_lookup_elem(fd, &key, values) == -1 && errno == ENOENT); |
5aa5bd14 DB |
302 | |
303 | /* Iterate over two elements. */ | |
5f155c25 | 304 | assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 && |
5aa5bd14 | 305 | next_key == 0); |
5f155c25 | 306 | assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 && |
5aa5bd14 | 307 | next_key == 1); |
5f155c25 | 308 | assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 && |
5aa5bd14 DB |
309 | errno == ENOENT); |
310 | ||
311 | /* Delete shouldn't succeed. */ | |
312 | key = 1; | |
e58383b8 | 313 | assert(bpf_map_delete_elem(fd, &key) == -1 && errno == EINVAL); |
5aa5bd14 DB |
314 | |
315 | close(fd); | |
316 | } | |
317 | ||
318 | static void test_arraymap_percpu_many_keys(void) | |
319 | { | |
e00c7b21 | 320 | unsigned int nr_cpus = bpf_num_possible_cpus(); |
5aa5bd14 DB |
321 | unsigned int nr_keys = 20000; |
322 | long values[nr_cpus]; | |
323 | int key, fd, i; | |
324 | ||
325 | fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key), | |
326 | sizeof(values[0]), nr_keys, 0); | |
327 | if (fd < 0) { | |
328 | printf("Failed to create per-cpu arraymap '%s'!\n", | |
329 | strerror(errno)); | |
330 | exit(1); | |
331 | } | |
332 | ||
333 | for (i = 0; i < nr_cpus; i++) | |
334 | values[i] = i + 10; | |
335 | ||
336 | for (key = 0; key < nr_keys; key++) | |
10ecc728 | 337 | assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0); |
5aa5bd14 DB |
338 | |
339 | for (key = 0; key < nr_keys; key++) { | |
340 | for (i = 0; i < nr_cpus; i++) | |
341 | values[i] = 0; | |
342 | ||
e5ff7c40 | 343 | assert(bpf_map_lookup_elem(fd, &key, values) == 0); |
5aa5bd14 DB |
344 | |
345 | for (i = 0; i < nr_cpus; i++) | |
346 | assert(values[i] == i + 10); | |
347 | } | |
348 | ||
349 | close(fd); | |
350 | } | |
351 | ||
352 | #define MAP_SIZE (32 * 1024) | |
353 | ||
354 | static void test_map_large(void) | |
355 | { | |
356 | struct bigkey { | |
357 | int a; | |
358 | char b[116]; | |
359 | long long c; | |
360 | } key; | |
361 | int fd, i, value; | |
362 | ||
363 | fd = bpf_map_create(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), | |
364 | MAP_SIZE, map_flags); | |
365 | if (fd < 0) { | |
366 | printf("Failed to create large map '%s'!\n", strerror(errno)); | |
367 | exit(1); | |
368 | } | |
369 | ||
370 | for (i = 0; i < MAP_SIZE; i++) { | |
371 | key = (struct bigkey) { .c = i }; | |
372 | value = i; | |
373 | ||
10ecc728 | 374 | assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0); |
5aa5bd14 DB |
375 | } |
376 | ||
377 | key.c = -1; | |
10ecc728 | 378 | assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && |
5aa5bd14 DB |
379 | errno == E2BIG); |
380 | ||
381 | /* Iterate through all elements. */ | |
382 | for (i = 0; i < MAP_SIZE; i++) | |
5f155c25 MS |
383 | assert(bpf_map_get_next_key(fd, &key, &key) == 0); |
384 | assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT); | |
5aa5bd14 DB |
385 | |
386 | key.c = 0; | |
e5ff7c40 | 387 | assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0); |
5aa5bd14 | 388 | key.a = 1; |
e5ff7c40 | 389 | assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT); |
5aa5bd14 DB |
390 | |
391 | close(fd); | |
392 | } | |
393 | ||
394 | static void run_parallel(int tasks, void (*fn)(int task, void *data), | |
395 | void *data) | |
396 | { | |
397 | pid_t pid[tasks]; | |
398 | int i; | |
399 | ||
400 | for (i = 0; i < tasks; i++) { | |
401 | pid[i] = fork(); | |
402 | if (pid[i] == 0) { | |
403 | fn(i, data); | |
404 | exit(0); | |
405 | } else if (pid[i] == -1) { | |
406 | printf("Couldn't spawn #%d process!\n", i); | |
407 | exit(1); | |
408 | } | |
409 | } | |
410 | ||
411 | for (i = 0; i < tasks; i++) { | |
412 | int status; | |
413 | ||
414 | assert(waitpid(pid[i], &status, 0) == pid[i]); | |
415 | assert(status == 0); | |
416 | } | |
417 | } | |
418 | ||
419 | static void test_map_stress(void) | |
420 | { | |
421 | run_parallel(100, test_hashmap, NULL); | |
422 | run_parallel(100, test_hashmap_percpu, NULL); | |
423 | ||
424 | run_parallel(100, test_arraymap, NULL); | |
425 | run_parallel(100, test_arraymap_percpu, NULL); | |
426 | } | |
427 | ||
428 | #define TASKS 1024 | |
429 | ||
430 | #define DO_UPDATE 1 | |
431 | #define DO_DELETE 0 | |
432 | ||
433 | static void do_work(int fn, void *data) | |
434 | { | |
435 | int do_update = ((int *)data)[1]; | |
436 | int fd = ((int *)data)[0]; | |
437 | int i, key, value; | |
438 | ||
439 | for (i = fn; i < MAP_SIZE; i += TASKS) { | |
440 | key = value = i; | |
441 | ||
442 | if (do_update) { | |
10ecc728 MS |
443 | assert(bpf_map_update_elem(fd, &key, &value, |
444 | BPF_NOEXIST) == 0); | |
445 | assert(bpf_map_update_elem(fd, &key, &value, | |
446 | BPF_EXIST) == 0); | |
5aa5bd14 | 447 | } else { |
e58383b8 | 448 | assert(bpf_map_delete_elem(fd, &key) == 0); |
5aa5bd14 DB |
449 | } |
450 | } | |
451 | } | |
452 | ||
453 | static void test_map_parallel(void) | |
454 | { | |
455 | int i, fd, key = 0, value = 0; | |
456 | int data[2]; | |
457 | ||
458 | fd = bpf_map_create(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), | |
459 | MAP_SIZE, map_flags); | |
460 | if (fd < 0) { | |
461 | printf("Failed to create map for parallel test '%s'!\n", | |
462 | strerror(errno)); | |
463 | exit(1); | |
464 | } | |
465 | ||
466 | /* Use the same fd in children to add elements to this map: | |
467 | * child_0 adds key=0, key=1024, key=2048, ... | |
468 | * child_1 adds key=1, key=1025, key=2049, ... | |
469 | * child_1023 adds key=1023, ... | |
470 | */ | |
471 | data[0] = fd; | |
472 | data[1] = DO_UPDATE; | |
473 | run_parallel(TASKS, do_work, data); | |
474 | ||
475 | /* Check that key=0 is already there. */ | |
10ecc728 | 476 | assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && |
5aa5bd14 DB |
477 | errno == EEXIST); |
478 | ||
479 | /* Check that all elements were inserted. */ | |
480 | key = -1; | |
481 | for (i = 0; i < MAP_SIZE; i++) | |
5f155c25 MS |
482 | assert(bpf_map_get_next_key(fd, &key, &key) == 0); |
483 | assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT); | |
5aa5bd14 DB |
484 | |
485 | /* Another check for all elements */ | |
486 | for (i = 0; i < MAP_SIZE; i++) { | |
487 | key = MAP_SIZE - i - 1; | |
488 | ||
e5ff7c40 | 489 | assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && |
5aa5bd14 DB |
490 | value == key); |
491 | } | |
492 | ||
493 | /* Now let's delete all elemenets in parallel. */ | |
494 | data[1] = DO_DELETE; | |
495 | run_parallel(TASKS, do_work, data); | |
496 | ||
497 | /* Nothing should be left. */ | |
498 | key = -1; | |
5f155c25 | 499 | assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT); |
5aa5bd14 DB |
500 | } |
501 | ||
502 | static void run_all_tests(void) | |
503 | { | |
504 | test_hashmap(0, NULL); | |
505 | test_hashmap_percpu(0, NULL); | |
506 | ||
507 | test_arraymap(0, NULL); | |
508 | test_arraymap_percpu(0, NULL); | |
509 | ||
510 | test_arraymap_percpu_many_keys(); | |
511 | ||
512 | test_map_large(); | |
513 | test_map_parallel(); | |
514 | test_map_stress(); | |
515 | } | |
516 | ||
517 | int main(void) | |
518 | { | |
519 | struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY }; | |
520 | ||
521 | setrlimit(RLIMIT_MEMLOCK, &rinf); | |
522 | ||
523 | map_flags = 0; | |
524 | run_all_tests(); | |
525 | ||
526 | map_flags = BPF_F_NO_PREALLOC; | |
527 | run_all_tests(); | |
528 | ||
529 | printf("test_maps: OK\n"); | |
530 | return 0; | |
531 | } |