Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: additional sockmap self tests

Add some more sockmap tests to cover,

- forwarding to NULL entries
- more than two maps to test list ops
- forwarding to different map

Signed-off-by: John Fastabend <john.fastabend@gmail.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

John Fastabend and committed by
David S. Miller
6fd28865 d26e597d

+98 -48
+3 -3
tools/testing/selftests/bpf/sockmap_parse_prog.c
··· 19 19 void *data = (void *)(long) skb->data; 20 20 __u32 lport = skb->local_port; 21 21 __u32 rport = skb->remote_port; 22 - char *d = data; 22 + __u8 *d = data; 23 23 24 - if (data + 8 > data_end) 24 + if (data + 10 > data_end) 25 25 return skb->len; 26 26 27 27 /* This write/read is a bit pointless but tests the verifier and 28 28 * strparser handler for read/write pkt data and access into sk 29 29 * fields. 30 30 */ 31 - d[0] = 1; 31 + d[7] = 1; 32 32 33 33 bpf_printk("parse: data[0] = (%u): local_port %i remote %i\n", 34 34 d[0], lport, bpf_ntohl(rport));
+18 -5
tools/testing/selftests/bpf/sockmap_verdict_prog.c
··· 12 12 ##__VA_ARGS__); \ 13 13 }) 14 14 15 - struct bpf_map_def SEC("maps") sock_map = { 15 + struct bpf_map_def SEC("maps") sock_map_rx = { 16 + .type = BPF_MAP_TYPE_SOCKMAP, 17 + .key_size = sizeof(int), 18 + .value_size = sizeof(int), 19 + .max_entries = 20, 20 + }; 21 + 22 + struct bpf_map_def SEC("maps") sock_map_tx = { 16 23 .type = BPF_MAP_TYPE_SOCKMAP, 17 24 .key_size = sizeof(int), 18 25 .value_size = sizeof(int), ··· 33 26 void *data = (void *)(long) skb->data; 34 27 __u32 lport = skb->local_port; 35 28 __u32 rport = skb->remote_port; 36 - char *d = data; 29 + __u8 *d = data; 30 + __u8 sk, map; 37 31 38 32 if (data + 8 > data_end) 39 33 return SK_DROP; 34 + 35 + map = d[0]; 36 + sk = d[1]; 40 37 41 38 d[0] = 0xd; 42 39 d[1] = 0xe; ··· 51 40 d[6] = 0xe; 52 41 d[7] = 0xf; 53 42 54 - bpf_printk("verdict: data[0] = (%u): local_port %i remote %i redirect 5\n", 55 - d[0], lport, bpf_ntohl(rport)); 56 - return bpf_sk_redirect_map(&sock_map, 5, 0); 43 + bpf_printk("verdict: data[0] = redir(%u:%u)\n", map, sk); 44 + 45 + if (!map) 46 + return bpf_sk_redirect_map(&sock_map_rx, sk, 0); 47 + return bpf_sk_redirect_map(&sock_map_tx, sk, 0); 57 48 } 58 49 59 50 char _license[] SEC("license") = "GPL";
+77 -40
tools/testing/selftests/bpf/test_maps.c
··· 465 465 { 466 466 int ports[] = {50200, 50201, 50202, 50204}; 467 467 int err, i, fd, sfd[6] = {0xdeadbeef}; 468 - char buf[] = "hello sockmap user\n"; 469 - int one = 1, map_fd, s, sc, rc; 468 + u8 buf[20] = {0x0, 0x5, 0x3, 0x2, 0x1, 0x0}; 469 + int one = 1, map_fd_rx, map_fd_tx, s, sc, rc; 470 470 int parse_prog, verdict_prog; 471 - struct bpf_map *bpf_map; 471 + struct bpf_map *bpf_map_rx, *bpf_map_tx; 472 472 struct sockaddr_in addr; 473 473 struct bpf_object *obj; 474 474 struct timeval to; ··· 585 585 goto out_sockmap; 586 586 } 587 587 588 - bpf_map = bpf_object__find_map_by_name(obj, "sock_map"); 589 - if (IS_ERR(bpf_map)) { 590 - printf("Failed to load map from verdict prog\n"); 588 + bpf_map_rx = bpf_object__find_map_by_name(obj, "sock_map_rx"); 589 + if (IS_ERR(bpf_map_rx)) { 590 + printf("Failed to load map rx from verdict prog\n"); 591 591 goto out_sockmap; 592 592 } 593 593 594 - map_fd = bpf_map__fd(bpf_map); 595 - if (map_fd < 0) { 594 + map_fd_rx = bpf_map__fd(bpf_map_rx); 595 + if (map_fd_rx < 0) { 596 596 printf("Failed to get map fd\n"); 597 597 goto out_sockmap; 598 598 } 599 599 600 - err = bpf_prog_attach(parse_prog, map_fd, 600 + bpf_map_tx = bpf_object__find_map_by_name(obj, "sock_map_tx"); 601 + if (IS_ERR(bpf_map_tx)) { 602 + printf("Failed to load map tx from verdict prog\n"); 603 + goto out_sockmap; 604 + } 605 + 606 + map_fd_tx = bpf_map__fd(bpf_map_tx); 607 + if (map_fd_tx < 0) { 608 + printf("Failed to get map tx fd\n"); 609 + goto out_sockmap; 610 + } 611 + 612 + err = bpf_prog_attach(parse_prog, map_fd_rx, 601 613 BPF_SK_SKB_STREAM_PARSER, 0); 602 614 if (err) { 603 615 printf("Failed bpf prog attach\n"); 604 616 goto out_sockmap; 605 617 } 606 618 607 - err = bpf_prog_attach(verdict_prog, map_fd, 619 + err = bpf_prog_attach(verdict_prog, map_fd_rx, 608 620 BPF_SK_SKB_STREAM_VERDICT, 0); 609 621 if (err) { 610 622 printf("Failed bpf prog attach\n"); ··· 625 613 626 614 /* Test map update elem afterwards fd lives in fd and map_fd */ 627 615 for (i = 0; i < 6; i++) { 628 - err = bpf_map_update_elem(map_fd, &i, &sfd[i], BPF_ANY); 616 + err = bpf_map_update_elem(map_fd_rx, &i, &sfd[i], BPF_ANY); 629 617 if (err) { 630 - printf("Failed map_fd update sockmap %i '%i:%i'\n", 618 + printf("Failed map_fd_rx update sockmap %i '%i:%i'\n", 619 + err, i, sfd[i]); 620 + goto out_sockmap; 621 + } 622 + err = bpf_map_update_elem(map_fd_tx, &i, &sfd[i], BPF_ANY); 623 + if (err) { 624 + printf("Failed map_fd_tx update sockmap %i '%i:%i'\n", 631 625 err, i, sfd[i]); 632 626 goto out_sockmap; 633 627 } ··· 641 623 642 624 /* Test map delete elem and remove send/recv sockets */ 643 625 for (i = 2; i < 4; i++) { 644 - err = bpf_map_delete_elem(map_fd, &i); 626 + err = bpf_map_delete_elem(map_fd_rx, &i); 645 627 if (err) { 646 - printf("Failed delete sockmap %i '%i:%i'\n", 628 + printf("Failed delete sockmap rx %i '%i:%i'\n", 629 + err, i, sfd[i]); 630 + goto out_sockmap; 631 + } 632 + err = bpf_map_delete_elem(map_fd_tx, &i); 633 + if (err) { 634 + printf("Failed delete sockmap tx %i '%i:%i'\n", 647 635 err, i, sfd[i]); 648 636 goto out_sockmap; 649 637 } 650 638 } 651 639 652 640 /* Test map send/recv */ 653 - sc = send(sfd[2], buf, 10, 0); 641 + for (i = 0; i < 2; i++) { 642 + buf[0] = i; 643 + buf[1] = 0x5; 644 + sc = send(sfd[2], buf, 20, 0); 645 + if (sc < 0) { 646 + printf("Failed sockmap send\n"); 647 + goto out_sockmap; 648 + } 649 + 650 + FD_ZERO(&w); 651 + FD_SET(sfd[3], &w); 652 + to.tv_sec = 1; 653 + to.tv_usec = 0; 654 + s = select(sfd[3] + 1, &w, NULL, NULL, &to); 655 + if (s == -1) { 656 + perror("Failed sockmap select()"); 657 + goto out_sockmap; 658 + } else if (!s) { 659 + printf("Failed sockmap unexpected timeout\n"); 660 + goto out_sockmap; 661 + } 662 + 663 + if (!FD_ISSET(sfd[3], &w)) { 664 + printf("Failed sockmap select/recv\n"); 665 + goto out_sockmap; 666 + } 667 + 668 + rc = recv(sfd[3], buf, sizeof(buf), 0); 669 + if (rc < 0) { 670 + printf("Failed sockmap recv\n"); 671 + goto out_sockmap; 672 + } 673 + } 674 + 675 + /* Negative null entry lookup from datapath should be dropped */ 676 + buf[0] = 1; 677 + buf[1] = 12; 678 + sc = send(sfd[2], buf, 20, 0); 654 679 if (sc < 0) { 655 680 printf("Failed sockmap send\n"); 656 - goto out_sockmap; 657 - } 658 - 659 - FD_ZERO(&w); 660 - FD_SET(sfd[3], &w); 661 - to.tv_sec = 1; 662 - to.tv_usec = 0; 663 - s = select(sfd[3] + 1, &w, NULL, NULL, &to); 664 - if (s == -1) { 665 - perror("Failed sockmap select()"); 666 - goto out_sockmap; 667 - } else if (!s) { 668 - printf("Failed sockmap unexpected timeout\n"); 669 - goto out_sockmap; 670 - } 671 - 672 - if (!FD_ISSET(sfd[3], &w)) { 673 - printf("Failed sockmap select/recv\n"); 674 - goto out_sockmap; 675 - } 676 - 677 - rc = recv(sfd[3], buf, sizeof(buf), 0); 678 - if (rc < 0) { 679 - printf("Failed sockmap recv\n"); 680 681 goto out_sockmap; 681 682 } 682 683 ··· 767 730 for (i = 0; i < 6; i++) 768 731 close(sfd[i]); 769 732 close(fd); 770 - close(map_fd); 733 + close(map_fd_rx); 771 734 bpf_object__close(obj); 772 735 return; 773 736 out: