Merge branch 'locking-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[cris-mirror.git] / tools / testing / selftests / bpf / test_maps.c
blob9e03a4c356a496e3f57d18058254df464c206278
1 /*
2 * Testsuite for eBPF maps
4 * Copyright (c) 2014 PLUMgrid, http://plumgrid.com
5 * Copyright (c) 2016 Facebook
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.
12 #include <stdio.h>
13 #include <unistd.h>
14 #include <errno.h>
15 #include <string.h>
16 #include <assert.h>
17 #include <stdlib.h>
19 #include <sys/wait.h>
20 #include <sys/resource.h>
22 #include <linux/bpf.h>
24 #include <bpf/bpf.h>
25 #include <bpf/libbpf.h>
26 #include "bpf_util.h"
28 static int map_flags;
30 static void test_hashmap(int task, void *data)
32 long long key, next_key, first_key, value;
33 int fd;
35 fd = bpf_create_map(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);
42 key = 1;
43 value = 1234;
44 /* Insert key=1 element. */
45 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
47 value = 0;
48 /* BPF_NOEXIST means add new element if it doesn't exist. */
49 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
50 /* key=1 already exists. */
51 errno == EEXIST);
53 /* -1 is an invalid flag. */
54 assert(bpf_map_update_elem(fd, &key, &value, -1) == -1 &&
55 errno == EINVAL);
57 /* Check that key=1 can be found. */
58 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234);
60 key = 2;
61 /* Check that key=2 is not found. */
62 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
64 /* BPF_EXIST means update existing element. */
65 assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == -1 &&
66 /* key=2 is not there. */
67 errno == ENOENT);
69 /* Insert key=2 element. */
70 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0);
72 /* key=1 and key=2 were inserted, check that key=0 cannot be
73 * inserted due to max_entries limit.
75 key = 0;
76 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
77 errno == E2BIG);
79 /* Update existing element, though the map is full. */
80 key = 1;
81 assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0);
82 key = 2;
83 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
84 key = 3;
85 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
86 errno == E2BIG);
88 /* Check that key = 0 doesn't exist. */
89 key = 0;
90 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
92 /* Iterate over two elements. */
93 assert(bpf_map_get_next_key(fd, NULL, &first_key) == 0 &&
94 (first_key == 1 || first_key == 2));
95 assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 &&
96 (next_key == first_key));
97 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 &&
98 (next_key == 1 || next_key == 2) &&
99 (next_key != first_key));
100 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 &&
101 errno == ENOENT);
103 /* Delete both elements. */
104 key = 1;
105 assert(bpf_map_delete_elem(fd, &key) == 0);
106 key = 2;
107 assert(bpf_map_delete_elem(fd, &key) == 0);
108 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
110 key = 0;
111 /* Check that map is empty. */
112 assert(bpf_map_get_next_key(fd, NULL, &next_key) == -1 &&
113 errno == ENOENT);
114 assert(bpf_map_get_next_key(fd, &key, &next_key) == -1 &&
115 errno == ENOENT);
117 close(fd);
120 static void test_hashmap_sizes(int task, void *data)
122 int fd, i, j;
124 for (i = 1; i <= 512; i <<= 1)
125 for (j = 1; j <= 1 << 18; j <<= 1) {
126 fd = bpf_create_map(BPF_MAP_TYPE_HASH, i, j,
127 2, map_flags);
128 if (fd < 0) {
129 if (errno == ENOMEM)
130 return;
131 printf("Failed to create hashmap key=%d value=%d '%s'\n",
132 i, j, strerror(errno));
133 exit(1);
135 close(fd);
136 usleep(10); /* give kernel time to destroy */
140 static void test_hashmap_percpu(int task, void *data)
142 unsigned int nr_cpus = bpf_num_possible_cpus();
143 BPF_DECLARE_PERCPU(long, value);
144 long long key, next_key, first_key;
145 int expected_key_mask = 0;
146 int fd, i;
148 fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_HASH, sizeof(key),
149 sizeof(bpf_percpu(value, 0)), 2, map_flags);
150 if (fd < 0) {
151 printf("Failed to create hashmap '%s'!\n", strerror(errno));
152 exit(1);
155 for (i = 0; i < nr_cpus; i++)
156 bpf_percpu(value, i) = i + 100;
158 key = 1;
159 /* Insert key=1 element. */
160 assert(!(expected_key_mask & key));
161 assert(bpf_map_update_elem(fd, &key, value, BPF_ANY) == 0);
162 expected_key_mask |= key;
164 /* BPF_NOEXIST means add new element if it doesn't exist. */
165 assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == -1 &&
166 /* key=1 already exists. */
167 errno == EEXIST);
169 /* -1 is an invalid flag. */
170 assert(bpf_map_update_elem(fd, &key, value, -1) == -1 &&
171 errno == EINVAL);
173 /* Check that key=1 can be found. Value could be 0 if the lookup
174 * was run from a different CPU.
176 bpf_percpu(value, 0) = 1;
177 assert(bpf_map_lookup_elem(fd, &key, value) == 0 &&
178 bpf_percpu(value, 0) == 100);
180 key = 2;
181 /* Check that key=2 is not found. */
182 assert(bpf_map_lookup_elem(fd, &key, value) == -1 && errno == ENOENT);
184 /* BPF_EXIST means update existing element. */
185 assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == -1 &&
186 /* key=2 is not there. */
187 errno == ENOENT);
189 /* Insert key=2 element. */
190 assert(!(expected_key_mask & key));
191 assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == 0);
192 expected_key_mask |= key;
194 /* key=1 and key=2 were inserted, check that key=0 cannot be
195 * inserted due to max_entries limit.
197 key = 0;
198 assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == -1 &&
199 errno == E2BIG);
201 /* Check that key = 0 doesn't exist. */
202 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
204 /* Iterate over two elements. */
205 assert(bpf_map_get_next_key(fd, NULL, &first_key) == 0 &&
206 ((expected_key_mask & first_key) == first_key));
207 while (!bpf_map_get_next_key(fd, &key, &next_key)) {
208 if (first_key) {
209 assert(next_key == first_key);
210 first_key = 0;
212 assert((expected_key_mask & next_key) == next_key);
213 expected_key_mask &= ~next_key;
215 assert(bpf_map_lookup_elem(fd, &next_key, value) == 0);
217 for (i = 0; i < nr_cpus; i++)
218 assert(bpf_percpu(value, i) == i + 100);
220 key = next_key;
222 assert(errno == ENOENT);
224 /* Update with BPF_EXIST. */
225 key = 1;
226 assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == 0);
228 /* Delete both elements. */
229 key = 1;
230 assert(bpf_map_delete_elem(fd, &key) == 0);
231 key = 2;
232 assert(bpf_map_delete_elem(fd, &key) == 0);
233 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
235 key = 0;
236 /* Check that map is empty. */
237 assert(bpf_map_get_next_key(fd, NULL, &next_key) == -1 &&
238 errno == ENOENT);
239 assert(bpf_map_get_next_key(fd, &key, &next_key) == -1 &&
240 errno == ENOENT);
242 close(fd);
245 static void test_hashmap_walk(int task, void *data)
247 int fd, i, max_entries = 1000;
248 long long key, value, next_key;
249 bool next_key_valid = true;
251 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
252 max_entries, map_flags);
253 if (fd < 0) {
254 printf("Failed to create hashmap '%s'!\n", strerror(errno));
255 exit(1);
258 for (i = 0; i < max_entries; i++) {
259 key = i; value = key;
260 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0);
263 for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key,
264 &next_key) == 0; i++) {
265 key = next_key;
266 assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
269 assert(i == max_entries);
271 assert(bpf_map_get_next_key(fd, NULL, &key) == 0);
272 for (i = 0; next_key_valid; i++) {
273 next_key_valid = bpf_map_get_next_key(fd, &key, &next_key) == 0;
274 assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
275 value++;
276 assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0);
277 key = next_key;
280 assert(i == max_entries);
282 for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key,
283 &next_key) == 0; i++) {
284 key = next_key;
285 assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
286 assert(value - 1 == key);
289 assert(i == max_entries);
290 close(fd);
293 static void test_arraymap(int task, void *data)
295 int key, next_key, fd;
296 long long value;
298 fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value),
299 2, 0);
300 if (fd < 0) {
301 printf("Failed to create arraymap '%s'!\n", strerror(errno));
302 exit(1);
305 key = 1;
306 value = 1234;
307 /* Insert key=1 element. */
308 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
310 value = 0;
311 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
312 errno == EEXIST);
314 /* Check that key=1 can be found. */
315 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234);
317 key = 0;
318 /* Check that key=0 is also found and zero initialized. */
319 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0);
321 /* key=0 and key=1 were inserted, check that key=2 cannot be inserted
322 * due to max_entries limit.
324 key = 2;
325 assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == -1 &&
326 errno == E2BIG);
328 /* Check that key = 2 doesn't exist. */
329 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
331 /* Iterate over two elements. */
332 assert(bpf_map_get_next_key(fd, NULL, &next_key) == 0 &&
333 next_key == 0);
334 assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 &&
335 next_key == 0);
336 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 &&
337 next_key == 1);
338 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 &&
339 errno == ENOENT);
341 /* Delete shouldn't succeed. */
342 key = 1;
343 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == EINVAL);
345 close(fd);
348 static void test_arraymap_percpu(int task, void *data)
350 unsigned int nr_cpus = bpf_num_possible_cpus();
351 BPF_DECLARE_PERCPU(long, values);
352 int key, next_key, fd, i;
354 fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
355 sizeof(bpf_percpu(values, 0)), 2, 0);
356 if (fd < 0) {
357 printf("Failed to create arraymap '%s'!\n", strerror(errno));
358 exit(1);
361 for (i = 0; i < nr_cpus; i++)
362 bpf_percpu(values, i) = i + 100;
364 key = 1;
365 /* Insert key=1 element. */
366 assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0);
368 bpf_percpu(values, 0) = 0;
369 assert(bpf_map_update_elem(fd, &key, values, BPF_NOEXIST) == -1 &&
370 errno == EEXIST);
372 /* Check that key=1 can be found. */
373 assert(bpf_map_lookup_elem(fd, &key, values) == 0 &&
374 bpf_percpu(values, 0) == 100);
376 key = 0;
377 /* Check that key=0 is also found and zero initialized. */
378 assert(bpf_map_lookup_elem(fd, &key, values) == 0 &&
379 bpf_percpu(values, 0) == 0 &&
380 bpf_percpu(values, nr_cpus - 1) == 0);
382 /* Check that key=2 cannot be inserted due to max_entries limit. */
383 key = 2;
384 assert(bpf_map_update_elem(fd, &key, values, BPF_EXIST) == -1 &&
385 errno == E2BIG);
387 /* Check that key = 2 doesn't exist. */
388 assert(bpf_map_lookup_elem(fd, &key, values) == -1 && errno == ENOENT);
390 /* Iterate over two elements. */
391 assert(bpf_map_get_next_key(fd, NULL, &next_key) == 0 &&
392 next_key == 0);
393 assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 &&
394 next_key == 0);
395 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 &&
396 next_key == 1);
397 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 &&
398 errno == ENOENT);
400 /* Delete shouldn't succeed. */
401 key = 1;
402 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == EINVAL);
404 close(fd);
407 static void test_arraymap_percpu_many_keys(void)
409 unsigned int nr_cpus = bpf_num_possible_cpus();
410 BPF_DECLARE_PERCPU(long, values);
411 /* nr_keys is not too large otherwise the test stresses percpu
412 * allocator more than anything else
414 unsigned int nr_keys = 2000;
415 int key, fd, i;
417 fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
418 sizeof(bpf_percpu(values, 0)), nr_keys, 0);
419 if (fd < 0) {
420 printf("Failed to create per-cpu arraymap '%s'!\n",
421 strerror(errno));
422 exit(1);
425 for (i = 0; i < nr_cpus; i++)
426 bpf_percpu(values, i) = i + 10;
428 for (key = 0; key < nr_keys; key++)
429 assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0);
431 for (key = 0; key < nr_keys; key++) {
432 for (i = 0; i < nr_cpus; i++)
433 bpf_percpu(values, i) = 0;
435 assert(bpf_map_lookup_elem(fd, &key, values) == 0);
437 for (i = 0; i < nr_cpus; i++)
438 assert(bpf_percpu(values, i) == i + 10);
441 close(fd);
444 static void test_devmap(int task, void *data)
446 int fd;
447 __u32 key, value;
449 fd = bpf_create_map(BPF_MAP_TYPE_DEVMAP, sizeof(key), sizeof(value),
450 2, 0);
451 if (fd < 0) {
452 printf("Failed to create arraymap '%s'!\n", strerror(errno));
453 exit(1);
456 close(fd);
459 #include <sys/socket.h>
460 #include <sys/ioctl.h>
461 #include <arpa/inet.h>
462 #include <sys/select.h>
463 #include <linux/err.h>
464 #define SOCKMAP_PARSE_PROG "./sockmap_parse_prog.o"
465 #define SOCKMAP_VERDICT_PROG "./sockmap_verdict_prog.o"
466 static void test_sockmap(int tasks, void *data)
468 int one = 1, map_fd_rx = 0, map_fd_tx = 0, map_fd_break, s, sc, rc;
469 struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_break;
470 int ports[] = {50200, 50201, 50202, 50204};
471 int err, i, fd, udp, sfd[6] = {0xdeadbeef};
472 u8 buf[20] = {0x0, 0x5, 0x3, 0x2, 0x1, 0x0};
473 int parse_prog, verdict_prog;
474 struct sockaddr_in addr;
475 struct bpf_object *obj;
476 struct timeval to;
477 __u32 key, value;
478 pid_t pid[tasks];
479 fd_set w;
481 /* Create some sockets to use with sockmap */
482 for (i = 0; i < 2; i++) {
483 sfd[i] = socket(AF_INET, SOCK_STREAM, 0);
484 if (sfd[i] < 0)
485 goto out;
486 err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR,
487 (char *)&one, sizeof(one));
488 if (err) {
489 printf("failed to setsockopt\n");
490 goto out;
492 err = ioctl(sfd[i], FIONBIO, (char *)&one);
493 if (err < 0) {
494 printf("failed to ioctl\n");
495 goto out;
497 memset(&addr, 0, sizeof(struct sockaddr_in));
498 addr.sin_family = AF_INET;
499 addr.sin_addr.s_addr = inet_addr("127.0.0.1");
500 addr.sin_port = htons(ports[i]);
501 err = bind(sfd[i], (struct sockaddr *)&addr, sizeof(addr));
502 if (err < 0) {
503 printf("failed to bind: err %i: %i:%i\n",
504 err, i, sfd[i]);
505 goto out;
507 err = listen(sfd[i], 32);
508 if (err < 0) {
509 printf("failed to listen\n");
510 goto out;
514 for (i = 2; i < 4; i++) {
515 sfd[i] = socket(AF_INET, SOCK_STREAM, 0);
516 if (sfd[i] < 0)
517 goto out;
518 err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR,
519 (char *)&one, sizeof(one));
520 if (err) {
521 printf("set sock opt\n");
522 goto out;
524 memset(&addr, 0, sizeof(struct sockaddr_in));
525 addr.sin_family = AF_INET;
526 addr.sin_addr.s_addr = inet_addr("127.0.0.1");
527 addr.sin_port = htons(ports[i - 2]);
528 err = connect(sfd[i], (struct sockaddr *)&addr, sizeof(addr));
529 if (err) {
530 printf("failed to connect\n");
531 goto out;
536 for (i = 4; i < 6; i++) {
537 sfd[i] = accept(sfd[i - 4], NULL, NULL);
538 if (sfd[i] < 0) {
539 printf("accept failed\n");
540 goto out;
544 /* Test sockmap with connected sockets */
545 fd = bpf_create_map(BPF_MAP_TYPE_SOCKMAP,
546 sizeof(key), sizeof(value),
547 6, 0);
548 if (fd < 0) {
549 printf("Failed to create sockmap %i\n", fd);
550 goto out_sockmap;
553 /* Test update with unsupported UDP socket */
554 udp = socket(AF_INET, SOCK_DGRAM, 0);
555 i = 0;
556 err = bpf_map_update_elem(fd, &i, &udp, BPF_ANY);
557 if (!err) {
558 printf("Failed socket SOCK_DGRAM allowed '%i:%i'\n",
559 i, udp);
560 goto out_sockmap;
563 /* Test update without programs */
564 for (i = 0; i < 6; i++) {
565 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
566 if (err) {
567 printf("Failed noprog update sockmap '%i:%i'\n",
568 i, sfd[i]);
569 goto out_sockmap;
573 /* Test attaching/detaching bad fds */
574 err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_PARSER, 0);
575 if (!err) {
576 printf("Failed invalid parser prog attach\n");
577 goto out_sockmap;
580 err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_VERDICT, 0);
581 if (!err) {
582 printf("Failed invalid verdict prog attach\n");
583 goto out_sockmap;
586 err = bpf_prog_attach(-1, fd, __MAX_BPF_ATTACH_TYPE, 0);
587 if (!err) {
588 printf("Failed unknown prog attach\n");
589 goto out_sockmap;
592 err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER);
593 if (err) {
594 printf("Failed empty parser prog detach\n");
595 goto out_sockmap;
598 err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT);
599 if (err) {
600 printf("Failed empty verdict prog detach\n");
601 goto out_sockmap;
604 err = bpf_prog_detach(fd, __MAX_BPF_ATTACH_TYPE);
605 if (!err) {
606 printf("Detach invalid prog successful\n");
607 goto out_sockmap;
610 /* Load SK_SKB program and Attach */
611 err = bpf_prog_load(SOCKMAP_PARSE_PROG,
612 BPF_PROG_TYPE_SK_SKB, &obj, &parse_prog);
613 if (err) {
614 printf("Failed to load SK_SKB parse prog\n");
615 goto out_sockmap;
618 err = bpf_prog_load(SOCKMAP_VERDICT_PROG,
619 BPF_PROG_TYPE_SK_SKB, &obj, &verdict_prog);
620 if (err) {
621 printf("Failed to load SK_SKB verdict prog\n");
622 goto out_sockmap;
625 bpf_map_rx = bpf_object__find_map_by_name(obj, "sock_map_rx");
626 if (IS_ERR(bpf_map_rx)) {
627 printf("Failed to load map rx from verdict prog\n");
628 goto out_sockmap;
631 map_fd_rx = bpf_map__fd(bpf_map_rx);
632 if (map_fd_rx < 0) {
633 printf("Failed to get map fd\n");
634 goto out_sockmap;
637 bpf_map_tx = bpf_object__find_map_by_name(obj, "sock_map_tx");
638 if (IS_ERR(bpf_map_tx)) {
639 printf("Failed to load map tx from verdict prog\n");
640 goto out_sockmap;
643 map_fd_tx = bpf_map__fd(bpf_map_tx);
644 if (map_fd_tx < 0) {
645 printf("Failed to get map tx fd\n");
646 goto out_sockmap;
649 bpf_map_break = bpf_object__find_map_by_name(obj, "sock_map_break");
650 if (IS_ERR(bpf_map_break)) {
651 printf("Failed to load map tx from verdict prog\n");
652 goto out_sockmap;
655 map_fd_break = bpf_map__fd(bpf_map_break);
656 if (map_fd_break < 0) {
657 printf("Failed to get map tx fd\n");
658 goto out_sockmap;
661 err = bpf_prog_attach(parse_prog, map_fd_break,
662 BPF_SK_SKB_STREAM_PARSER, 0);
663 if (!err) {
664 printf("Allowed attaching SK_SKB program to invalid map\n");
665 goto out_sockmap;
668 err = bpf_prog_attach(parse_prog, map_fd_rx,
669 BPF_SK_SKB_STREAM_PARSER, 0);
670 if (err) {
671 printf("Failed stream parser bpf prog attach\n");
672 goto out_sockmap;
675 err = bpf_prog_attach(verdict_prog, map_fd_rx,
676 BPF_SK_SKB_STREAM_VERDICT, 0);
677 if (err) {
678 printf("Failed stream verdict bpf prog attach\n");
679 goto out_sockmap;
682 err = bpf_prog_attach(verdict_prog, map_fd_rx,
683 __MAX_BPF_ATTACH_TYPE, 0);
684 if (!err) {
685 printf("Attached unknown bpf prog\n");
686 goto out_sockmap;
689 /* Test map update elem afterwards fd lives in fd and map_fd */
690 for (i = 0; i < 6; i++) {
691 err = bpf_map_update_elem(map_fd_rx, &i, &sfd[i], BPF_ANY);
692 if (err) {
693 printf("Failed map_fd_rx update sockmap %i '%i:%i'\n",
694 err, i, sfd[i]);
695 goto out_sockmap;
697 err = bpf_map_update_elem(map_fd_tx, &i, &sfd[i], BPF_ANY);
698 if (err) {
699 printf("Failed map_fd_tx update sockmap %i '%i:%i'\n",
700 err, i, sfd[i]);
701 goto out_sockmap;
705 /* Test map delete elem and remove send/recv sockets */
706 for (i = 2; i < 4; i++) {
707 err = bpf_map_delete_elem(map_fd_rx, &i);
708 if (err) {
709 printf("Failed delete sockmap rx %i '%i:%i'\n",
710 err, i, sfd[i]);
711 goto out_sockmap;
713 err = bpf_map_delete_elem(map_fd_tx, &i);
714 if (err) {
715 printf("Failed delete sockmap tx %i '%i:%i'\n",
716 err, i, sfd[i]);
717 goto out_sockmap;
721 /* Test map send/recv */
722 for (i = 0; i < 2; i++) {
723 buf[0] = i;
724 buf[1] = 0x5;
725 sc = send(sfd[2], buf, 20, 0);
726 if (sc < 0) {
727 printf("Failed sockmap send\n");
728 goto out_sockmap;
731 FD_ZERO(&w);
732 FD_SET(sfd[3], &w);
733 to.tv_sec = 1;
734 to.tv_usec = 0;
735 s = select(sfd[3] + 1, &w, NULL, NULL, &to);
736 if (s == -1) {
737 perror("Failed sockmap select()");
738 goto out_sockmap;
739 } else if (!s) {
740 printf("Failed sockmap unexpected timeout\n");
741 goto out_sockmap;
744 if (!FD_ISSET(sfd[3], &w)) {
745 printf("Failed sockmap select/recv\n");
746 goto out_sockmap;
749 rc = recv(sfd[3], buf, sizeof(buf), 0);
750 if (rc < 0) {
751 printf("Failed sockmap recv\n");
752 goto out_sockmap;
756 /* Negative null entry lookup from datapath should be dropped */
757 buf[0] = 1;
758 buf[1] = 12;
759 sc = send(sfd[2], buf, 20, 0);
760 if (sc < 0) {
761 printf("Failed sockmap send\n");
762 goto out_sockmap;
765 /* Push fd into same slot */
766 i = 2;
767 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST);
768 if (!err) {
769 printf("Failed allowed sockmap dup slot BPF_NOEXIST\n");
770 goto out_sockmap;
773 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
774 if (err) {
775 printf("Failed sockmap update new slot BPF_ANY\n");
776 goto out_sockmap;
779 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST);
780 if (err) {
781 printf("Failed sockmap update new slot BPF_EXIST\n");
782 goto out_sockmap;
785 /* Delete the elems without programs */
786 for (i = 0; i < 6; i++) {
787 err = bpf_map_delete_elem(fd, &i);
788 if (err) {
789 printf("Failed delete sockmap %i '%i:%i'\n",
790 err, i, sfd[i]);
794 /* Test having multiple maps open and set with programs on same fds */
795 err = bpf_prog_attach(parse_prog, fd,
796 BPF_SK_SKB_STREAM_PARSER, 0);
797 if (err) {
798 printf("Failed fd bpf parse prog attach\n");
799 goto out_sockmap;
801 err = bpf_prog_attach(verdict_prog, fd,
802 BPF_SK_SKB_STREAM_VERDICT, 0);
803 if (err) {
804 printf("Failed fd bpf verdict prog attach\n");
805 goto out_sockmap;
808 for (i = 4; i < 6; i++) {
809 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
810 if (!err) {
811 printf("Failed allowed duplicate programs in update ANY sockmap %i '%i:%i'\n",
812 err, i, sfd[i]);
813 goto out_sockmap;
815 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST);
816 if (!err) {
817 printf("Failed allowed duplicate program in update NOEXIST sockmap %i '%i:%i'\n",
818 err, i, sfd[i]);
819 goto out_sockmap;
821 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST);
822 if (!err) {
823 printf("Failed allowed duplicate program in update EXIST sockmap %i '%i:%i'\n",
824 err, i, sfd[i]);
825 goto out_sockmap;
829 /* Test tasks number of forked operations */
830 for (i = 0; i < tasks; i++) {
831 pid[i] = fork();
832 if (pid[i] == 0) {
833 for (i = 0; i < 6; i++) {
834 bpf_map_delete_elem(map_fd_tx, &i);
835 bpf_map_delete_elem(map_fd_rx, &i);
836 bpf_map_update_elem(map_fd_tx, &i,
837 &sfd[i], BPF_ANY);
838 bpf_map_update_elem(map_fd_rx, &i,
839 &sfd[i], BPF_ANY);
841 exit(0);
842 } else if (pid[i] == -1) {
843 printf("Couldn't spawn #%d process!\n", i);
844 exit(1);
848 for (i = 0; i < tasks; i++) {
849 int status;
851 assert(waitpid(pid[i], &status, 0) == pid[i]);
852 assert(status == 0);
855 err = bpf_prog_detach(map_fd_rx, __MAX_BPF_ATTACH_TYPE);
856 if (!err) {
857 printf("Detached an invalid prog type.\n");
858 goto out_sockmap;
861 err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
862 if (err) {
863 printf("Failed parser prog detach\n");
864 goto out_sockmap;
867 err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
868 if (err) {
869 printf("Failed parser prog detach\n");
870 goto out_sockmap;
873 /* Test map close sockets and empty maps */
874 for (i = 0; i < 6; i++) {
875 bpf_map_delete_elem(map_fd_tx, &i);
876 bpf_map_delete_elem(map_fd_rx, &i);
877 close(sfd[i]);
879 close(fd);
880 close(map_fd_rx);
881 bpf_object__close(obj);
882 return;
883 out:
884 for (i = 0; i < 6; i++)
885 close(sfd[i]);
886 printf("Failed to create sockmap '%i:%s'!\n", i, strerror(errno));
887 exit(1);
888 out_sockmap:
889 for (i = 0; i < 6; i++) {
890 if (map_fd_tx)
891 bpf_map_delete_elem(map_fd_tx, &i);
892 if (map_fd_rx)
893 bpf_map_delete_elem(map_fd_rx, &i);
894 close(sfd[i]);
896 close(fd);
897 exit(1);
900 #define MAP_SIZE (32 * 1024)
902 static void test_map_large(void)
904 struct bigkey {
905 int a;
906 char b[116];
907 long long c;
908 } key;
909 int fd, i, value;
911 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
912 MAP_SIZE, map_flags);
913 if (fd < 0) {
914 printf("Failed to create large map '%s'!\n", strerror(errno));
915 exit(1);
918 for (i = 0; i < MAP_SIZE; i++) {
919 key = (struct bigkey) { .c = i };
920 value = i;
922 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0);
925 key.c = -1;
926 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
927 errno == E2BIG);
929 /* Iterate through all elements. */
930 assert(bpf_map_get_next_key(fd, NULL, &key) == 0);
931 key.c = -1;
932 for (i = 0; i < MAP_SIZE; i++)
933 assert(bpf_map_get_next_key(fd, &key, &key) == 0);
934 assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT);
936 key.c = 0;
937 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0);
938 key.a = 1;
939 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
941 close(fd);
944 #define run_parallel(N, FN, DATA) \
945 printf("Fork %d tasks to '" #FN "'\n", N); \
946 __run_parallel(N, FN, DATA)
948 static void __run_parallel(int tasks, void (*fn)(int task, void *data),
949 void *data)
951 pid_t pid[tasks];
952 int i;
954 for (i = 0; i < tasks; i++) {
955 pid[i] = fork();
956 if (pid[i] == 0) {
957 fn(i, data);
958 exit(0);
959 } else if (pid[i] == -1) {
960 printf("Couldn't spawn #%d process!\n", i);
961 exit(1);
965 for (i = 0; i < tasks; i++) {
966 int status;
968 assert(waitpid(pid[i], &status, 0) == pid[i]);
969 assert(status == 0);
973 static void test_map_stress(void)
975 run_parallel(100, test_hashmap, NULL);
976 run_parallel(100, test_hashmap_percpu, NULL);
977 run_parallel(100, test_hashmap_sizes, NULL);
978 run_parallel(100, test_hashmap_walk, NULL);
980 run_parallel(100, test_arraymap, NULL);
981 run_parallel(100, test_arraymap_percpu, NULL);
984 #define TASKS 1024
986 #define DO_UPDATE 1
987 #define DO_DELETE 0
989 static void test_update_delete(int fn, void *data)
991 int do_update = ((int *)data)[1];
992 int fd = ((int *)data)[0];
993 int i, key, value;
995 for (i = fn; i < MAP_SIZE; i += TASKS) {
996 key = value = i;
998 if (do_update) {
999 assert(bpf_map_update_elem(fd, &key, &value,
1000 BPF_NOEXIST) == 0);
1001 assert(bpf_map_update_elem(fd, &key, &value,
1002 BPF_EXIST) == 0);
1003 } else {
1004 assert(bpf_map_delete_elem(fd, &key) == 0);
1009 static void test_map_parallel(void)
1011 int i, fd, key = 0, value = 0;
1012 int data[2];
1014 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
1015 MAP_SIZE, map_flags);
1016 if (fd < 0) {
1017 printf("Failed to create map for parallel test '%s'!\n",
1018 strerror(errno));
1019 exit(1);
1022 /* Use the same fd in children to add elements to this map:
1023 * child_0 adds key=0, key=1024, key=2048, ...
1024 * child_1 adds key=1, key=1025, key=2049, ...
1025 * child_1023 adds key=1023, ...
1027 data[0] = fd;
1028 data[1] = DO_UPDATE;
1029 run_parallel(TASKS, test_update_delete, data);
1031 /* Check that key=0 is already there. */
1032 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
1033 errno == EEXIST);
1035 /* Check that all elements were inserted. */
1036 assert(bpf_map_get_next_key(fd, NULL, &key) == 0);
1037 key = -1;
1038 for (i = 0; i < MAP_SIZE; i++)
1039 assert(bpf_map_get_next_key(fd, &key, &key) == 0);
1040 assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT);
1042 /* Another check for all elements */
1043 for (i = 0; i < MAP_SIZE; i++) {
1044 key = MAP_SIZE - i - 1;
1046 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 &&
1047 value == key);
1050 /* Now let's delete all elemenets in parallel. */
1051 data[1] = DO_DELETE;
1052 run_parallel(TASKS, test_update_delete, data);
1054 /* Nothing should be left. */
1055 key = -1;
1056 assert(bpf_map_get_next_key(fd, NULL, &key) == -1 && errno == ENOENT);
1057 assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT);
1060 static void test_map_rdonly(void)
1062 int fd, key = 0, value = 0;
1064 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
1065 MAP_SIZE, map_flags | BPF_F_RDONLY);
1066 if (fd < 0) {
1067 printf("Failed to create map for read only test '%s'!\n",
1068 strerror(errno));
1069 exit(1);
1072 key = 1;
1073 value = 1234;
1074 /* Insert key=1 element. */
1075 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == -1 &&
1076 errno == EPERM);
1078 /* Check that key=2 is not found. */
1079 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
1080 assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == ENOENT);
1083 static void test_map_wronly(void)
1085 int fd, key = 0, value = 0;
1087 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
1088 MAP_SIZE, map_flags | BPF_F_WRONLY);
1089 if (fd < 0) {
1090 printf("Failed to create map for read only test '%s'!\n",
1091 strerror(errno));
1092 exit(1);
1095 key = 1;
1096 value = 1234;
1097 /* Insert key=1 element. */
1098 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
1100 /* Check that key=2 is not found. */
1101 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == EPERM);
1102 assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == EPERM);
1105 static void run_all_tests(void)
1107 test_hashmap(0, NULL);
1108 test_hashmap_percpu(0, NULL);
1109 test_hashmap_walk(0, NULL);
1111 test_arraymap(0, NULL);
1112 test_arraymap_percpu(0, NULL);
1114 test_arraymap_percpu_many_keys();
1116 test_devmap(0, NULL);
1117 test_sockmap(0, NULL);
1119 test_map_large();
1120 test_map_parallel();
1121 test_map_stress();
1123 test_map_rdonly();
1124 test_map_wronly();
1127 int main(void)
1129 struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
1131 setrlimit(RLIMIT_MEMLOCK, &rinf);
1133 map_flags = 0;
1134 run_all_tests();
1136 map_flags = BPF_F_NO_PREALLOC;
1137 run_all_tests();
1139 printf("test_maps: OK\n");
1140 return 0;