diff options
| -rw-r--r-- | tools/lib/bpf/bpf.c | 12 | ||||
| -rw-r--r-- | tools/lib/bpf/bpf.h | 2 | ||||
| -rw-r--r-- | tools/testing/selftests/bpf/Makefile | 5 | ||||
| -rw-r--r-- | tools/testing/selftests/bpf/bpf_helpers.h | 7 | ||||
| -rw-r--r-- | tools/testing/selftests/bpf/test_maps.c | 122 | ||||
| -rw-r--r-- | tools/testing/selftests/bpf/test_progs.c | 99 | ||||
| -rw-r--r-- | tools/testing/selftests/bpf/test_queue_map.c | 4 | ||||
| -rw-r--r-- | tools/testing/selftests/bpf/test_queue_stack_map.h | 59 | ||||
| -rw-r--r-- | tools/testing/selftests/bpf/test_stack_map.c | 4 |
9 files changed, 313 insertions, 1 deletions
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index d70a255cb05e..03f9bcc4ef50 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c | |||
| @@ -278,6 +278,18 @@ int bpf_map_lookup_elem(int fd, const void *key, void *value) | |||
| 278 | return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr)); | 278 | return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr)); |
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | int bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value) | ||
| 282 | { | ||
| 283 | union bpf_attr attr; | ||
| 284 | |||
| 285 | bzero(&attr, sizeof(attr)); | ||
| 286 | attr.map_fd = fd; | ||
| 287 | attr.key = ptr_to_u64(key); | ||
| 288 | attr.value = ptr_to_u64(value); | ||
| 289 | |||
| 290 | return sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, sizeof(attr)); | ||
| 291 | } | ||
| 292 | |||
| 281 | int bpf_map_delete_elem(int fd, const void *key) | 293 | int bpf_map_delete_elem(int fd, const void *key) |
| 282 | { | 294 | { |
| 283 | union bpf_attr attr; | 295 | union bpf_attr attr; |
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h index 258c3c178333..26a51538213c 100644 --- a/tools/lib/bpf/bpf.h +++ b/tools/lib/bpf/bpf.h | |||
| @@ -99,6 +99,8 @@ LIBBPF_API int bpf_map_update_elem(int fd, const void *key, const void *value, | |||
| 99 | __u64 flags); | 99 | __u64 flags); |
| 100 | 100 | ||
| 101 | LIBBPF_API int bpf_map_lookup_elem(int fd, const void *key, void *value); | 101 | LIBBPF_API int bpf_map_lookup_elem(int fd, const void *key, void *value); |
| 102 | LIBBPF_API int bpf_map_lookup_and_delete_elem(int fd, const void *key, | ||
| 103 | void *value); | ||
| 102 | LIBBPF_API int bpf_map_delete_elem(int fd, const void *key); | 104 | LIBBPF_API int bpf_map_delete_elem(int fd, const void *key); |
| 103 | LIBBPF_API int bpf_map_get_next_key(int fd, const void *key, void *next_key); | 105 | LIBBPF_API int bpf_map_get_next_key(int fd, const void *key, void *next_key); |
| 104 | LIBBPF_API int bpf_obj_pin(int fd, const char *pathname); | 106 | LIBBPF_API int bpf_obj_pin(int fd, const char *pathname); |
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index d99dd6fc3fbe..e39dfb4e7970 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile | |||
| @@ -37,7 +37,7 @@ TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test | |||
| 37 | test_lwt_seg6local.o sendmsg4_prog.o sendmsg6_prog.o test_lirc_mode2_kern.o \ | 37 | test_lwt_seg6local.o sendmsg4_prog.o sendmsg6_prog.o test_lirc_mode2_kern.o \ |
| 38 | get_cgroup_id_kern.o socket_cookie_prog.o test_select_reuseport_kern.o \ | 38 | get_cgroup_id_kern.o socket_cookie_prog.o test_select_reuseport_kern.o \ |
| 39 | test_skb_cgroup_id_kern.o bpf_flow.o netcnt_prog.o \ | 39 | test_skb_cgroup_id_kern.o bpf_flow.o netcnt_prog.o \ |
| 40 | test_sk_lookup_kern.o test_xdp_vlan.o | 40 | test_sk_lookup_kern.o test_xdp_vlan.o test_queue_map.o test_stack_map.o |
| 41 | 41 | ||
| 42 | # Order correspond to 'make run_tests' order | 42 | # Order correspond to 'make run_tests' order |
| 43 | TEST_PROGS := test_kmod.sh \ | 43 | TEST_PROGS := test_kmod.sh \ |
| @@ -118,6 +118,9 @@ CLANG_FLAGS = -I. -I./include/uapi -I../../../include/uapi \ | |||
| 118 | $(OUTPUT)/test_l4lb_noinline.o: CLANG_FLAGS += -fno-inline | 118 | $(OUTPUT)/test_l4lb_noinline.o: CLANG_FLAGS += -fno-inline |
| 119 | $(OUTPUT)/test_xdp_noinline.o: CLANG_FLAGS += -fno-inline | 119 | $(OUTPUT)/test_xdp_noinline.o: CLANG_FLAGS += -fno-inline |
| 120 | 120 | ||
| 121 | $(OUTPUT)/test_queue_map.o: test_queue_stack_map.h | ||
| 122 | $(OUTPUT)/test_stack_map.o: test_queue_stack_map.h | ||
| 123 | |||
| 121 | BTF_LLC_PROBE := $(shell $(LLC) -march=bpf -mattr=help 2>&1 | grep dwarfris) | 124 | BTF_LLC_PROBE := $(shell $(LLC) -march=bpf -mattr=help 2>&1 | grep dwarfris) |
| 122 | BTF_PAHOLE_PROBE := $(shell $(BTF_PAHOLE) --help 2>&1 | grep BTF) | 125 | BTF_PAHOLE_PROBE := $(shell $(BTF_PAHOLE) --help 2>&1 | grep BTF) |
| 123 | BTF_OBJCOPY_PROBE := $(shell $(LLVM_OBJCOPY) --help 2>&1 | grep -i 'usage.*llvm') | 126 | BTF_OBJCOPY_PROBE := $(shell $(LLVM_OBJCOPY) --help 2>&1 | grep -i 'usage.*llvm') |
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h index fda8c162d0df..6407a3df0f3b 100644 --- a/tools/testing/selftests/bpf/bpf_helpers.h +++ b/tools/testing/selftests/bpf/bpf_helpers.h | |||
| @@ -16,6 +16,13 @@ static int (*bpf_map_update_elem)(void *map, void *key, void *value, | |||
| 16 | (void *) BPF_FUNC_map_update_elem; | 16 | (void *) BPF_FUNC_map_update_elem; |
| 17 | static int (*bpf_map_delete_elem)(void *map, void *key) = | 17 | static int (*bpf_map_delete_elem)(void *map, void *key) = |
| 18 | (void *) BPF_FUNC_map_delete_elem; | 18 | (void *) BPF_FUNC_map_delete_elem; |
| 19 | static int (*bpf_map_push_elem)(void *map, void *value, | ||
| 20 | unsigned long long flags) = | ||
| 21 | (void *) BPF_FUNC_map_push_elem; | ||
| 22 | static int (*bpf_map_pop_elem)(void *map, void *value) = | ||
| 23 | (void *) BPF_FUNC_map_pop_elem; | ||
| 24 | static int (*bpf_map_peek_elem)(void *map, void *value) = | ||
| 25 | (void *) BPF_FUNC_map_peek_elem; | ||
| 19 | static int (*bpf_probe_read)(void *dst, int size, void *unsafe_ptr) = | 26 | static int (*bpf_probe_read)(void *dst, int size, void *unsafe_ptr) = |
| 20 | (void *) BPF_FUNC_probe_read; | 27 | (void *) BPF_FUNC_probe_read; |
| 21 | static unsigned long long (*bpf_ktime_get_ns)(void) = | 28 | static unsigned long long (*bpf_ktime_get_ns)(void) = |
diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c index 9b552c0fc47d..4db2116e52be 100644 --- a/tools/testing/selftests/bpf/test_maps.c +++ b/tools/testing/selftests/bpf/test_maps.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <string.h> | 15 | #include <string.h> |
| 16 | #include <assert.h> | 16 | #include <assert.h> |
| 17 | #include <stdlib.h> | 17 | #include <stdlib.h> |
| 18 | #include <time.h> | ||
| 18 | 19 | ||
| 19 | #include <sys/wait.h> | 20 | #include <sys/wait.h> |
| 20 | #include <sys/socket.h> | 21 | #include <sys/socket.h> |
| @@ -471,6 +472,122 @@ static void test_devmap(int task, void *data) | |||
| 471 | close(fd); | 472 | close(fd); |
| 472 | } | 473 | } |
| 473 | 474 | ||
| 475 | static void test_queuemap(int task, void *data) | ||
| 476 | { | ||
| 477 | const int MAP_SIZE = 32; | ||
| 478 | __u32 vals[MAP_SIZE + MAP_SIZE/2], val; | ||
| 479 | int fd, i; | ||
| 480 | |||
| 481 | /* Fill test values to be used */ | ||
| 482 | for (i = 0; i < MAP_SIZE + MAP_SIZE/2; i++) | ||
| 483 | vals[i] = rand(); | ||
| 484 | |||
| 485 | /* Invalid key size */ | ||
| 486 | fd = bpf_create_map(BPF_MAP_TYPE_QUEUE, 4, sizeof(val), MAP_SIZE, | ||
| 487 | map_flags); | ||
| 488 | assert(fd < 0 && errno == EINVAL); | ||
| 489 | |||
| 490 | fd = bpf_create_map(BPF_MAP_TYPE_QUEUE, 0, sizeof(val), MAP_SIZE, | ||
| 491 | map_flags); | ||
| 492 | /* Queue map does not support BPF_F_NO_PREALLOC */ | ||
| 493 | if (map_flags & BPF_F_NO_PREALLOC) { | ||
| 494 | assert(fd < 0 && errno == EINVAL); | ||
| 495 | return; | ||
| 496 | } | ||
| 497 | if (fd < 0) { | ||
| 498 | printf("Failed to create queuemap '%s'!\n", strerror(errno)); | ||
| 499 | exit(1); | ||
| 500 | } | ||
| 501 | |||
| 502 | /* Push MAP_SIZE elements */ | ||
| 503 | for (i = 0; i < MAP_SIZE; i++) | ||
| 504 | assert(bpf_map_update_elem(fd, NULL, &vals[i], 0) == 0); | ||
| 505 | |||
| 506 | /* Check that element cannot be pushed due to max_entries limit */ | ||
| 507 | assert(bpf_map_update_elem(fd, NULL, &val, 0) == -1 && | ||
| 508 | errno == E2BIG); | ||
| 509 | |||
| 510 | /* Peek element */ | ||
| 511 | assert(bpf_map_lookup_elem(fd, NULL, &val) == 0 && val == vals[0]); | ||
| 512 | |||
| 513 | /* Replace half elements */ | ||
| 514 | for (i = MAP_SIZE; i < MAP_SIZE + MAP_SIZE/2; i++) | ||
| 515 | assert(bpf_map_update_elem(fd, NULL, &vals[i], BPF_EXIST) == 0); | ||
| 516 | |||
| 517 | /* Pop all elements */ | ||
| 518 | for (i = MAP_SIZE/2; i < MAP_SIZE + MAP_SIZE/2; i++) | ||
| 519 | assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == 0 && | ||
| 520 | val == vals[i]); | ||
| 521 | |||
| 522 | /* Check that there are not elements left */ | ||
| 523 | assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == -1 && | ||
| 524 | errno == ENOENT); | ||
| 525 | |||
| 526 | /* Check that non supported functions set errno to EINVAL */ | ||
| 527 | assert(bpf_map_delete_elem(fd, NULL) == -1 && errno == EINVAL); | ||
| 528 | assert(bpf_map_get_next_key(fd, NULL, NULL) == -1 && errno == EINVAL); | ||
| 529 | |||
| 530 | close(fd); | ||
| 531 | } | ||
| 532 | |||
| 533 | static void test_stackmap(int task, void *data) | ||
| 534 | { | ||
| 535 | const int MAP_SIZE = 32; | ||
| 536 | __u32 vals[MAP_SIZE + MAP_SIZE/2], val; | ||
| 537 | int fd, i; | ||
| 538 | |||
| 539 | /* Fill test values to be used */ | ||
| 540 | for (i = 0; i < MAP_SIZE + MAP_SIZE/2; i++) | ||
| 541 | vals[i] = rand(); | ||
| 542 | |||
| 543 | /* Invalid key size */ | ||
| 544 | fd = bpf_create_map(BPF_MAP_TYPE_STACK, 4, sizeof(val), MAP_SIZE, | ||
| 545 | map_flags); | ||
| 546 | assert(fd < 0 && errno == EINVAL); | ||
| 547 | |||
| 548 | fd = bpf_create_map(BPF_MAP_TYPE_STACK, 0, sizeof(val), MAP_SIZE, | ||
| 549 | map_flags); | ||
| 550 | /* Stack map does not support BPF_F_NO_PREALLOC */ | ||
| 551 | if (map_flags & BPF_F_NO_PREALLOC) { | ||
| 552 | assert(fd < 0 && errno == EINVAL); | ||
| 553 | return; | ||
| 554 | } | ||
| 555 | if (fd < 0) { | ||
| 556 | printf("Failed to create stackmap '%s'!\n", strerror(errno)); | ||
| 557 | exit(1); | ||
| 558 | } | ||
| 559 | |||
| 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); | ||
| 563 | |||
| 564 | /* Check that element cannot be pushed due to max_entries limit */ | ||
| 565 | assert(bpf_map_update_elem(fd, NULL, &val, 0) == -1 && | ||
| 566 | errno == E2BIG); | ||
