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

bpf: convert sockmap field attach_bpf_fd2 to type

In the initial sockmap API we provided strparser and verdict programs
using a single attach command by extending the attach API with a the
attach_bpf_fd2 field.

However, if we add other programs in the future we will be adding a
field for every new possible type, attach_bpf_fd(3,4,..). This
seems a bit clumsy for an API. So lets push the programs using two
new type fields.

BPF_SK_SKB_STREAM_PARSER
BPF_SK_SKB_STREAM_VERDICT

This has the advantage of having a readable name and can easily be
extended in the future.

Updates to samples and sockmap included here also generalize tests
slightly to support upcoming patch for multiple map support.

Signed-off-by: John Fastabend <john.fastabend@gmail.com>
Fixes: 174a79ff9515 ("bpf: sockmap with sk redirect support")
Suggested-by: Alexei Starovoitov <ast@kernel.org>
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
464bc0fd 901c5d2f

+121 -156
+8 -2
include/linux/bpf.h
··· 39 39 void (*map_fd_put_ptr)(void *ptr); 40 40 u32 (*map_gen_lookup)(struct bpf_map *map, struct bpf_insn *insn_buf); 41 41 u32 (*map_fd_sys_lookup_elem)(void *ptr); 42 - int (*map_attach)(struct bpf_map *map, 43 - struct bpf_prog *p1, struct bpf_prog *p2); 44 42 }; 45 43 46 44 struct bpf_map { ··· 385 387 386 388 #if defined(CONFIG_STREAM_PARSER) && defined(CONFIG_BPF_SYSCALL) 387 389 struct sock *__sock_map_lookup_elem(struct bpf_map *map, u32 key); 390 + int sock_map_attach_prog(struct bpf_map *map, struct bpf_prog *prog, u32 type); 388 391 #else 389 392 static inline struct sock *__sock_map_lookup_elem(struct bpf_map *map, u32 key) 390 393 { 391 394 return NULL; 395 + } 396 + 397 + static inline int sock_map_attach_prog(struct bpf_map *map, 398 + struct bpf_prog *prog, 399 + u32 type) 400 + { 401 + return -EOPNOTSUPP; 392 402 } 393 403 #endif 394 404
+3 -6
include/uapi/linux/bpf.h
··· 136 136 BPF_CGROUP_INET_EGRESS, 137 137 BPF_CGROUP_INET_SOCK_CREATE, 138 138 BPF_CGROUP_SOCK_OPS, 139 - BPF_CGROUP_SMAP_INGRESS, 139 + BPF_SK_SKB_STREAM_PARSER, 140 + BPF_SK_SKB_STREAM_VERDICT, 140 141 __MAX_BPF_ATTACH_TYPE 141 142 }; 142 143 ··· 225 224 __u32 attach_bpf_fd; /* eBPF program to attach */ 226 225 __u32 attach_type; 227 226 __u32 attach_flags; 228 - __u32 attach_bpf_fd2; 229 227 }; 230 228 231 229 struct { /* anonymous struct used by BPF_PROG_TEST_RUN command */ ··· 580 580 * @flags: reserved for future use 581 581 * Return: SK_REDIRECT 582 582 * 583 - * int bpf_sock_map_update(skops, map, key, flags, map_flags) 583 + * int bpf_sock_map_update(skops, map, key, flags) 584 584 * @skops: pointer to bpf_sock_ops 585 585 * @map: pointer to sockmap to update 586 586 * @key: key to insert/update sock in map 587 587 * @flags: same flags as map update elem 588 - * @map_flags: sock map specific flags 589 - * bit 1: Enable strparser 590 - * other bits: reserved 591 588 */ 592 589 #define __BPF_FUNC_MAPPER(FN) \ 593 590 FN(unspec), \
+14 -11
kernel/bpf/sockmap.c
··· 723 723 return err; 724 724 } 725 725 726 - static int sock_map_attach_prog(struct bpf_map *map, 727 - struct bpf_prog *parse, 728 - struct bpf_prog *verdict) 726 + int sock_map_attach_prog(struct bpf_map *map, struct bpf_prog *prog, u32 type) 729 727 { 730 728 struct bpf_stab *stab = container_of(map, struct bpf_stab, map); 731 - struct bpf_prog *_parse, *_verdict; 729 + struct bpf_prog *orig; 732 730 733 - _parse = xchg(&stab->bpf_parse, parse); 734 - _verdict = xchg(&stab->bpf_verdict, verdict); 731 + switch (type) { 732 + case BPF_SK_SKB_STREAM_PARSER: 733 + orig = xchg(&stab->bpf_parse, prog); 734 + break; 735 + case BPF_SK_SKB_STREAM_VERDICT: 736 + orig = xchg(&stab->bpf_verdict, prog); 737 + break; 738 + default: 739 + return -EOPNOTSUPP; 740 + } 735 741 736 - if (_parse) 737 - bpf_prog_put(_parse); 738 - if (_verdict) 739 - bpf_prog_put(_verdict); 742 + if (orig) 743 + bpf_prog_put(orig); 740 744 741 745 return 0; 742 746 } ··· 781 777 .map_get_next_key = sock_map_get_next_key, 782 778 .map_update_elem = sock_map_update_elem, 783 779 .map_delete_elem = sock_map_delete_elem, 784 - .map_attach = sock_map_attach_prog, 785 780 }; 786 781 787 782 BPF_CALL_5(bpf_sock_map_update, struct bpf_sock_ops_kern *, bpf_sock,
+11 -27
kernel/bpf/syscall.c
··· 1093 1093 1094 1094 #ifdef CONFIG_CGROUP_BPF 1095 1095 1096 - #define BPF_PROG_ATTACH_LAST_FIELD attach_bpf_fd2 1096 + #define BPF_PROG_ATTACH_LAST_FIELD attach_flags 1097 1097 1098 - static int sockmap_get_from_fd(const union bpf_attr *attr, int ptype) 1098 + static int sockmap_get_from_fd(const union bpf_attr *attr) 1099 1099 { 1100 - struct bpf_prog *prog1, *prog2; 1101 1100 int ufd = attr->target_fd; 1101 + struct bpf_prog *prog; 1102 1102 struct bpf_map *map; 1103 1103 struct fd f; 1104 1104 int err; ··· 1108 1108 if (IS_ERR(map)) 1109 1109 return PTR_ERR(map); 1110 1110 1111 - if (!map->ops->map_attach) { 1111 + prog = bpf_prog_get_type(attr->attach_bpf_fd, BPF_PROG_TYPE_SK_SKB); 1112 + if (IS_ERR(prog)) { 1112 1113 fdput(f); 1113 - return -EOPNOTSUPP; 1114 + return PTR_ERR(prog); 1114 1115 } 1115 1116 1116 - prog1 = bpf_prog_get_type(attr->attach_bpf_fd, ptype); 1117 - if (IS_ERR(prog1)) { 1118 - fdput(f); 1119 - return PTR_ERR(prog1); 1120 - } 1121 - 1122 - prog2 = bpf_prog_get_type(attr->attach_bpf_fd2, ptype); 1123 - if (IS_ERR(prog2)) { 1124 - fdput(f); 1125 - bpf_prog_put(prog1); 1126 - return PTR_ERR(prog2); 1127 - } 1128 - 1129 - err = map->ops->map_attach(map, prog1, prog2); 1117 + err = sock_map_attach_prog(map, prog, attr->attach_type); 1130 1118 if (err) { 1131 1119 fdput(f); 1132 - bpf_prog_put(prog1); 1133 - bpf_prog_put(prog2); 1120 + bpf_prog_put(prog); 1134 1121 return err; 1135 1122 } 1136 1123 ··· 1152 1165 case BPF_CGROUP_SOCK_OPS: 1153 1166 ptype = BPF_PROG_TYPE_SOCK_OPS; 1154 1167 break; 1155 - case BPF_CGROUP_SMAP_INGRESS: 1156 - ptype = BPF_PROG_TYPE_SK_SKB; 1157 - break; 1168 + case BPF_SK_SKB_STREAM_PARSER: 1169 + case BPF_SK_SKB_STREAM_VERDICT: 1170 + return sockmap_get_from_fd(attr); 1158 1171 default: 1159 1172 return -EINVAL; 1160 1173 } 1161 - 1162 - if (attr->attach_type == BPF_CGROUP_SMAP_INGRESS) 1163 - return sockmap_get_from_fd(attr, ptype); 1164 1174 1165 1175 prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype); 1166 1176 if (IS_ERR(prog))
+2 -4
samples/sockmap/sockmap_kern.c
··· 82 82 if (lport == 10000) { 83 83 ret = 1; 84 84 err = bpf_sock_map_update(skops, &sock_map, &ret, 85 - BPF_NOEXIST, 86 - BPF_SOCKMAP_STRPARSER); 85 + BPF_NOEXIST); 87 86 bpf_printk("passive(%i -> %i) map ctx update err: %d\n", 88 87 lport, bpf_ntohl(rport), err); 89 88 } ··· 94 95 if (bpf_ntohl(rport) == 10001) { 95 96 ret = 10; 96 97 err = bpf_sock_map_update(skops, &sock_map, &ret, 97 - BPF_NOEXIST, 98 - BPF_SOCKMAP_STRPARSER); 98 + BPF_NOEXIST); 99 99 bpf_printk("active(%i -> %i) map ctx update err: %d\n", 100 100 lport, bpf_ntohl(rport), err); 101 101 }
+10 -2
samples/sockmap/sockmap_user.c
··· 256 256 } 257 257 258 258 /* Attach programs to sockmap */ 259 - err = __bpf_prog_attach(prog_fd[0], prog_fd[1], map_fd[0], 260 - BPF_CGROUP_SMAP_INGRESS, 0); 259 + err = bpf_prog_attach(prog_fd[0], map_fd[0], 260 + BPF_SK_SKB_STREAM_PARSER, 0); 261 + if (err) { 262 + fprintf(stderr, "ERROR: bpf_prog_attach (sockmap): %d (%s)\n", 263 + err, strerror(errno)); 264 + return err; 265 + } 266 + 267 + err = bpf_prog_attach(prog_fd[1], map_fd[0], 268 + BPF_SK_SKB_STREAM_VERDICT, 0); 261 269 if (err) { 262 270 fprintf(stderr, "ERROR: bpf_prog_attach (sockmap): %d (%s)\n", 263 271 err, strerror(errno));
+3 -6
tools/include/uapi/linux/bpf.h
··· 136 136 BPF_CGROUP_INET_EGRESS, 137 137 BPF_CGROUP_INET_SOCK_CREATE, 138 138 BPF_CGROUP_SOCK_OPS, 139 - BPF_CGROUP_SMAP_INGRESS, 139 + BPF_SK_SKB_STREAM_PARSER, 140 + BPF_SK_SKB_STREAM_VERDICT, 140 141 __MAX_BPF_ATTACH_TYPE 141 142 }; 142 143 ··· 228 227 __u32 attach_bpf_fd; /* eBPF program to attach */ 229 228 __u32 attach_type; 230 229 __u32 attach_flags; 231 - __u32 attach_bpf_fd2; 232 230 }; 233 231 234 232 struct { /* anonymous struct used by BPF_PROG_TEST_RUN command */ ··· 572 572 * @flags: reserved for future use 573 573 * Return: SK_REDIRECT 574 574 * 575 - * int bpf_sock_map_update(skops, map, key, flags, map_flags) 575 + * int bpf_sock_map_update(skops, map, key, flags) 576 576 * @skops: pointer to bpf_sock_ops 577 577 * @map: pointer to sockmap to update 578 578 * @key: key to insert/update sock in map 579 579 * @flags: same flags as map update elem 580 - * @map_flags: sock map specific flags 581 - * bit 1: Enable strparser 582 - * other bits: reserved 583 580 */ 584 581 #define __BPF_FUNC_MAPPER(FN) \ 585 582 FN(unspec), \
+3 -11
tools/lib/bpf/bpf.c
··· 235 235 return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr)); 236 236 } 237 237 238 - int __bpf_prog_attach(int prog_fd1, int prog_fd2, int target_fd, 239 - enum bpf_attach_type type, 240 - unsigned int flags) 238 + int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type, 239 + unsigned int flags) 241 240 { 242 241 union bpf_attr attr; 243 242 244 243 bzero(&attr, sizeof(attr)); 245 244 attr.target_fd = target_fd; 246 - attr.attach_bpf_fd = prog_fd1; 247 - attr.attach_bpf_fd2 = prog_fd2; 245 + attr.attach_bpf_fd = prog_fd; 248 246 attr.attach_type = type; 249 247 attr.attach_flags = flags; 250 248 251 249 return sys_bpf(BPF_PROG_ATTACH, &attr, sizeof(attr)); 252 - } 253 - 254 - int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type, 255 - unsigned int flags) 256 - { 257 - return __bpf_prog_attach(prog_fd, 0, target_fd, type, flags); 258 250 } 259 251 260 252 int bpf_prog_detach(int target_fd, enum bpf_attach_type type)
-4
tools/lib/bpf/bpf.h
··· 56 56 int bpf_obj_get(const char *pathname); 57 57 int bpf_prog_attach(int prog_fd, int attachable_fd, enum bpf_attach_type type, 58 58 unsigned int flags); 59 - int __bpf_prog_attach(int prog1, int prog2, 60 - int attachable_fd, 61 - enum bpf_attach_type type, 62 - unsigned int flags); 63 59 int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type); 64 60 int bpf_prog_test_run(int prog_fd, int repeat, void *data, __u32 size, 65 61 void *data_out, __u32 *size_out, __u32 *retval,
+1 -2
tools/testing/selftests/bpf/bpf_helpers.h
··· 68 68 static int (*bpf_sk_redirect_map)(void *map, int key, int flags) = 69 69 (void *) BPF_FUNC_sk_redirect_map; 70 70 static int (*bpf_sock_map_update)(void *map, void *key, void *value, 71 - unsigned long long flags, 72 - unsigned long long map_lags) = 71 + unsigned long long flags) = 73 72 (void *) BPF_FUNC_sock_map_update; 74 73 75 74
+1 -1
tools/testing/selftests/bpf/sockmap_parse_prog.c
··· 30 30 */ 31 31 d[0] = 1; 32 32 33 - bpf_printk("data[0] = (%u): local_port %i remote %i\n", 33 + bpf_printk("parse: data[0] = (%u): local_port %i remote %i\n", 34 34 d[0], lport, bpf_ntohl(rport)); 35 35 return skb->len; 36 36 }
+1 -1
tools/testing/selftests/bpf/sockmap_verdict_prog.c
··· 40 40 d[6] = 0xe; 41 41 d[7] = 0xf; 42 42 43 - bpf_printk("data[0] = (%u): local_port %i remote %i\n", 43 + bpf_printk("verdict: data[0] = (%u): local_port %i remote %i redirect 5\n", 44 44 d[0], lport, bpf_ntohl(rport)); 45 45 return bpf_sk_redirect_map(&sock_map, 5, 0); 46 46 }
+64 -79
tools/testing/selftests/bpf/test_maps.c
··· 547 547 goto out_sockmap; 548 548 } 549 549 550 - /* Nothing attached so these should fail */ 550 + /* Test update without programs */ 551 551 for (i = 0; i < 6; i++) { 552 552 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); 553 - if (!err) { 554 - printf("Failed invalid update sockmap '%i:%i'\n", 553 + if (err) { 554 + printf("Failed noprog update sockmap '%i:%i'\n", 555 555 i, sfd[i]); 556 556 goto out_sockmap; 557 557 } 558 558 } 559 559 560 560 /* Test attaching bad fds */ 561 - err = __bpf_prog_attach(-1, -2, fd, BPF_CGROUP_SMAP_INGRESS, 0); 561 + err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_PARSER, 0); 562 562 if (!err) { 563 - printf("Failed invalid prog attach\n"); 563 + printf("Failed invalid parser prog attach\n"); 564 + goto out_sockmap; 565 + } 566 + 567 + err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_VERDICT, 0); 568 + if (!err) { 569 + printf("Failed invalid verdict prog attach\n"); 564 570 goto out_sockmap; 565 571 } 566 572 ··· 597 591 goto out_sockmap; 598 592 } 599 593 600 - err = __bpf_prog_attach(parse_prog, verdict_prog, map_fd, 601 - BPF_CGROUP_SMAP_INGRESS, 0); 594 + err = bpf_prog_attach(parse_prog, map_fd, 595 + BPF_SK_SKB_STREAM_PARSER, 0); 602 596 if (err) { 603 597 printf("Failed bpf prog attach\n"); 604 598 goto out_sockmap; 605 599 } 606 600 607 - /* Test map update elem */ 601 + err = bpf_prog_attach(verdict_prog, map_fd, 602 + BPF_SK_SKB_STREAM_VERDICT, 0); 603 + if (err) { 604 + printf("Failed bpf prog attach\n"); 605 + goto out_sockmap; 606 + } 607 + 608 + /* Test map update elem afterwards fd lives in fd and map_fd */ 608 609 for (i = 0; i < 6; i++) { 609 610 err = bpf_map_update_elem(map_fd, &i, &sfd[i], BPF_ANY); 610 611 if (err) { ··· 662 649 goto out_sockmap; 663 650 } 664 651 665 - /* Delete the reset of the elems include some NULL elems */ 666 - for (i = 0; i < 6; i++) { 667 - err = bpf_map_delete_elem(map_fd, &i); 668 - if (err && (i == 0 || i == 1 || i >= 4)) { 669 - printf("Failed delete sockmap %i '%i:%i'\n", 670 - err, i, sfd[i]); 671 - goto out_sockmap; 672 - } else if (!err && (i == 2 || i == 3)) { 673 - printf("Failed null delete sockmap %i '%i:%i'\n", 674 - err, i, sfd[i]); 675 - goto out_sockmap; 676 - } 677 - } 678 - 679 - /* Test having multiple SMAPs open and active on same fds */ 680 - err = __bpf_prog_attach(parse_prog, verdict_prog, fd, 681 - BPF_CGROUP_SMAP_INGRESS, 0); 682 - if (err) { 683 - printf("Failed fd bpf prog attach\n"); 684 - goto out_sockmap; 685 - } 686 - 687 - for (i = 0; i < 6; i++) { 688 - err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); 689 - if (err) { 690 - printf("Failed fd update sockmap %i '%i:%i'\n", 691 - err, i, sfd[i]); 692 - goto out_sockmap; 693 - } 694 - } 695 - 696 - /* Test duplicate socket add of NOEXIST, ANY and EXIST */ 697 - i = 0; 698 - err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST); 699 - if (!err) { 700 - printf("Failed BPF_NOEXIST create\n"); 701 - goto out_sockmap; 702 - } 703 - 704 - err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); 705 - if (err) { 706 - printf("Failed sockmap update BPF_ANY\n"); 707 - goto out_sockmap; 708 - } 709 - 710 - err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST); 711 - if (err) { 712 - printf("Failed sockmap update BPF_EXIST\n"); 713 - goto out_sockmap; 714 - } 715 - 716 - /* The above were pushing fd into same slot try different slot now */ 652 + /* Push fd into same slot */ 717 653 i = 2; 718 654 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST); 719 655 if (!err) { 720 - printf("Failed BPF_NOEXIST create\n"); 656 + printf("Failed allowed sockmap dup slot BPF_NOEXIST\n"); 721 657 goto out_sockmap; 722 658 } 723 659 724 660 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); 725 661 if (err) { 726 - printf("Failed sockmap update BPF_ANY\n"); 662 + printf("Failed sockmap update new slot BPF_ANY\n"); 727 663 goto out_sockmap; 728 664 } 729 665 730 666 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST); 731 667 if (err) { 732 - printf("Failed sockmap update BPF_EXIST\n"); 668 + printf("Failed sockmap update new slot BPF_EXIST\n"); 733 669 goto out_sockmap; 734 670 } 735 671 736 - /* Try pushing fd into different map, this is not allowed at the 737 - * moment. Which programs would we use? 738 - */ 739 - err = bpf_map_update_elem(map_fd, &i, &sfd[i], BPF_NOEXIST); 740 - if (!err) { 741 - printf("Failed BPF_NOEXIST create\n"); 672 + /* Delete the elems without programs */ 673 + for (i = 0; i < 6; i++) { 674 + err = bpf_map_delete_elem(fd, &i); 675 + if (err) { 676 + printf("Failed delete sockmap %i '%i:%i'\n", 677 + err, i, sfd[i]); 678 + } 679 + } 680 + 681 + /* Test having multiple maps open and set with programs on same fds */ 682 + err = bpf_prog_attach(parse_prog, fd, 683 + BPF_SK_SKB_STREAM_PARSER, 0); 684 + if (err) { 685 + printf("Failed fd bpf parse prog attach\n"); 686 + goto out_sockmap; 687 + } 688 + err = bpf_prog_attach(verdict_prog, fd, 689 + BPF_SK_SKB_STREAM_VERDICT, 0); 690 + if (err) { 691 + printf("Failed fd bpf verdict prog attach\n"); 742 692 goto out_sockmap; 743 693 } 744 694 745 - err = bpf_map_update_elem(map_fd, &i, &sfd[i], BPF_ANY); 746 - if (!err) { 747 - printf("Failed sockmap update BPF_ANY\n"); 748 - goto out_sockmap; 749 - } 750 - 751 - err = bpf_map_update_elem(map_fd, &i, &sfd[i], BPF_EXIST); 752 - if (!err) { 753 - printf("Failed sockmap update BPF_EXIST\n"); 754 - goto out_sockmap; 695 + for (i = 4; i < 6; i++) { 696 + err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); 697 + if (!err) { 698 + printf("Failed allowed duplicate programs in update ANY sockmap %i '%i:%i'\n", 699 + err, i, sfd[i]); 700 + goto out_sockmap; 701 + } 702 + err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST); 703 + if (!err) { 704 + printf("Failed allowed duplicate program in update NOEXIST sockmap %i '%i:%i'\n", 705 + err, i, sfd[i]); 706 + goto out_sockmap; 707 + } 708 + err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST); 709 + if (!err) { 710 + printf("Failed allowed duplicate program in update EXIST sockmap %i '%i:%i'\n", 711 + err, i, sfd[i]); 712 + goto out_sockmap; 713 + } 755 714 } 756 715 757 716 /* Test map close sockets */