diff options
author | Yonghong Song <yhs@fb.com> | 2018-01-18 18:08:51 -0500 |
---|---|---|
committer | Daniel Borkmann <daniel@iogearbox.net> | 2018-01-19 17:26:41 -0500 |
commit | 8c417dc15f9522672795981dcb63d9099ca6bd8c (patch) | |
tree | b6d14d27dd9c79219b79291db99683a4ba8b9f07 /tools | |
parent | b471f2f1de8b816f1e799b80aa92588f3566e4bd (diff) |
tools/bpf: add a testcase for MAP_GET_NEXT_KEY command of LPM_TRIE map
A test case is added in tools/testing/selftests/bpf/test_lpm_map.c
for MAP_GET_NEXT_KEY command. A four node trie, which
is described in kernel/bpf/lpm_trie.c, is built and the
MAP_GET_NEXT_KEY results are checked.
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/testing/selftests/bpf/test_lpm_map.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/tools/testing/selftests/bpf/test_lpm_map.c b/tools/testing/selftests/bpf/test_lpm_map.c index f61480641b6e..081510853c6d 100644 --- a/tools/testing/selftests/bpf/test_lpm_map.c +++ b/tools/testing/selftests/bpf/test_lpm_map.c | |||
@@ -521,6 +521,126 @@ static void test_lpm_delete(void) | |||
521 | close(map_fd); | 521 | close(map_fd); |
522 | } | 522 | } |
523 | 523 | ||
524 | static void test_lpm_get_next_key(void) | ||
525 | { | ||
526 | struct bpf_lpm_trie_key *key_p, *next_key_p; | ||
527 | size_t key_size; | ||
528 | __u32 value = 0; | ||
529 | int map_fd; | ||
530 | |||
531 | key_size = sizeof(*key_p) + sizeof(__u32); | ||
532 | key_p = alloca(key_size); | ||
533 | next_key_p = alloca(key_size); | ||
534 | |||
535 | map_fd = bpf_create_map(BPF_MAP_TYPE_LPM_TRIE, key_size, sizeof(value), | ||
536 | 100, BPF_F_NO_PREALLOC); | ||
537 | assert(map_fd >= 0); | ||
538 | |||
539 | /* empty tree. get_next_key should return ENOENT */ | ||
540 | assert(bpf_map_get_next_key(map_fd, NULL, key_p) == -1 && | ||
541 | errno == ENOENT); | ||
542 | |||
543 | /* get and verify the first key, get the second one should fail. */ | ||
544 | key_p->prefixlen = 16; | ||
545 | inet_pton(AF_INET, "192.168.0.0", key_p->data); | ||
546 | assert(bpf_map_update_elem(map_fd, key_p, &value, 0) == 0); | ||
547 | |||
548 | memset(key_p, 0, key_size); | ||
549 | assert(bpf_map_get_next_key(map_fd, NULL, key_p) == 0); | ||
550 | assert(key_p->prefixlen == 16 && key_p->data[0] == 192 && | ||
551 | key_p->data[1] == 168); | ||
552 | |||
553 | assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == -1 && | ||
554 | errno == ENOENT); | ||
555 | |||
556 | /* no exact matching key should get the first one in post order. */ | ||
557 | key_p->prefixlen = 8; | ||
558 | assert(bpf_map_get_next_key(map_fd, NULL, key_p) == 0); | ||
559 | assert(key_p->prefixlen == 16 && key_p->data[0] == 192 && | ||
560 | key_p->data[1] == 168); | ||
561 | |||
562 | /* add one more element (total two) */ | ||
563 | key_p->prefixlen = 24; | ||
564 | inet_pton(AF_INET, "192.168.0.0", key_p->data); | ||
565 | assert(bpf_map_update_elem(map_fd, key_p, &value, 0) == 0); | ||
566 | |||
567 | memset(key_p, 0, key_size); | ||
568 | assert(bpf_map_get_next_key(map_fd, NULL, key_p) == 0); | ||
569 | assert(key_p->prefixlen == 24 && key_p->data[0] == 192 && | ||
570 | key_p->data[1] == 168 && key_p->data[2] == 0); | ||
571 | |||
572 | memset(next_key_p, 0, key_size); | ||
573 | assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0); | ||
574 | assert(next_key_p->prefixlen == 16 && next_key_p->data[0] == 192 && | ||
575 | next_key_p->data[1] == 168); | ||
576 | |||
577 | memcpy(key_p, next_key_p, key_size); | ||
578 | assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == -1 && | ||
579 | errno == ENOENT); | ||
580 | |||
581 | /* Add one more element (total three) */ | ||
582 | key_p->prefixlen = 24; | ||
583 | inet_pton(AF_INET, "192.168.128.0", key_p->data); | ||
584 | assert(bpf_map_update_elem(map_fd, key_p, &value, 0) == 0); | ||
585 | |||
586 | memset(key_p, 0, key_size); | ||
587 | assert(bpf_map_get_next_key(map_fd, NULL, key_p) == 0); | ||
588 | assert(key_p->prefixlen == 24 && key_p->data[0] == 192 && | ||
589 | key_p->data[1] == 168 && key_p->data[2] == 0); | ||
590 | |||
591 | memset(next_key_p, 0, key_size); | ||
592 | assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0); | ||
593 | assert(next_key_p->prefixlen == 24 && next_key_p->data[0] == 192 && | ||
594 | next_key_p->data[1] == 168 && next_key_p->data[2] == 128); | ||
595 | |||
596 | memcpy(key_p, next_key_p, key_size); | ||
597 | assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0); | ||
598 | assert(next_key_p->prefixlen == 16 && next_key_p->data[0] == 192 && | ||
599 | next_key_p->data[1] == 168); | ||
600 | |||
601 | memcpy(key_p, next_key_p, key_size); | ||
602 | assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == -1 && | ||
603 | errno == ENOENT); | ||
604 | |||
605 | /* Add one more element (total four) */ | ||
606 | key_p->prefixlen = 24; | ||
607 | inet_pton(AF_INET, "192.168.1.0", key_p->data); | ||
608 | assert(bpf_map_update_elem(map_fd, key_p, &value, 0) == 0); | ||
609 | |||
610 | memset(key_p, 0, key_size); | ||
611 | assert(bpf_map_get_next_key(map_fd, NULL, key_p) == 0); | ||
612 | assert(key_p->prefixlen == 24 && key_p->data[0] == 192 && | ||
613 | key_p->data[1] == 168 && key_p->data[2] == 0); | ||
614 | |||
615 | memset(next_key_p, 0, key_size); | ||
616 | assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0); | ||
617 | assert(next_key_p->prefixlen == 24 && next_key_p->data[0] == 192 && | ||
618 | next_key_p->data[1] == 168 && next_key_p->data[2] == 1); | ||
619 | |||
620 | memcpy(key_p, next_key_p, key_size); | ||
621 | assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0); | ||
622 | assert(next_key_p->prefixlen == 24 && next_key_p->data[0] == 192 && | ||
623 | next_key_p->data[1] == 168 && next_key_p->data[2] == 128); | ||
624 | |||
625 | memcpy(key_p, next_key_p, key_size); | ||
626 | assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0); | ||
627 | assert(next_key_p->prefixlen == 16 && next_key_p->data[0] == 192 && | ||
628 | next_key_p->data[1] == 168); | ||
629 | |||
630 | memcpy(key_p, next_key_p, key_size); | ||
631 | assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == -1 && | ||
632 | errno == ENOENT); | ||
633 | |||
634 | /* no exact matching key should return the first one in post order */ | ||
635 | key_p->prefixlen = 22; | ||
636 | inet_pton(AF_INET, "192.168.1.0", key_p->data); | ||
637 | assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0); | ||
638 | assert(next_key_p->prefixlen == 24 && next_key_p->data[0] == 192 && | ||
639 | next_key_p->data[1] == 168 && next_key_p->data[2] == 0); | ||
640 | |||
641 | close(map_fd); | ||
642 | } | ||
643 | |||
524 | int main(void) | 644 | int main(void) |
525 | { | 645 | { |
526 | struct rlimit limit = { RLIM_INFINITY, RLIM_INFINITY }; | 646 | struct rlimit limit = { RLIM_INFINITY, RLIM_INFINITY }; |
@@ -545,6 +665,8 @@ int main(void) | |||
545 | 665 | ||
546 | test_lpm_delete(); | 666 | test_lpm_delete(); |
547 | 667 | ||
668 | test_lpm_get_next_key(); | ||
669 | |||
548 | printf("test_lpm: OK\n"); | 670 | printf("test_lpm: OK\n"); |
549 | return 0; | 671 | return 0; |
550 | } | 672 | } |