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

bpf: add map tests for BPF_PROG_TYPE_SK_MSG

Add map tests to attach BPF_PROG_TYPE_SK_MSG types to a sockmap.

Signed-off-by: John Fastabend <john.fastabend@gmail.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>

authored by

John Fastabend and committed by
Daniel Borkmann
82a86168 015632bb

+118 -7
+10
tools/include/uapi/linux/bpf.h
··· 133 133 BPF_PROG_TYPE_SOCK_OPS, 134 134 BPF_PROG_TYPE_SK_SKB, 135 135 BPF_PROG_TYPE_CGROUP_DEVICE, 136 + BPF_PROG_TYPE_SK_MSG, 136 137 }; 137 138 138 139 enum bpf_attach_type { ··· 144 143 BPF_SK_SKB_STREAM_PARSER, 145 144 BPF_SK_SKB_STREAM_VERDICT, 146 145 BPF_CGROUP_DEVICE, 146 + BPF_SK_MSG_VERDICT, 147 147 __MAX_BPF_ATTACH_TYPE 148 148 }; 149 149 ··· 941 939 enum sk_action { 942 940 SK_DROP = 0, 943 941 SK_PASS, 942 + }; 943 + 944 + /* user accessible metadata for SK_MSG packet hook, new fields must 945 + * be added to the end of this structure 946 + */ 947 + struct sk_msg_md { 948 + void *data; 949 + void *data_end; 944 950 }; 945 951 946 952 #define BPF_TAG_SIZE 8
+2 -1
tools/testing/selftests/bpf/Makefile
··· 29 29 test_pkt_md_access.o test_xdp_redirect.o test_xdp_meta.o sockmap_parse_prog.o \ 30 30 sockmap_verdict_prog.o dev_cgroup.o sample_ret0.o test_tracepoint.o \ 31 31 test_l4lb_noinline.o test_xdp_noinline.o test_stacktrace_map.o \ 32 - sample_map_ret0.o test_tcpbpf_kern.o test_stacktrace_build_id.o 32 + sample_map_ret0.o test_tcpbpf_kern.o test_stacktrace_build_id.o \ 33 + sockmap_tcp_msg_prog.o 33 34 34 35 # Order correspond to 'make run_tests' order 35 36 TEST_PROGS := test_kmod.sh \
+2
tools/testing/selftests/bpf/bpf_helpers.h
··· 123 123 (void *) BPF_FUNC_skb_under_cgroup; 124 124 static int (*bpf_skb_change_head)(void *, int len, int flags) = 125 125 (void *) BPF_FUNC_skb_change_head; 126 + static int (*bpf_skb_pull_data)(void *, int len) = 127 + (void *) BPF_FUNC_skb_pull_data; 126 128 127 129 /* Scan the ARCH passed in from ARCH env variable (see Makefile) */ 128 130 #if defined(__TARGET_ARCH_x86)
+13 -2
tools/testing/selftests/bpf/sockmap_parse_prog.c
··· 20 20 __u32 lport = skb->local_port; 21 21 __u32 rport = skb->remote_port; 22 22 __u8 *d = data; 23 + __u32 len = (__u32) data_end - (__u32) data; 24 + int err; 23 25 24 - if (data + 10 > data_end) 25 - return skb->len; 26 + if (data + 10 > data_end) { 27 + err = bpf_skb_pull_data(skb, 10); 28 + if (err) 29 + return SK_DROP; 30 + 31 + data_end = (void *)(long)skb->data_end; 32 + data = (void *)(long)skb->data; 33 + if (data + 10 > data_end) 34 + return SK_DROP; 35 + } 26 36 27 37 /* This write/read is a bit pointless but tests the verifier and 28 38 * strparser handler for read/write pkt data and access into sk 29 39 * fields. 30 40 */ 41 + d = data; 31 42 d[7] = 1; 32 43 return skb->len; 33 44 }
+33
tools/testing/selftests/bpf/sockmap_tcp_msg_prog.c
··· 1 + #include <linux/bpf.h> 2 + #include "bpf_helpers.h" 3 + #include "bpf_util.h" 4 + #include "bpf_endian.h" 5 + 6 + int _version SEC("version") = 1; 7 + 8 + #define bpf_printk(fmt, ...) \ 9 + ({ \ 10 + char ____fmt[] = fmt; \ 11 + bpf_trace_printk(____fmt, sizeof(____fmt), \ 12 + ##__VA_ARGS__); \ 13 + }) 14 + 15 + SEC("sk_msg1") 16 + int bpf_prog1(struct sk_msg_md *msg) 17 + { 18 + void *data_end = (void *)(long) msg->data_end; 19 + void *data = (void *)(long) msg->data; 20 + 21 + char *d; 22 + 23 + if (data + 8 > data_end) 24 + return SK_DROP; 25 + 26 + bpf_printk("data length %i\n", (__u64)msg->data_end - (__u64)msg->data); 27 + d = (char *)data; 28 + bpf_printk("hello sendmsg hook %i %i\n", d[0], d[1]); 29 + 30 + return SK_PASS; 31 + } 32 + 33 + char _license[] SEC("license") = "GPL";
+7
tools/testing/selftests/bpf/sockmap_verdict_prog.c
··· 26 26 .max_entries = 20, 27 27 }; 28 28 29 + struct bpf_map_def SEC("maps") sock_map_msg = { 30 + .type = BPF_MAP_TYPE_SOCKMAP, 31 + .key_size = sizeof(int), 32 + .value_size = sizeof(int), 33 + .max_entries = 20, 34 + }; 35 + 29 36 struct bpf_map_def SEC("maps") sock_map_break = { 30 37 .type = BPF_MAP_TYPE_ARRAY, 31 38 .key_size = sizeof(int),
+51 -4
tools/testing/selftests/bpf/test_maps.c
··· 464 464 #include <linux/err.h> 465 465 #define SOCKMAP_PARSE_PROG "./sockmap_parse_prog.o" 466 466 #define SOCKMAP_VERDICT_PROG "./sockmap_verdict_prog.o" 467 + #define SOCKMAP_TCP_MSG_PROG "./sockmap_tcp_msg_prog.o" 467 468 static void test_sockmap(int tasks, void *data) 468 469 { 469 - int one = 1, map_fd_rx = 0, map_fd_tx = 0, map_fd_break, s, sc, rc; 470 - struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_break; 470 + struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_msg, *bpf_map_break; 471 + int map_fd_msg = 0, map_fd_rx = 0, map_fd_tx = 0, map_fd_break; 471 472 int ports[] = {50200, 50201, 50202, 50204}; 472 473 int err, i, fd, udp, sfd[6] = {0xdeadbeef}; 473 474 u8 buf[20] = {0x0, 0x5, 0x3, 0x2, 0x1, 0x0}; 474 - int parse_prog, verdict_prog; 475 + int parse_prog, verdict_prog, msg_prog; 475 476 struct sockaddr_in addr; 477 + int one = 1, s, sc, rc; 476 478 struct bpf_object *obj; 477 479 struct timeval to; 478 480 __u32 key, value; ··· 586 584 goto out_sockmap; 587 585 } 588 586 587 + err = bpf_prog_attach(-1, fd, BPF_SK_MSG_VERDICT, 0); 588 + if (!err) { 589 + printf("Failed invalid msg verdict prog attach\n"); 590 + goto out_sockmap; 591 + } 592 + 589 593 err = bpf_prog_attach(-1, fd, __MAX_BPF_ATTACH_TYPE, 0); 590 594 if (!err) { 591 595 printf("Failed unknown prog attach\n"); ··· 610 602 goto out_sockmap; 611 603 } 612 604 605 + err = bpf_prog_detach(fd, BPF_SK_MSG_VERDICT); 606 + if (err) { 607 + printf("Failed empty msg verdict prog detach\n"); 608 + goto out_sockmap; 609 + } 610 + 613 611 err = bpf_prog_detach(fd, __MAX_BPF_ATTACH_TYPE); 614 612 if (!err) { 615 613 printf("Detach invalid prog successful\n"); ··· 627 613 BPF_PROG_TYPE_SK_SKB, &obj, &parse_prog); 628 614 if (err) { 629 615 printf("Failed to load SK_SKB parse prog\n"); 616 + goto out_sockmap; 617 + } 618 + 619 + err = bpf_prog_load(SOCKMAP_TCP_MSG_PROG, 620 + BPF_PROG_TYPE_SK_MSG, &obj, &msg_prog); 621 + if (err) { 622 + printf("Failed to load SK_SKB msg prog\n"); 630 623 goto out_sockmap; 631 624 } 632 625 ··· 652 631 653 632 map_fd_rx = bpf_map__fd(bpf_map_rx); 654 633 if (map_fd_rx < 0) { 655 - printf("Failed to get map fd\n"); 634 + printf("Failed to get map rx fd\n"); 656 635 goto out_sockmap; 657 636 } 658 637 ··· 665 644 map_fd_tx = bpf_map__fd(bpf_map_tx); 666 645 if (map_fd_tx < 0) { 667 646 printf("Failed to get map tx fd\n"); 647 + goto out_sockmap; 648 + } 649 + 650 + bpf_map_msg = bpf_object__find_map_by_name(obj, "sock_map_msg"); 651 + if (IS_ERR(bpf_map_msg)) { 652 + printf("Failed to load map msg from msg_verdict prog\n"); 653 + goto out_sockmap; 654 + } 655 + 656 + map_fd_msg = bpf_map__fd(bpf_map_msg); 657 + if (map_fd_msg < 0) { 658 + printf("Failed to get map msg fd\n"); 668 659 goto out_sockmap; 669 660 } 670 661 ··· 710 677 BPF_SK_SKB_STREAM_VERDICT, 0); 711 678 if (err) { 712 679 printf("Failed stream verdict bpf prog attach\n"); 680 + goto out_sockmap; 681 + } 682 + 683 + err = bpf_prog_attach(msg_prog, map_fd_msg, BPF_SK_MSG_VERDICT, 0); 684 + if (err) { 685 + printf("Failed msg verdict bpf prog attach\n"); 713 686 goto out_sockmap; 714 687 } 715 688 ··· 756 717 err, i, sfd[i]); 757 718 goto out_sockmap; 758 719 } 720 + } 721 + 722 + /* Put sfd[2] (sending fd below) into msg map to test sendmsg bpf */ 723 + i = 0; 724 + err = bpf_map_update_elem(map_fd_msg, &i, &sfd[2], BPF_ANY); 725 + if (err) { 726 + printf("Failed map_fd_msg update sockmap %i\n", err); 727 + goto out_sockmap; 759 728 } 760 729 761 730 /* Test map send/recv */