1 // SPDX-License-Identifier: GPL-2.0-only
3 * Testsuite for eBPF maps
5 * Copyright (c) 2014 PLUMgrid, http://plumgrid.com
6 * Copyright (c) 2016 Facebook
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <linux/bpf.h>
23 #include <bpf/libbpf.h>
26 #include "test_maps.h"
27 #include "testing_helpers.h"
31 static struct bpf_map_create_opts map_opts
= { .sz
= sizeof(map_opts
) };
33 static void test_hashmap(unsigned int task
, void *data
)
35 long long key
, next_key
, first_key
, value
;
38 fd
= bpf_map_create(BPF_MAP_TYPE_HASH
, NULL
, sizeof(key
), sizeof(value
), 2, &map_opts
);
40 printf("Failed to create hashmap '%s'!\n", strerror(errno
));
46 /* Insert key=1 element. */
47 assert(bpf_map_update_elem(fd
, &key
, &value
, BPF_ANY
) == 0);
50 /* BPF_NOEXIST means add new element if it doesn't exist. */
51 assert(bpf_map_update_elem(fd
, &key
, &value
, BPF_NOEXIST
) < 0 &&
52 /* key=1 already exists. */
55 /* -1 is an invalid flag. */
56 assert(bpf_map_update_elem(fd
, &key
, &value
, -1) < 0 &&
59 /* Check that key=1 can be found. */
60 assert(bpf_map_lookup_elem(fd
, &key
, &value
) == 0 && value
== 1234);
64 /* Insert key=2 element. */
65 assert(bpf_map_update_elem(fd
, &key
, &value
, BPF_ANY
) == 0);
67 /* Check that key=2 matches the value and delete it */
68 assert(bpf_map_lookup_and_delete_elem(fd
, &key
, &value
) == 0 && value
== 1234);
70 /* Check that key=2 is not found. */
71 assert(bpf_map_lookup_elem(fd
, &key
, &value
) < 0 && errno
== ENOENT
);
73 /* BPF_EXIST means update existing element. */
74 assert(bpf_map_update_elem(fd
, &key
, &value
, BPF_EXIST
) < 0 &&
75 /* key=2 is not there. */
78 /* Insert key=2 element. */
79 assert(bpf_map_update_elem(fd
, &key
, &value
, BPF_NOEXIST
) == 0);
81 /* key=1 and key=2 were inserted, check that key=0 cannot be
82 * inserted due to max_entries limit.
85 assert(bpf_map_update_elem(fd
, &key
, &value
, BPF_NOEXIST
) < 0 &&
88 /* Update existing element, though the map is full. */
90 assert(bpf_map_update_elem(fd
, &key
, &value
, BPF_EXIST
) == 0);
92 assert(bpf_map_update_elem(fd
, &key
, &value
, BPF_ANY
) == 0);
94 assert(bpf_map_update_elem(fd
, &key
, &value
, BPF_NOEXIST
) < 0 &&
97 /* Check that key = 0 doesn't exist. */
99 assert(bpf_map_delete_elem(fd
, &key
) < 0 && errno
== ENOENT
);
101 /* Iterate over two elements. */
102 assert(bpf_map_get_next_key(fd
, NULL
, &first_key
) == 0 &&
103 (first_key
== 1 || first_key
== 2));
104 assert(bpf_map_get_next_key(fd
, &key
, &next_key
) == 0 &&
105 (next_key
== first_key
));
106 assert(bpf_map_get_next_key(fd
, &next_key
, &next_key
) == 0 &&
107 (next_key
== 1 || next_key
== 2) &&
108 (next_key
!= first_key
));
109 assert(bpf_map_get_next_key(fd
, &next_key
, &next_key
) < 0 &&
112 /* Delete both elements. */
114 assert(bpf_map_delete_elem(fd
, &key
) == 0);
116 assert(bpf_map_delete_elem(fd
, &key
) == 0);
117 assert(bpf_map_delete_elem(fd
, &key
) < 0 && errno
== ENOENT
);
120 /* Check that map is empty. */
121 assert(bpf_map_get_next_key(fd
, NULL
, &next_key
) < 0 &&
123 assert(bpf_map_get_next_key(fd
, &key
, &next_key
) < 0 &&
129 static void test_hashmap_sizes(unsigned int task
, void *data
)
133 for (i
= 1; i
<= 512; i
<<= 1)
134 for (j
= 1; j
<= 1 << 18; j
<<= 1) {
135 fd
= bpf_map_create(BPF_MAP_TYPE_HASH
, NULL
, i
, j
, 2, &map_opts
);
139 printf("Failed to create hashmap key=%d value=%d '%s'\n",
140 i
, j
, strerror(errno
));
144 usleep(10); /* give kernel time to destroy */
148 static void test_hashmap_percpu(unsigned int task
, void *data
)
150 unsigned int nr_cpus
= bpf_num_possible_cpus();
151 BPF_DECLARE_PERCPU(long, value
);
152 long long key
, next_key
, first_key
;
153 int expected_key_mask
= 0;
156 fd
= bpf_map_create(BPF_MAP_TYPE_PERCPU_HASH
, NULL
, sizeof(key
),
157 sizeof(bpf_percpu(value
, 0)), 2, &map_opts
);
159 printf("Failed to create hashmap '%s'!\n", strerror(errno
));
163 for (i
= 0; i
< nr_cpus
; i
++)
164 bpf_percpu(value
, i
) = i
+ 100;
167 /* Insert key=1 element. */
168 assert(!(expected_key_mask
& key
));
169 assert(bpf_map_update_elem(fd
, &key
, value
, BPF_ANY
) == 0);
171 /* Lookup and delete elem key=1 and check value. */
172 assert(bpf_map_lookup_and_delete_elem(fd
, &key
, value
) == 0 &&
173 bpf_percpu(value
,0) == 100);
175 for (i
= 0; i
< nr_cpus
; i
++)
176 bpf_percpu(value
,i
) = i
+ 100;
178 /* Insert key=1 element which should not exist. */
179 assert(bpf_map_update_elem(fd
, &key
, value
, BPF_NOEXIST
) == 0);
180 expected_key_mask
|= key
;
182 /* BPF_NOEXIST means add new element if it doesn't exist. */
183 assert(bpf_map_update_elem(fd
, &key
, value
, BPF_NOEXIST
) < 0 &&
184 /* key=1 already exists. */
187 /* -1 is an invalid flag. */
188 assert(bpf_map_update_elem(fd
, &key
, value
, -1) < 0 &&
191 /* Check that key=1 can be found. Value could be 0 if the lookup
192 * was run from a different CPU.
194 bpf_percpu(value
, 0) = 1;
195 assert(bpf_map_lookup_elem(fd
, &key
, value
) == 0 &&
196 bpf_percpu(value
, 0) == 100);
199 /* Check that key=2 is not found. */
200 assert(bpf_map_lookup_elem(fd
, &key
, value
) < 0 && errno
== ENOENT
);
202 /* BPF_EXIST means update existing element. */
203 assert(bpf_map_update_elem(fd
, &key
, value
, BPF_EXIST
) < 0 &&
204 /* key=2 is not there. */
207 /* Insert key=2 element. */
208 assert(!(expected_key_mask
& key
));
209 assert(bpf_map_update_elem(fd
, &key
, value
, BPF_NOEXIST
) == 0);
210 expected_key_mask
|= key
;
212 /* key=1 and key=2 were inserted, check that key=0 cannot be
213 * inserted due to max_entries limit.
216 assert(bpf_map_update_elem(fd
, &key
, value
, BPF_NOEXIST
) < 0 &&
219 /* Check that key = 0 doesn't exist. */
220 assert(bpf_map_delete_elem(fd
, &key
) < 0 && errno
== ENOENT
);
222 /* Iterate over two elements. */
223 assert(bpf_map_get_next_key(fd
, NULL
, &first_key
) == 0 &&
224 ((expected_key_mask
& first_key
) == first_key
));
225 while (!bpf_map_get_next_key(fd
, &key
, &next_key
)) {
227 assert(next_key
== first_key
);
230 assert((expected_key_mask
& next_key
) == next_key
);
231 expected_key_mask
&= ~next_key
;
233 assert(bpf_map_lookup_elem(fd
, &next_key
, value
) == 0);
235 for (i
= 0; i
< nr_cpus
; i
++)
236 assert(bpf_percpu(value
, i
) == i
+ 100);
240 assert(errno
== ENOENT
);
242 /* Update with BPF_EXIST. */
244 assert(bpf_map_update_elem(fd
, &key
, value
, BPF_EXIST
) == 0);
246 /* Delete both elements. */
248 assert(bpf_map_delete_elem(fd
, &key
) == 0);
250 assert(bpf_map_delete_elem(fd
, &key
) == 0);
251 assert(bpf_map_delete_elem(fd
, &key
) < 0 && errno
== ENOENT
);
254 /* Check that map is empty. */
255 assert(bpf_map_get_next_key(fd
, NULL
, &next_key
) < 0 &&
257 assert(bpf_map_get_next_key(fd
, &key
, &next_key
) < 0 &&
264 static int helper_fill_hashmap(int max_entries
)
267 long long key
, value
[VALUE_SIZE
] = {};
269 fd
= bpf_map_create(BPF_MAP_TYPE_HASH
, NULL
, sizeof(key
), sizeof(value
),
270 max_entries
, &map_opts
);
272 "failed to create hashmap",
273 "err: %s, flags: 0x%x\n", strerror(errno
), map_opts
.map_flags
);
275 for (i
= 0; i
< max_entries
; i
++) {
276 key
= i
; value
[0] = key
;
277 ret
= bpf_map_update_elem(fd
, &key
, value
, BPF_NOEXIST
);
279 "can't update hashmap",
280 "err: %s\n", strerror(ret
));
286 static void test_hashmap_walk(unsigned int task
, void *data
)
288 int fd
, i
, max_entries
= 10000;
289 long long key
, value
[VALUE_SIZE
], next_key
;
290 bool next_key_valid
= true;
292 fd
= helper_fill_hashmap(max_entries
);
294 for (i
= 0; bpf_map_get_next_key(fd
, !i
? NULL
: &key
,
295 &next_key
) == 0; i
++) {
297 assert(bpf_map_lookup_elem(fd
, &key
, value
) == 0);
300 assert(i
== max_entries
);
302 assert(bpf_map_get_next_key(fd
, NULL
, &key
) == 0);
303 for (i
= 0; next_key_valid
; i
++) {
304 next_key_valid
= bpf_map_get_next_key(fd
, &key
, &next_key
) == 0;
305 assert(bpf_map_lookup_elem(fd
, &key
, value
) == 0);
307 assert(bpf_map_update_elem(fd
, &key
, value
, BPF_EXIST
) == 0);
311 assert(i
== max_entries
);
313 for (i
= 0; bpf_map_get_next_key(fd
, !i
? NULL
: &key
,
314 &next_key
) == 0; i
++) {
316 assert(bpf_map_lookup_elem(fd
, &key
, value
) == 0);
317 assert(value
[0] - 1 == key
);
320 assert(i
== max_entries
);
324 static void test_hashmap_zero_seed(void)
326 int i
, first
, second
, old_flags
;
327 long long key
, next_first
, next_second
;
329 old_flags
= map_opts
.map_flags
;
330 map_opts
.map_flags
|= BPF_F_ZERO_SEED
;
332 first
= helper_fill_hashmap(3);
333 second
= helper_fill_hashmap(3);
336 void *key_ptr
= !i
? NULL
: &key
;
338 if (bpf_map_get_next_key(first
, key_ptr
, &next_first
) != 0)
341 CHECK(bpf_map_get_next_key(second
, key_ptr
, &next_second
) != 0,
342 "next_key for second map must succeed",
343 "key_ptr: %p", key_ptr
);
344 CHECK(next_first
!= next_second
,
346 "i: %d first: %lld second: %lld\n", i
,
347 next_first
, next_second
);
352 map_opts
.map_flags
= old_flags
;
357 static void test_arraymap(unsigned int task
, void *data
)
359 int key
, next_key
, fd
;
362 fd
= bpf_map_create(BPF_MAP_TYPE_ARRAY
, NULL
, sizeof(key
), sizeof(value
), 2, NULL
);
364 printf("Failed to create arraymap '%s'!\n", strerror(errno
));
370 /* Insert key=1 element. */
371 assert(bpf_map_update_elem(fd
, &key
, &value
, BPF_ANY
) == 0);
374 assert(bpf_map_update_elem(fd
, &key
, &value
, BPF_NOEXIST
) < 0 &&
377 /* Check that key=1 can be found. */
378 assert(bpf_map_lookup_elem(fd
, &key
, &value
) == 0 && value
== 1234);
381 /* Check that key=0 is also found and zero initialized. */
382 assert(bpf_map_lookup_elem(fd
, &key
, &value
) == 0 && value
== 0);
384 /* key=0 and key=1 were inserted, check that key=2 cannot be inserted
385 * due to max_entries limit.
388 assert(bpf_map_update_elem(fd
, &key
, &value
, BPF_EXIST
) < 0 &&
391 /* Check that key = 2 doesn't exist. */
392 assert(bpf_map_lookup_elem(fd
, &key
, &value
) < 0 && errno
== ENOENT
);
394 /* Iterate over two elements. */
395 assert(bpf_map_get_next_key(fd
, NULL
, &next_key
) == 0 &&
397 assert(bpf_map_get_next_key(fd
, &key
, &next_key
) == 0 &&
399 assert(bpf_map_get_next_key(fd
, &next_key
, &next_key
) == 0 &&
401 assert(bpf_map_get_next_key(fd
, &next_key
, &next_key
) < 0 &&
404 /* Delete shouldn't succeed. */
406 assert(bpf_map_delete_elem(fd
, &key
) < 0 && errno
== EINVAL
);
411 static void test_arraymap_percpu(unsigned int task
, void *data
)
413 unsigned int nr_cpus
= bpf_num_possible_cpus();
414 BPF_DECLARE_PERCPU(long, values
);
415 int key
, next_key
, fd
, i
;
417 fd
= bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY
, NULL
, sizeof(key
),
418 sizeof(bpf_percpu(values
, 0)), 2, NULL
);
420 printf("Failed to create arraymap '%s'!\n", strerror(errno
));
424 for (i
= 0; i
< nr_cpus
; i
++)
425 bpf_percpu(values
, i
) = i
+ 100;
428 /* Insert key=1 element. */
429 assert(bpf_map_update_elem(fd
, &key
, values
, BPF_ANY
) == 0);
431 bpf_percpu(values
, 0) = 0;
432 assert(bpf_map_update_elem(fd
, &key
, values
, BPF_NOEXIST
) < 0 &&
435 /* Check that key=1 can be found. */
436 assert(bpf_map_lookup_elem(fd
, &key
, values
) == 0 &&
437 bpf_percpu(values
, 0) == 100);
440 /* Check that key=0 is also found and zero initialized. */
441 assert(bpf_map_lookup_elem(fd
, &key
, values
) == 0 &&
442 bpf_percpu(values
, 0) == 0 &&
443 bpf_percpu(values
, nr_cpus
- 1) == 0);
445 /* Check that key=2 cannot be inserted due to max_entries limit. */
447 assert(bpf_map_update_elem(fd
, &key
, values
, BPF_EXIST
) < 0 &&
450 /* Check that key = 2 doesn't exist. */
451 assert(bpf_map_lookup_elem(fd
, &key
, values
) < 0 && errno
== ENOENT
);
453 /* Iterate over two elements. */
454 assert(bpf_map_get_next_key(fd
, NULL
, &next_key
) == 0 &&
456 assert(bpf_map_get_next_key(fd
, &key
, &next_key
) == 0 &&
458 assert(bpf_map_get_next_key(fd
, &next_key
, &next_key
) == 0 &&
460 assert(bpf_map_get_next_key(fd
, &next_key
, &next_key
) < 0 &&
463 /* Delete shouldn't succeed. */
465 assert(bpf_map_delete_elem(fd
, &key
) < 0 && errno
== EINVAL
);
470 static void test_arraymap_percpu_many_keys(void)
472 unsigned int nr_cpus
= bpf_num_possible_cpus();
473 BPF_DECLARE_PERCPU(long, values
);
474 /* nr_keys is not too large otherwise the test stresses percpu
475 * allocator more than anything else
477 unsigned int nr_keys
= 2000;
480 fd
= bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY
, NULL
, sizeof(key
),
481 sizeof(bpf_percpu(values
, 0)), nr_keys
, NULL
);
483 printf("Failed to create per-cpu arraymap '%s'!\n",
488 for (i
= 0; i
< nr_cpus
; i
++)
489 bpf_percpu(values
, i
) = i
+ 10;
491 for (key
= 0; key
< nr_keys
; key
++)
492 assert(bpf_map_update_elem(fd
, &key
, values
, BPF_ANY
) == 0);
494 for (key
= 0; key
< nr_keys
; key
++) {
495 for (i
= 0; i
< nr_cpus
; i
++)
496 bpf_percpu(values
, i
) = 0;
498 assert(bpf_map_lookup_elem(fd
, &key
, values
) == 0);
500 for (i
= 0; i
< nr_cpus
; i
++)
501 assert(bpf_percpu(values
, i
) == i
+ 10);
507 static void test_devmap(unsigned int task
, void *data
)
512 fd
= bpf_map_create(BPF_MAP_TYPE_DEVMAP
, NULL
, sizeof(key
), sizeof(value
), 2, NULL
);
514 printf("Failed to create devmap '%s'!\n", strerror(errno
));
521 static void test_devmap_hash(unsigned int task
, void *data
)
526 fd
= bpf_map_create(BPF_MAP_TYPE_DEVMAP_HASH
, NULL
, sizeof(key
), sizeof(value
), 2, NULL
);
528 printf("Failed to create devmap_hash '%s'!\n", strerror(errno
));
535 static void test_queuemap(unsigned int task
, void *data
)
537 const int MAP_SIZE
= 32;
538 __u32 vals
[MAP_SIZE
+ MAP_SIZE
/2], val
;
541 /* Fill test values to be used */
542 for (i
= 0; i
< MAP_SIZE
+ MAP_SIZE
/2; i
++)
545 /* Invalid key size */
546 fd
= bpf_map_create(BPF_MAP_TYPE_QUEUE
, NULL
, 4, sizeof(val
), MAP_SIZE
, &map_opts
);
547 assert(fd
< 0 && errno
== EINVAL
);
549 fd
= bpf_map_create(BPF_MAP_TYPE_QUEUE
, NULL
, 0, sizeof(val
), MAP_SIZE
, &map_opts
);
550 /* Queue map does not support BPF_F_NO_PREALLOC */
551 if (map_opts
.map_flags
& BPF_F_NO_PREALLOC
) {
552 assert(fd
< 0 && errno
== EINVAL
);
556 printf("Failed to create queuemap '%s'!\n", strerror(errno
));
560 /* Push MAP_SIZE elements */
561 for (i
= 0; i
< MAP_SIZE
; i
++)
562 assert(bpf_map_update_elem(fd
, NULL
, &vals
[i
], 0) == 0);
564 /* Check that element cannot be pushed due to max_entries limit */
565 assert(bpf_map_update_elem(fd
, NULL
, &val
, 0) < 0 &&
569 assert(bpf_map_lookup_elem(fd
, NULL
, &val
) == 0 && val
== vals
[0]);
571 /* Replace half elements */
572 for (i
= MAP_SIZE
; i
< MAP_SIZE
+ MAP_SIZE
/2; i
++)
573 assert(bpf_map_update_elem(fd
, NULL
, &vals
[i
], BPF_EXIST
) == 0);
575 /* Pop all elements */
576 for (i
= MAP_SIZE
/2; i
< MAP_SIZE
+ MAP_SIZE
/2; i
++)
577 assert(bpf_map_lookup_and_delete_elem(fd
, NULL
, &val
) == 0 &&
580 /* Check that there are not elements left */
581 assert(bpf_map_lookup_and_delete_elem(fd
, NULL
, &val
) < 0 &&
584 /* Check that non supported functions set errno to EINVAL */
585 assert(bpf_map_delete_elem(fd
, NULL
) < 0 && errno
== EINVAL
);
586 assert(bpf_map_get_next_key(fd
, NULL
, NULL
) < 0 && errno
== EINVAL
);
591 static void test_stackmap(unsigned int task
, void *data
)
593 const int MAP_SIZE
= 32;
594 __u32 vals
[MAP_SIZE
+ MAP_SIZE
/2], val
;
597 /* Fill test values to be used */
598 for (i
= 0; i
< MAP_SIZE
+ MAP_SIZE
/2; i
++)
601 /* Invalid key size */
602 fd
= bpf_map_create(BPF_MAP_TYPE_STACK
, NULL
, 4, sizeof(val
), MAP_SIZE
, &map_opts
);
603 assert(fd
< 0 && errno
== EINVAL
);
605 fd
= bpf_map_create(BPF_MAP_TYPE_STACK
, NULL
, 0, sizeof(val
), MAP_SIZE
, &map_opts
);
606 /* Stack map does not support BPF_F_NO_PREALLOC */
607 if (map_opts
.map_flags
& BPF_F_NO_PREALLOC
) {
608 assert(fd
< 0 && errno
== EINVAL
);
612 printf("Failed to create stackmap '%s'!\n", strerror(errno
));
616 /* Push MAP_SIZE elements */
617 for (i
= 0; i
< MAP_SIZE
; i
++)
618 assert(bpf_map_update_elem(fd
, NULL
, &vals
[i
], 0) == 0);
620 /* Check that element cannot be pushed due to max_entries limit */
621 assert(bpf_map_update_elem(fd
, NULL
, &val
, 0) < 0 &&
625 assert(bpf_map_lookup_elem(fd
, NULL
, &val
) == 0 && val
== vals
[i
- 1]);
627 /* Replace half elements */
628 for (i
= MAP_SIZE
; i
< MAP_SIZE
+ MAP_SIZE
/2; i
++)
629 assert(bpf_map_update_elem(fd
, NULL
, &vals
[i
], BPF_EXIST
) == 0);
631 /* Pop all elements */
632 for (i
= MAP_SIZE
+ MAP_SIZE
/2 - 1; i
>= MAP_SIZE
/2; i
--)
633 assert(bpf_map_lookup_and_delete_elem(fd
, NULL
, &val
) == 0 &&
636 /* Check that there are not elements left */
637 assert(bpf_map_lookup_and_delete_elem(fd
, NULL
, &val
) < 0 &&
640 /* Check that non supported functions set errno to EINVAL */
641 assert(bpf_map_delete_elem(fd
, NULL
) < 0 && errno
== EINVAL
);
642 assert(bpf_map_get_next_key(fd
, NULL
, NULL
) < 0 && errno
== EINVAL
);
647 #include <sys/ioctl.h>
648 #include <arpa/inet.h>
649 #include <sys/select.h>
650 #include <linux/err.h>
651 #define SOCKMAP_PARSE_PROG "./sockmap_parse_prog.bpf.o"
652 #define SOCKMAP_VERDICT_PROG "./sockmap_verdict_prog.bpf.o"
653 #define SOCKMAP_TCP_MSG_PROG "./sockmap_tcp_msg_prog.bpf.o"
654 static void test_sockmap(unsigned int tasks
, void *data
)
656 struct bpf_map
*bpf_map_rx
, *bpf_map_tx
, *bpf_map_msg
, *bpf_map_break
;
657 int map_fd_msg
= 0, map_fd_rx
= 0, map_fd_tx
= 0, map_fd_break
;
658 struct bpf_object
*parse_obj
, *verdict_obj
, *msg_obj
;
659 int ports
[] = {50200, 50201, 50202, 50204};
660 int err
, i
, fd
, udp
, sfd
[6] = {0xdeadbeef};
661 u8 buf
[20] = {0x0, 0x5, 0x3, 0x2, 0x1, 0x0};
662 int parse_prog
, verdict_prog
, msg_prog
;
663 struct sockaddr_in addr
;
664 int one
= 1, s
, sc
, rc
;
670 /* Create some sockets to use with sockmap */
671 for (i
= 0; i
< 2; i
++) {
672 sfd
[i
] = socket(AF_INET
, SOCK_STREAM
, 0);
675 err
= setsockopt(sfd
[i
], SOL_SOCKET
, SO_REUSEADDR
,
676 (char *)&one
, sizeof(one
));
678 printf("failed to setsockopt\n");
681 err
= ioctl(sfd
[i
], FIONBIO
, (char *)&one
);
683 printf("failed to ioctl\n");
686 memset(&addr
, 0, sizeof(struct sockaddr_in
));
687 addr
.sin_family
= AF_INET
;
688 addr
.sin_addr
.s_addr
= inet_addr("127.0.0.1");
689 addr
.sin_port
= htons(ports
[i
]);
690 err
= bind(sfd
[i
], (struct sockaddr
*)&addr
, sizeof(addr
));
692 printf("failed to bind: err %i: %i:%i\n",
696 err
= listen(sfd
[i
], 32);
698 printf("failed to listen\n");
703 for (i
= 2; i
< 4; i
++) {
704 sfd
[i
] = socket(AF_INET
, SOCK_STREAM
, 0);
707 err
= setsockopt(sfd
[i
], SOL_SOCKET
, SO_REUSEADDR
,
708 (char *)&one
, sizeof(one
));
710 printf("set sock opt\n");
713 memset(&addr
, 0, sizeof(struct sockaddr_in
));
714 addr
.sin_family
= AF_INET
;
715 addr
.sin_addr
.s_addr
= inet_addr("127.0.0.1");
716 addr
.sin_port
= htons(ports
[i
- 2]);
717 err
= connect(sfd
[i
], (struct sockaddr
*)&addr
, sizeof(addr
));
719 printf("failed to connect\n");
725 for (i
= 4; i
< 6; i
++) {
726 sfd
[i
] = accept(sfd
[i
- 4], NULL
, NULL
);
728 printf("accept failed\n");
733 /* Test sockmap with connected sockets */
734 fd
= bpf_map_create(BPF_MAP_TYPE_SOCKMAP
, NULL
,
735 sizeof(key
), sizeof(value
),
738 if (!libbpf_probe_bpf_map_type(BPF_MAP_TYPE_SOCKMAP
, NULL
)) {
739 printf("%s SKIP (unsupported map type BPF_MAP_TYPE_SOCKMAP)\n",
742 for (i
= 0; i
< 6; i
++)
747 printf("Failed to create sockmap %i\n", fd
);
751 /* Test update with unsupported UDP socket */
752 udp
= socket(AF_INET
, SOCK_DGRAM
, 0);
754 err
= bpf_map_update_elem(fd
, &i
, &udp
, BPF_ANY
);
756 printf("Failed socket update SOCK_DGRAM '%i:%i'\n",
762 /* Test update without programs */
763 for (i
= 0; i
< 6; i
++) {
764 err
= bpf_map_update_elem(fd
, &i
, &sfd
[i
], BPF_ANY
);
766 printf("Failed noprog update sockmap '%i:%i'\n",
772 /* Test attaching/detaching bad fds */
773 err
= bpf_prog_attach(-1, fd
, BPF_SK_SKB_STREAM_PARSER
, 0);
775 printf("Failed invalid parser prog attach\n");
779 err
= bpf_prog_attach(-1, fd
, BPF_SK_SKB_STREAM_VERDICT
, 0);
781 printf("Failed invalid verdict prog attach\n");
785 err
= bpf_prog_attach(-1, fd
, BPF_SK_MSG_VERDICT
, 0);
787 printf("Failed invalid msg verdict prog attach\n");
791 err
= bpf_prog_attach(-1, fd
, __MAX_BPF_ATTACH_TYPE
, 0);
793 printf("Failed unknown prog attach\n");
797 err
= bpf_prog_detach(fd
, BPF_SK_SKB_STREAM_PARSER
);
799 printf("Failed empty parser prog detach\n");
803 err
= bpf_prog_detach(fd
, BPF_SK_SKB_STREAM_VERDICT
);
805 printf("Failed empty verdict prog detach\n");
809 err
= bpf_prog_detach(fd
, BPF_SK_MSG_VERDICT
);
811 printf("Failed empty msg verdict prog detach\n");
815 err
= bpf_prog_detach(fd
, __MAX_BPF_ATTACH_TYPE
);
817 printf("Detach invalid prog successful\n");
821 /* Load SK_SKB program and Attach */
822 err
= bpf_prog_test_load(SOCKMAP_PARSE_PROG
,
823 BPF_PROG_TYPE_SK_SKB
, &parse_obj
, &parse_prog
);
825 printf("Failed to load SK_SKB parse prog\n");
829 err
= bpf_prog_test_load(SOCKMAP_TCP_MSG_PROG
,
830 BPF_PROG_TYPE_SK_MSG
, &msg_obj
, &msg_prog
);
832 printf("Failed to load SK_SKB msg prog\n");
836 err
= bpf_prog_test_load(SOCKMAP_VERDICT_PROG
,
837 BPF_PROG_TYPE_SK_SKB
, &verdict_obj
, &verdict_prog
);
839 printf("Failed to load SK_SKB verdict prog\n");
843 bpf_map_rx
= bpf_object__find_map_by_name(verdict_obj
, "sock_map_rx");
845 printf("Failed to load map rx from verdict prog\n");
849 map_fd_rx
= bpf_map__fd(bpf_map_rx
);
851 printf("Failed to get map rx fd\n");
855 bpf_map_tx
= bpf_object__find_map_by_name(verdict_obj
, "sock_map_tx");
857 printf("Failed to load map tx from verdict prog\n");
861 map_fd_tx
= bpf_map__fd(bpf_map_tx
);
863 printf("Failed to get map tx fd\n");
867 bpf_map_msg
= bpf_object__find_map_by_name(verdict_obj
, "sock_map_msg");
869 printf("Failed to load map msg from msg_verdict prog\n");
873 map_fd_msg
= bpf_map__fd(bpf_map_msg
);
874 if (map_fd_msg
< 0) {
875 printf("Failed to get map msg fd\n");
879 bpf_map_break
= bpf_object__find_map_by_name(verdict_obj
, "sock_map_break");
880 if (!bpf_map_break
) {
881 printf("Failed to load map tx from verdict prog\n");
885 map_fd_break
= bpf_map__fd(bpf_map_break
);
886 if (map_fd_break
< 0) {
887 printf("Failed to get map tx fd\n");
891 err
= bpf_prog_attach(parse_prog
, map_fd_break
,
892 BPF_SK_SKB_STREAM_PARSER
, 0);
894 printf("Allowed attaching SK_SKB program to invalid map\n");
898 err
= bpf_prog_attach(parse_prog
, map_fd_rx
,
899 BPF_SK_SKB_STREAM_PARSER
, 0);
901 printf("Failed stream parser bpf prog attach\n");
905 err
= bpf_prog_attach(verdict_prog
, map_fd_rx
,
906 BPF_SK_SKB_STREAM_VERDICT
, 0);
908 printf("Failed stream verdict bpf prog attach\n");
912 err
= bpf_prog_attach(msg_prog
, map_fd_msg
, BPF_SK_MSG_VERDICT
, 0);
914 printf("Failed msg verdict bpf prog attach\n");
918 err
= bpf_prog_attach(verdict_prog
, map_fd_rx
,
919 __MAX_BPF_ATTACH_TYPE
, 0);
921 printf("Attached unknown bpf prog\n");
925 /* Test map update elem afterwards fd lives in fd and map_fd */
926 for (i
= 2; i
< 6; i
++) {
927 err
= bpf_map_update_elem(map_fd_rx
, &i
, &sfd
[i
], BPF_ANY
);
929 printf("Failed map_fd_rx update sockmap %i '%i:%i'\n",
933 err
= bpf_map_update_elem(map_fd_tx
, &i
, &sfd
[i
], BPF_ANY
);
935 printf("Failed map_fd_tx update sockmap %i '%i:%i'\n",
941 /* Test map delete elem and remove send/recv sockets */
942 for (i
= 2; i
< 4; i
++) {
943 err
= bpf_map_delete_elem(map_fd_rx
, &i
);
945 printf("Failed delete sockmap rx %i '%i:%i'\n",
949 err
= bpf_map_delete_elem(map_fd_tx
, &i
);
951 printf("Failed delete sockmap tx %i '%i:%i'\n",
957 /* Put sfd[2] (sending fd below) into msg map to test sendmsg bpf */
959 err
= bpf_map_update_elem(map_fd_msg
, &i
, &sfd
[2], BPF_ANY
);
961 printf("Failed map_fd_msg update sockmap %i\n", err
);
965 /* Test map send/recv */
966 for (i
= 0; i
< 2; i
++) {
969 sc
= send(sfd
[2], buf
, 20, 0);
971 printf("Failed sockmap send\n");
979 s
= select(sfd
[3] + 1, &w
, NULL
, NULL
, &to
);
981 perror("Failed sockmap select()");
984 printf("Failed sockmap unexpected timeout\n");
988 if (!FD_ISSET(sfd
[3], &w
)) {
989 printf("Failed sockmap select/recv\n");
993 rc
= recv(sfd
[3], buf
, sizeof(buf
), 0);
995 printf("Failed sockmap recv\n");
1000 /* Negative null entry lookup from datapath should be dropped */
1003 sc
= send(sfd
[2], buf
, 20, 0);
1005 printf("Failed sockmap send\n");
1009 /* Push fd into same slot */
1011 err
= bpf_map_update_elem(fd
, &i
, &sfd
[i
], BPF_NOEXIST
);
1013 printf("Failed allowed sockmap dup slot BPF_NOEXIST\n");
1017 err
= bpf_map_update_elem(fd
, &i
, &sfd
[i
], BPF_ANY
);
1019 printf("Failed sockmap update new slot BPF_ANY\n");
1023 err
= bpf_map_update_elem(fd
, &i
, &sfd
[i
], BPF_EXIST
);
1025 printf("Failed sockmap update new slot BPF_EXIST\n");
1029 /* Delete the elems without programs */
1030 for (i
= 2; i
< 6; i
++) {
1031 err
= bpf_map_delete_elem(fd
, &i
);
1033 printf("Failed delete sockmap %i '%i:%i'\n",
1038 /* Test having multiple maps open and set with programs on same fds */
1039 err
= bpf_prog_attach(parse_prog
, fd
,
1040 BPF_SK_SKB_STREAM_PARSER
, 0);
1042 printf("Failed fd bpf parse prog attach\n");
1045 err
= bpf_prog_attach(verdict_prog
, fd
,
1046 BPF_SK_SKB_STREAM_VERDICT
, 0);
1048 printf("Failed fd bpf verdict prog attach\n");
1052 for (i
= 4; i
< 6; i
++) {
1053 err
= bpf_map_update_elem(fd
, &i
, &sfd
[i
], BPF_ANY
);
1055 printf("Failed allowed duplicate programs in update ANY sockmap %i '%i:%i'\n",
1059 err
= bpf_map_update_elem(fd
, &i
, &sfd
[i
], BPF_NOEXIST
);
1061 printf("Failed allowed duplicate program in update NOEXIST sockmap %i '%i:%i'\n",
1065 err
= bpf_map_update_elem(fd
, &i
, &sfd
[i
], BPF_EXIST
);
1067 printf("Failed allowed duplicate program in update EXIST sockmap %i '%i:%i'\n",
1073 /* Test tasks number of forked operations */
1074 for (i
= 0; i
< tasks
; i
++) {
1077 for (i
= 0; i
< 6; i
++) {
1078 bpf_map_delete_elem(map_fd_tx
, &i
);
1079 bpf_map_delete_elem(map_fd_rx
, &i
);
1080 bpf_map_update_elem(map_fd_tx
, &i
,
1082 bpf_map_update_elem(map_fd_rx
, &i
,
1086 } else if (pid
[i
] == -1) {
1087 printf("Couldn't spawn #%d process!\n", i
);
1092 for (i
= 0; i
< tasks
; i
++) {
1095 assert(waitpid(pid
[i
], &status
, 0) == pid
[i
]);
1096 assert(status
== 0);
1099 err
= bpf_prog_detach2(parse_prog
, map_fd_rx
, __MAX_BPF_ATTACH_TYPE
);
1101 printf("Detached an invalid prog type.\n");
1105 err
= bpf_prog_detach2(parse_prog
, map_fd_rx
, BPF_SK_SKB_STREAM_PARSER
);
1107 printf("Failed parser prog detach\n");
1111 err
= bpf_prog_detach2(verdict_prog
, map_fd_rx
, BPF_SK_SKB_STREAM_VERDICT
);
1113 printf("Failed parser prog detach\n");
1117 /* Test map close sockets and empty maps */
1118 for (i
= 0; i
< 6; i
++) {
1119 bpf_map_delete_elem(map_fd_tx
, &i
);
1120 bpf_map_delete_elem(map_fd_rx
, &i
);
1125 bpf_object__close(parse_obj
);
1126 bpf_object__close(msg_obj
);
1127 bpf_object__close(verdict_obj
);
1130 for (i
= 0; i
< 6; i
++)
1132 printf("Failed to create sockmap '%i:%s'!\n", i
, strerror(errno
));
1135 for (i
= 0; i
< 6; i
++) {
1137 bpf_map_delete_elem(map_fd_tx
, &i
);
1139 bpf_map_delete_elem(map_fd_rx
, &i
);
1146 #define MAPINMAP_PROG "./test_map_in_map.bpf.o"
1147 #define MAPINMAP_INVALID_PROG "./test_map_in_map_invalid.bpf.o"
1148 static void test_map_in_map(void)
1150 struct bpf_object
*obj
;
1151 struct bpf_map
*map
;
1152 int mim_fd
, fd
, err
;
1154 struct bpf_map_info info
= {};
1155 __u32 len
= sizeof(info
);
1157 libbpf_print_fn_t old_print_fn
;
1159 obj
= bpf_object__open(MAPINMAP_PROG
);
1161 fd
= bpf_map_create(BPF_MAP_TYPE_HASH
, NULL
, sizeof(int), sizeof(int), 2, NULL
);
1163 printf("Failed to create hashmap '%s'!\n", strerror(errno
));
1167 map
= bpf_object__find_map_by_name(obj
, "mim_array");
1169 printf("Failed to load array of maps from test prog\n");
1170 goto out_map_in_map
;
1172 err
= bpf_map__set_inner_map_fd(map
, fd
);
1174 printf("Failed to set inner_map_fd for array of maps\n");
1175 goto out_map_in_map
;
1178 map
= bpf_object__find_map_by_name(obj
, "mim_hash");
1180 printf("Failed to load hash of maps from test prog\n");
1181 goto out_map_in_map
;
1183 err
= bpf_map__set_inner_map_fd(map
, fd
);
1185 printf("Failed to set inner_map_fd for hash of maps\n");
1186 goto out_map_in_map
;
1189 err
= bpf_object__load(obj
);
1191 printf("Failed to load test prog\n");
1192 goto out_map_in_map
;
1195 map
= bpf_object__find_map_by_name(obj
, "mim_array");
1197 printf("Failed to load array of maps from test prog\n");
1198 goto out_map_in_map
;
1200 mim_fd
= bpf_map__fd(map
);
1202 printf("Failed to get descriptor for array of maps\n");
1203 goto out_map_in_map
;
1206 err
= bpf_map_update_elem(mim_fd
, &pos
, &fd
, 0);
1208 printf("Failed to update array of maps\n");
1209 goto out_map_in_map
;
1212 map
= bpf_object__find_map_by_name(obj
, "mim_hash");
1214 printf("Failed to load hash of maps from test prog\n");
1215 goto out_map_in_map
;
1217 mim_fd
= bpf_map__fd(map
);
1219 printf("Failed to get descriptor for hash of maps\n");
1220 goto out_map_in_map
;
1223 err
= bpf_map_update_elem(mim_fd
, &pos
, &fd
, 0);
1225 printf("Failed to update hash of maps\n");
1226 goto out_map_in_map
;
1231 bpf_object__close(obj
);
1233 /* Test that failing bpf_object__create_map() destroys the inner map */
1234 obj
= bpf_object__open(MAPINMAP_INVALID_PROG
);
1235 err
= libbpf_get_error(obj
);
1237 printf("Failed to load %s program: %d %d",
1238 MAPINMAP_INVALID_PROG
, err
, errno
);
1239 goto out_map_in_map
;
1242 map
= bpf_object__find_map_by_name(obj
, "mim");
1244 printf("Failed to load array of maps from test prog\n");
1245 goto out_map_in_map
;
1248 old_print_fn
= libbpf_set_print(NULL
);
1250 err
= bpf_object__load(obj
);
1252 printf("Loading obj supposed to fail\n");
1253 goto out_map_in_map
;
1256 libbpf_set_print(old_print_fn
);
1258 /* Iterate over all maps to check whether the internal map
1259 * ("mim.internal") has been destroyed.
1262 err
= bpf_map_get_next_id(id
, &id
);
1264 if (errno
== ENOENT
)
1266 printf("Failed to get next map: %d", errno
);
1267 goto out_map_in_map
;
1270 fd
= bpf_map_get_fd_by_id(id
);
1272 if (errno
== ENOENT
)
1274 printf("Failed to get map by id %u: %d", id
, errno
);
1275 goto out_map_in_map
;
1278 err
= bpf_map_get_info_by_fd(fd
, &info
, &len
);
1280 printf("Failed to get map info by fd %d: %d", fd
,
1282 goto out_map_in_map
;
1285 if (!strcmp(info
.name
, "mim.inner")) {
1286 printf("Inner map mim.inner was not destroyed\n");
1287 goto out_map_in_map
;
1293 bpf_object__close(obj
);
1302 #define MAP_SIZE (32 * 1024)
1304 static void test_map_large(void)
1314 fd
= bpf_map_create(BPF_MAP_TYPE_HASH
, NULL
, sizeof(key
), sizeof(value
),
1315 MAP_SIZE
, &map_opts
);
1317 printf("Failed to create large map '%s'!\n", strerror(errno
));
1321 for (i
= 0; i
< MAP_SIZE
; i
++) {
1322 key
= (struct bigkey
) { .c
= i
};
1325 assert(bpf_map_update_elem(fd
, &key
, &value
, BPF_NOEXIST
) == 0);
1329 assert(bpf_map_update_elem(fd
, &key
, &value
, BPF_NOEXIST
) < 0 &&
1332 /* Iterate through all elements. */
1333 assert(bpf_map_get_next_key(fd
, NULL
, &key
) == 0);
1335 for (i
= 0; i
< MAP_SIZE
; i
++)
1336 assert(bpf_map_get_next_key(fd
, &key
, &key
) == 0);
1337 assert(bpf_map_get_next_key(fd
, &key
, &key
) < 0 && errno
== ENOENT
);
1340 assert(bpf_map_lookup_elem(fd
, &key
, &value
) == 0 && value
== 0);
1342 assert(bpf_map_lookup_elem(fd
, &key
, &value
) < 0 && errno
== ENOENT
);
1347 #define run_parallel(N, FN, DATA) \
1348 printf("Fork %u tasks to '" #FN "'\n", N); \
1349 __run_parallel(N, FN, DATA)
1351 static void __run_parallel(unsigned int tasks
,
1352 void (*fn
)(unsigned int task
, void *data
),
1360 for (i
= 0; i
< tasks
; i
++) {
1365 } else if (pid
[i
] == -1) {
1366 printf("Couldn't spawn #%d process!\n", i
);
1371 for (i
= 0; i
< tasks
; i
++) {
1374 assert(waitpid(pid
[i
], &status
, 0) == pid
[i
]);
1375 assert(status
== 0);
1379 static void test_map_stress(void)
1381 run_parallel(100, test_hashmap_walk
, NULL
);
1382 run_parallel(100, test_hashmap
, NULL
);
1383 run_parallel(100, test_hashmap_percpu
, NULL
);
1384 run_parallel(100, test_hashmap_sizes
, NULL
);
1386 run_parallel(100, test_arraymap
, NULL
);
1387 run_parallel(100, test_arraymap_percpu
, NULL
);
1395 #define MAP_RETRIES 20
1396 #define MAX_DELAY_US 50000
1397 #define MIN_DELAY_RANGE_US 5000
1399 static bool retry_for_again_or_busy(int err
)
1401 return (err
== EAGAIN
|| err
== EBUSY
);
1404 int map_update_retriable(int map_fd
, const void *key
, const void *value
, int flags
, int attempts
,
1405 retry_for_error_fn need_retry
)
1407 int delay
= rand() % MIN_DELAY_RANGE_US
;
1409 while (bpf_map_update_elem(map_fd
, key
, value
, flags
)) {
1410 if (!attempts
|| !need_retry(errno
))
1413 if (delay
<= MAX_DELAY_US
/ 2)
1423 static int map_delete_retriable(int map_fd
, const void *key
, int attempts
)
1425 int delay
= rand() % MIN_DELAY_RANGE_US
;
1427 while (bpf_map_delete_elem(map_fd
, key
)) {
1428 if (!attempts
|| (errno
!= EAGAIN
&& errno
!= EBUSY
))
1431 if (delay
<= MAX_DELAY_US
/ 2)
1441 static void test_update_delete(unsigned int fn
, void *data
)
1443 int do_update
= ((int *)data
)[1];
1444 int fd
= ((int *)data
)[0];
1445 int i
, key
, value
, err
;
1448 test_hashmap_walk(fn
, NULL
);
1449 for (i
= fn
; i
< MAP_SIZE
; i
+= TASKS
) {
1453 err
= map_update_retriable(fd
, &key
, &value
, BPF_NOEXIST
, MAP_RETRIES
,
1454 retry_for_again_or_busy
);
1456 printf("error %d %d\n", err
, errno
);
1458 err
= map_update_retriable(fd
, &key
, &value
, BPF_EXIST
, MAP_RETRIES
,
1459 retry_for_again_or_busy
);
1461 printf("error %d %d\n", err
, errno
);
1464 err
= map_delete_retriable(fd
, &key
, MAP_RETRIES
);
1466 printf("error %d %d\n", err
, errno
);
1472 static void test_map_parallel(void)
1474 int i
, fd
, key
= 0, value
= 0, j
= 0;
1477 fd
= bpf_map_create(BPF_MAP_TYPE_HASH
, NULL
, sizeof(key
), sizeof(value
),
1478 MAP_SIZE
, &map_opts
);
1480 printf("Failed to create map for parallel test '%s'!\n",
1486 /* Use the same fd in children to add elements to this map:
1487 * child_0 adds key=0, key=1024, key=2048, ...
1488 * child_1 adds key=1, key=1025, key=2049, ...
1489 * child_1023 adds key=1023, ...
1492 data
[1] = DO_UPDATE
;
1493 run_parallel(TASKS
, test_update_delete
, data
);
1495 /* Check that key=0 is already there. */
1496 assert(bpf_map_update_elem(fd
, &key
, &value
, BPF_NOEXIST
) < 0 &&
1499 /* Check that all elements were inserted. */
1500 assert(bpf_map_get_next_key(fd
, NULL
, &key
) == 0);
1502 for (i
= 0; i
< MAP_SIZE
; i
++)
1503 assert(bpf_map_get_next_key(fd
, &key
, &key
) == 0);
1504 assert(bpf_map_get_next_key(fd
, &key
, &key
) < 0 && errno
== ENOENT
);
1506 /* Another check for all elements */
1507 for (i
= 0; i
< MAP_SIZE
; i
++) {
1508 key
= MAP_SIZE
- i
- 1;
1510 assert(bpf_map_lookup_elem(fd
, &key
, &value
) == 0 &&
1514 /* Now let's delete all elements in parallel. */
1515 data
[1] = DO_DELETE
;
1516 run_parallel(TASKS
, test_update_delete
, data
);
1518 /* Nothing should be left. */
1520 assert(bpf_map_get_next_key(fd
, NULL
, &key
) < 0 && errno
== ENOENT
);
1521 assert(bpf_map_get_next_key(fd
, &key
, &key
) < 0 && errno
== ENOENT
);
1524 bpf_map_delete_elem(fd
, &key
);
1530 static void test_map_rdonly(void)
1532 int fd
, key
= 0, value
= 0;
1535 old_flags
= map_opts
.map_flags
;
1536 map_opts
.map_flags
|= BPF_F_RDONLY
;
1537 fd
= bpf_map_create(BPF_MAP_TYPE_HASH
, NULL
, sizeof(key
), sizeof(value
),
1538 MAP_SIZE
, &map_opts
);
1539 map_opts
.map_flags
= old_flags
;
1541 printf("Failed to create map for read only test '%s'!\n",
1548 /* Try to insert key=1 element. */
1549 assert(bpf_map_update_elem(fd
, &key
, &value
, BPF_ANY
) < 0 &&
1552 /* Check that key=1 is not found. */
1553 assert(bpf_map_lookup_elem(fd
, &key
, &value
) < 0 && errno
== ENOENT
);
1554 assert(bpf_map_get_next_key(fd
, &key
, &value
) < 0 && errno
== ENOENT
);
1559 static void test_map_wronly_hash(void)
1561 int fd
, key
= 0, value
= 0;
1564 old_flags
= map_opts
.map_flags
;
1565 map_opts
.map_flags
|= BPF_F_WRONLY
;
1566 fd
= bpf_map_create(BPF_MAP_TYPE_HASH
, NULL
, sizeof(key
), sizeof(value
),
1567 MAP_SIZE
, &map_opts
);
1568 map_opts
.map_flags
= old_flags
;
1570 printf("Failed to create map for write only test '%s'!\n",
1577 /* Insert key=1 element. */
1578 assert(bpf_map_update_elem(fd
, &key
, &value
, BPF_ANY
) == 0);
1580 /* Check that reading elements and keys from the map is not allowed. */
1581 assert(bpf_map_lookup_elem(fd
, &key
, &value
) < 0 && errno
== EPERM
);
1582 assert(bpf_map_get_next_key(fd
, &key
, &value
) < 0 && errno
== EPERM
);
1587 static void test_map_wronly_stack_or_queue(enum bpf_map_type map_type
)
1593 assert(map_type
== BPF_MAP_TYPE_QUEUE
||
1594 map_type
== BPF_MAP_TYPE_STACK
);
1595 old_flags
= map_opts
.map_flags
;
1596 map_opts
.map_flags
|= BPF_F_WRONLY
;
1597 fd
= bpf_map_create(map_type
, NULL
, 0, sizeof(value
), MAP_SIZE
, &map_opts
);
1598 map_opts
.map_flags
= old_flags
;
1599 /* Stack/Queue maps do not support BPF_F_NO_PREALLOC */
1600 if (map_opts
.map_flags
& BPF_F_NO_PREALLOC
) {
1601 assert(fd
< 0 && errno
== EINVAL
);
1605 printf("Failed to create map '%s'!\n", strerror(errno
));
1610 assert(bpf_map_update_elem(fd
, NULL
, &value
, BPF_ANY
) == 0);
1612 /* Peek element should fail */
1613 assert(bpf_map_lookup_elem(fd
, NULL
, &value
) < 0 && errno
== EPERM
);
1615 /* Pop element should fail */
1616 assert(bpf_map_lookup_and_delete_elem(fd
, NULL
, &value
) < 0 &&
1622 static void test_map_wronly(void)
1624 test_map_wronly_hash();
1625 test_map_wronly_stack_or_queue(BPF_MAP_TYPE_STACK
);
1626 test_map_wronly_stack_or_queue(BPF_MAP_TYPE_QUEUE
);
1629 static void prepare_reuseport_grp(int type
, int map_fd
, size_t map_elem_size
,
1630 __s64
*fds64
, __u64
*sk_cookies
,
1633 socklen_t optlen
, addrlen
;
1634 struct sockaddr_in6 s6
;
1635 const __u32 index0
= 0;
1636 const int optval
= 1;
1644 s6
.sin6_family
= AF_INET6
;
1645 s6
.sin6_addr
= in6addr_any
;
1647 addrlen
= sizeof(s6
);
1648 optlen
= sizeof(sk_cookie
);
1650 for (i
= 0; i
< n
; i
++) {
1651 fd64
= socket(AF_INET6
, type
, 0);
1652 CHECK(fd64
== -1, "socket()",
1653 "sock_type:%d fd64:%lld errno:%d\n",
1656 err
= setsockopt(fd64
, SOL_SOCKET
, SO_REUSEPORT
,
1657 &optval
, sizeof(optval
));
1658 CHECK(err
== -1, "setsockopt(SO_REUSEPORT)",
1659 "err:%d errno:%d\n", err
, errno
);
1661 /* reuseport_array does not allow unbound sk */
1662 if (map_elem_size
== sizeof(__u64
))
1665 assert(map_elem_size
== sizeof(__u32
));
1669 err
= bpf_map_update_elem(map_fd
, &index0
, value
, BPF_ANY
);
1670 CHECK(err
>= 0 || errno
!= EINVAL
,
1671 "reuseport array update unbound sk",
1672 "sock_type:%d err:%d errno:%d\n",
1675 err
= bind(fd64
, (struct sockaddr
*)&s6
, sizeof(s6
));
1676 CHECK(err
== -1, "bind()",
1677 "sock_type:%d err:%d errno:%d\n", type
, err
, errno
);
1680 err
= getsockname(fd64
, (struct sockaddr
*)&s6
,
1682 CHECK(err
== -1, "getsockname()",
1683 "sock_type:%d err:%d errno:%d\n",
1687 err
= getsockopt(fd64
, SOL_SOCKET
, SO_COOKIE
, &sk_cookie
,
1689 CHECK(err
== -1, "getsockopt(SO_COOKIE)",
1690 "sock_type:%d err:%d errno:%d\n", type
, err
, errno
);
1692 if (type
== SOCK_STREAM
) {
1694 * reuseport_array does not allow
1695 * non-listening tcp sk.
1697 err
= bpf_map_update_elem(map_fd
, &index0
, value
,
1699 CHECK(err
>= 0 || errno
!= EINVAL
,
1700 "reuseport array update non-listening sk",
1701 "sock_type:%d err:%d errno:%d\n",
1703 err
= listen(fd64
, 0);
1704 CHECK(err
== -1, "listen()",
1705 "sock_type:%d, err:%d errno:%d\n",
1710 sk_cookies
[i
] = sk_cookie
;
1714 static void test_reuseport_array(void)
1716 #define REUSEPORT_FD_IDX(err, last) ({ (err) ? last : !last; })
1718 const __u32 array_size
= 4, index0
= 0, index3
= 3;
1719 int types
[2] = { SOCK_STREAM
, SOCK_DGRAM
}, type
;
1720 __u64 grpa_cookies
[2], sk_cookie
, map_cookie
;
1721 __s64 grpa_fds64
[2] = { -1, -1 }, fd64
= -1;
1722 const __u32 bad_index
= array_size
;
1723 int map_fd
, err
, t
, f
;
1727 map_fd
= bpf_map_create(BPF_MAP_TYPE_REUSEPORT_SOCKARRAY
, NULL
,
1728 sizeof(__u32
), sizeof(__u64
), array_size
, NULL
);
1729 CHECK(map_fd
< 0, "reuseport array create",
1730 "map_fd:%d, errno:%d\n", map_fd
, errno
);
1732 /* Test lookup/update/delete with invalid index */
1733 err
= bpf_map_delete_elem(map_fd
, &bad_index
);
1734 CHECK(err
>= 0 || errno
!= E2BIG
, "reuseport array del >=max_entries",
1735 "err:%d errno:%d\n", err
, errno
);
1737 err
= bpf_map_update_elem(map_fd
, &bad_index
, &fd64
, BPF_ANY
);
1738 CHECK(err
>= 0 || errno
!= E2BIG
,
1739 "reuseport array update >=max_entries",
1740 "err:%d errno:%d\n", err
, errno
);
1742 err
= bpf_map_lookup_elem(map_fd
, &bad_index
, &map_cookie
);
1743 CHECK(err
>= 0 || errno
!= ENOENT
,
1744 "reuseport array update >=max_entries",
1745 "err:%d errno:%d\n", err
, errno
);
1747 /* Test lookup/delete non existence elem */
1748 err
= bpf_map_lookup_elem(map_fd
, &index3
, &map_cookie
);
1749 CHECK(err
>= 0 || errno
!= ENOENT
,
1750 "reuseport array lookup not-exist elem",
1751 "err:%d errno:%d\n", err
, errno
);
1752 err
= bpf_map_delete_elem(map_fd
, &index3
);
1753 CHECK(err
>= 0 || errno
!= ENOENT
,
1754 "reuseport array del not-exist elem",
1755 "err:%d errno:%d\n", err
, errno
);
1757 for (t
= 0; t
< ARRAY_SIZE(types
); t
++) {
1760 prepare_reuseport_grp(type
, map_fd
, sizeof(__u64
), grpa_fds64
,
1761 grpa_cookies
, ARRAY_SIZE(grpa_fds64
));
1763 /* Test BPF_* update flags */
1764 /* BPF_EXIST failure case */
1765 err
= bpf_map_update_elem(map_fd
, &index3
, &grpa_fds64
[fds_idx
],
1767 CHECK(err
>= 0 || errno
!= ENOENT
,
1768 "reuseport array update empty elem BPF_EXIST",
1769 "sock_type:%d err:%d errno:%d\n",
1771 fds_idx
= REUSEPORT_FD_IDX(err
, fds_idx
);
1773 /* BPF_NOEXIST success case */
1774 err
= bpf_map_update_elem(map_fd
, &index3
, &grpa_fds64
[fds_idx
],
1777 "reuseport array update empty elem BPF_NOEXIST",
1778 "sock_type:%d err:%d errno:%d\n",
1780 fds_idx
= REUSEPORT_FD_IDX(err
, fds_idx
);
1782 /* BPF_EXIST success case. */
1783 err
= bpf_map_update_elem(map_fd
, &index3
, &grpa_fds64
[fds_idx
],
1786 "reuseport array update same elem BPF_EXIST",
1787 "sock_type:%d err:%d errno:%d\n", type
, err
, errno
);
1788 fds_idx
= REUSEPORT_FD_IDX(err
, fds_idx
);
1790 /* BPF_NOEXIST failure case */
1791 err
= bpf_map_update_elem(map_fd
, &index3
, &grpa_fds64
[fds_idx
],
1793 CHECK(err
>= 0 || errno
!= EEXIST
,
1794 "reuseport array update non-empty elem BPF_NOEXIST",
1795 "sock_type:%d err:%d errno:%d\n",
1797 fds_idx
= REUSEPORT_FD_IDX(err
, fds_idx
);
1799 /* BPF_ANY case (always succeed) */
1800 err
= bpf_map_update_elem(map_fd
, &index3
, &grpa_fds64
[fds_idx
],
1803 "reuseport array update same sk with BPF_ANY",
1804 "sock_type:%d err:%d errno:%d\n", type
, err
, errno
);
1806 fd64
= grpa_fds64
[fds_idx
];
1807 sk_cookie
= grpa_cookies
[fds_idx
];
1809 /* The same sk cannot be added to reuseport_array twice */
1810 err
= bpf_map_update_elem(map_fd
, &index3
, &fd64
, BPF_ANY
);
1811 CHECK(err
>= 0 || errno
!= EBUSY
,
1812 "reuseport array update same sk with same index",
1813 "sock_type:%d err:%d errno:%d\n",
1816 err
= bpf_map_update_elem(map_fd
, &index0
, &fd64
, BPF_ANY
);
1817 CHECK(err
>= 0 || errno
!= EBUSY
,
1818 "reuseport array update same sk with different index",
1819 "sock_type:%d err:%d errno:%d\n",
1822 /* Test delete elem */
1823 err
= bpf_map_delete_elem(map_fd
, &index3
);
1824 CHECK(err
< 0, "reuseport array delete sk",
1825 "sock_type:%d err:%d errno:%d\n",
1828 /* Add it back with BPF_NOEXIST */
1829 err
= bpf_map_update_elem(map_fd
, &index3
, &fd64
, BPF_NOEXIST
);
1831 "reuseport array re-add with BPF_NOEXIST after del",
1832 "sock_type:%d err:%d errno:%d\n", type
, err
, errno
);
1835 err
= bpf_map_lookup_elem(map_fd
, &index3
, &map_cookie
);
1836 CHECK(err
< 0 || sk_cookie
!= map_cookie
,
1837 "reuseport array lookup re-added sk",
1838 "sock_type:%d err:%d errno:%d sk_cookie:0x%llx map_cookie:0x%llxn",
1839 type
, err
, errno
, sk_cookie
, map_cookie
);
1841 /* Test elem removed by close() */
1842 for (f
= 0; f
< ARRAY_SIZE(grpa_fds64
); f
++)
1843 close(grpa_fds64
[f
]);
1844 err
= bpf_map_lookup_elem(map_fd
, &index3
, &map_cookie
);
1845 CHECK(err
>= 0 || errno
!= ENOENT
,
1846 "reuseport array lookup after close()",
1847 "sock_type:%d err:%d errno:%d\n",
1852 fd64
= socket(AF_INET6
, SOCK_RAW
, IPPROTO_UDP
);
1853 CHECK(fd64
== -1, "socket(SOCK_RAW)", "err:%d errno:%d\n",
1855 err
= bpf_map_update_elem(map_fd
, &index3
, &fd64
, BPF_NOEXIST
);
1856 CHECK(err
>= 0 || errno
!= ENOTSUPP
, "reuseport array update SOCK_RAW",
1857 "err:%d errno:%d\n", err
, errno
);
1860 /* Close the 64 bit value map */
1863 /* Test 32 bit fd */
1864 map_fd
= bpf_map_create(BPF_MAP_TYPE_REUSEPORT_SOCKARRAY
, NULL
,
1865 sizeof(__u32
), sizeof(__u32
), array_size
, NULL
);
1866 CHECK(map_fd
< 0, "reuseport array create",
1867 "map_fd:%d, errno:%d\n", map_fd
, errno
);
1868 prepare_reuseport_grp(SOCK_STREAM
, map_fd
, sizeof(__u32
), &fd64
,
1871 err
= bpf_map_update_elem(map_fd
, &index3
, &fd
, BPF_NOEXIST
);
1872 CHECK(err
< 0, "reuseport array update 32 bit fd",
1873 "err:%d errno:%d\n", err
, errno
);
1874 err
= bpf_map_lookup_elem(map_fd
, &index3
, &map_cookie
);
1875 CHECK(err
>= 0 || errno
!= ENOSPC
,
1876 "reuseport array lookup 32 bit fd",
1877 "err:%d errno:%d\n", err
, errno
);
1882 static void run_all_tests(void)
1884 test_hashmap(0, NULL
);
1885 test_hashmap_percpu(0, NULL
);
1886 test_hashmap_walk(0, NULL
);
1887 test_hashmap_zero_seed();
1889 test_arraymap(0, NULL
);
1890 test_arraymap_percpu(0, NULL
);
1892 test_arraymap_percpu_many_keys();
1894 test_devmap(0, NULL
);
1895 test_devmap_hash(0, NULL
);
1896 test_sockmap(0, NULL
);
1899 test_map_parallel();
1905 test_reuseport_array();
1907 test_queuemap(0, NULL
);
1908 test_stackmap(0, NULL
);
1913 #define DEFINE_TEST(name) extern void test_##name(void);
1914 #include <map_tests/tests.h>
1921 libbpf_set_strict_mode(LIBBPF_STRICT_ALL
);
1923 map_opts
.map_flags
= 0;
1926 map_opts
.map_flags
= BPF_F_NO_PREALLOC
;
1929 #define DEFINE_TEST(name) test_##name();
1930 #include <map_tests/tests.h>
1933 printf("test_maps: OK, %d SKIPPED\n", skips
);