Loading samples/bpf/bpf_load.c +6 −2 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size) bool is_cgroup_sk = strncmp(event, "cgroup/sock", 11) == 0; bool is_sockops = strncmp(event, "sockops", 7) == 0; bool is_sk_skb = strncmp(event, "sk_skb", 6) == 0; bool is_sk_msg = strncmp(event, "sk_msg", 6) == 0; size_t insns_cnt = size / sizeof(struct bpf_insn); enum bpf_prog_type prog_type; char buf[256]; Loading Loading @@ -96,6 +97,8 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size) prog_type = BPF_PROG_TYPE_SOCK_OPS; } else if (is_sk_skb) { prog_type = BPF_PROG_TYPE_SK_SKB; } else if (is_sk_msg) { prog_type = BPF_PROG_TYPE_SK_MSG; } else { printf("Unknown event '%s'\n", event); return -1; Loading @@ -113,7 +116,7 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size) if (is_xdp || is_perf_event || is_cgroup_skb || is_cgroup_sk) return 0; if (is_socket || is_sockops || is_sk_skb) { if (is_socket || is_sockops || is_sk_skb || is_sk_msg) { if (is_socket) event += 6; else Loading Loading @@ -589,7 +592,8 @@ static int do_load_bpf_file(const char *path, fixup_map_cb fixup_map) memcmp(shname, "socket", 6) == 0 || memcmp(shname, "cgroup/", 7) == 0 || memcmp(shname, "sockops", 7) == 0 || memcmp(shname, "sk_skb", 6) == 0) { memcmp(shname, "sk_skb", 6) == 0 || memcmp(shname, "sk_msg", 6) == 0) { ret = load_and_attach(shname, data->d_buf, data->d_size); if (ret != 0) Loading samples/sockmap/sockmap_kern.c +52 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,20 @@ struct bpf_map_def SEC("maps") sock_map = { .max_entries = 20, }; struct bpf_map_def SEC("maps") sock_map_txmsg = { .type = BPF_MAP_TYPE_SOCKMAP, .key_size = sizeof(int), .value_size = sizeof(int), .max_entries = 20, }; struct bpf_map_def SEC("maps") sock_map_redir = { .type = BPF_MAP_TYPE_SOCKMAP, .key_size = sizeof(int), .value_size = sizeof(int), .max_entries = 1, }; SEC("sk_skb1") int bpf_prog1(struct __sk_buff *skb) { Loading Loading @@ -105,4 +119,42 @@ int bpf_sockmap(struct bpf_sock_ops *skops) return 0; } SEC("sk_msg1") int bpf_prog4(struct sk_msg_md *msg) { return SK_PASS; } SEC("sk_msg2") int bpf_prog5(struct sk_msg_md *msg) { void *data_end = (void *)(long) msg->data_end; void *data = (void *)(long) msg->data; bpf_printk("sk_msg2: data length %i\n", (__u32)data_end - (__u32)data); return SK_PASS; } SEC("sk_msg3") int bpf_prog6(struct sk_msg_md *msg) { void *data_end = (void *)(long) msg->data_end; void *data = (void *)(long) msg->data; int ret = 0; return bpf_msg_redirect_map(msg, &sock_map_redir, ret, 0); } SEC("sk_msg4") int bpf_prog7(struct sk_msg_md *msg) { void *data_end = (void *)(long) msg->data_end; void *data = (void *)(long) msg->data; int ret = 0; bpf_printk("sk_msg3: redirect(%iB)\n", (__u32)data_end - (__u32)data); return bpf_msg_redirect_map(msg, &sock_map_redir, ret, 0); } char _license[] SEC("license") = "GPL"; samples/sockmap/sockmap_user.c +61 −6 Original line number Diff line number Diff line Loading @@ -54,6 +54,11 @@ void running_handler(int a); /* global sockets */ int s1, s2, c1, c2, p1, p2; int txmsg_pass; int txmsg_noisy; int txmsg_redir; int txmsg_redir_noisy; static const struct option long_options[] = { {"help", no_argument, NULL, 'h' }, {"cgroup", required_argument, NULL, 'c' }, Loading @@ -62,6 +67,10 @@ static const struct option long_options[] = { {"iov_count", required_argument, NULL, 'i' }, {"length", required_argument, NULL, 'l' }, {"test", required_argument, NULL, 't' }, {"txmsg", no_argument, &txmsg_pass, 1 }, {"txmsg_noisy", no_argument, &txmsg_noisy, 1 }, {"txmsg_redir", no_argument, &txmsg_redir, 1 }, {"txmsg_redir_noisy", no_argument, &txmsg_redir_noisy, 1}, {0, 0, NULL, 0 } }; Loading Loading @@ -447,13 +456,13 @@ enum { int main(int argc, char **argv) { int iov_count = 1, length = 1024, rate = 1, verbose = 0; int iov_count = 1, length = 1024, rate = 1, verbose = 0, tx_prog_fd; struct rlimit r = {10 * 1024 * 1024, RLIM_INFINITY}; int opt, longindex, err, cg_fd = 0; int test = PING_PONG; char filename[256]; while ((opt = getopt_long(argc, argv, "hvc:r:i:l:t:", while ((opt = getopt_long(argc, argv, ":hvc:r:i:l:t:", long_options, &longindex)) != -1) { switch (opt) { /* Cgroup configuration */ Loading Loading @@ -490,6 +499,8 @@ int main(int argc, char **argv) return -1; } break; case 0: break; case 'h': default: usage(argv); Loading @@ -515,16 +526,16 @@ int main(int argc, char **argv) /* catch SIGINT */ signal(SIGINT, running_handler); /* If base test skip BPF setup */ if (test == BASE) goto run; if (load_bpf_file(filename)) { fprintf(stderr, "load_bpf_file: (%s) %s\n", filename, strerror(errno)); return 1; } /* If base test skip BPF setup */ if (test == BASE) goto run; /* Attach programs to sockmap */ err = bpf_prog_attach(prog_fd[0], map_fd[0], BPF_SK_SKB_STREAM_PARSER, 0); Loading Loading @@ -557,6 +568,50 @@ int main(int argc, char **argv) goto out; } /* Attach txmsg program to sockmap */ if (txmsg_pass) tx_prog_fd = prog_fd[3]; else if (txmsg_noisy) tx_prog_fd = prog_fd[4]; else if (txmsg_redir) tx_prog_fd = prog_fd[5]; else if (txmsg_redir_noisy) tx_prog_fd = prog_fd[6]; else tx_prog_fd = 0; if (tx_prog_fd) { int redir_fd, i = 0; err = bpf_prog_attach(tx_prog_fd, map_fd[1], BPF_SK_MSG_VERDICT, 0); if (err) { fprintf(stderr, "ERROR: bpf_prog_attach (txmsg): %d (%s)\n", err, strerror(errno)); return err; } err = bpf_map_update_elem(map_fd[1], &i, &c1, BPF_ANY); if (err) { fprintf(stderr, "ERROR: bpf_map_update_elem (txmsg): %d (%s\n", err, strerror(errno)); return err; } if (test == SENDMSG) redir_fd = c2; else redir_fd = c1; err = bpf_map_update_elem(map_fd[2], &i, &redir_fd, BPF_ANY); if (err) { fprintf(stderr, "ERROR: bpf_map_update_elem (txmsg): %d (%s\n", err, strerror(errno)); return err; } } if (test == PING_PONG) err = forever_ping_pong(rate, verbose); else if (test == SENDMSG) Loading tools/include/uapi/linux/bpf.h +12 −1 Original line number Diff line number Diff line Loading @@ -720,6 +720,15 @@ union bpf_attr { * int bpf_override_return(pt_regs, rc) * @pt_regs: pointer to struct pt_regs * @rc: the return value to set * * int bpf_msg_redirect_map(map, key, flags) * Redirect msg to a sock in map using key as a lookup key for the * sock in map. * @map: pointer to sockmap * @key: key to lookup sock in map * @flags: reserved for future use * Return: SK_PASS * */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ Loading Loading @@ -781,7 +790,9 @@ union bpf_attr { FN(perf_prog_read_value), \ FN(getsockopt), \ FN(override_return), \ FN(sock_ops_cb_flags_set), FN(sock_ops_cb_flags_set), \ FN(msg_redirect_map), \ FN(msg_apply_bytes), /* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call Loading tools/lib/bpf/libbpf.c +1 −0 Original line number Diff line number Diff line Loading @@ -1857,6 +1857,7 @@ static const struct { BPF_PROG_SEC("lwt_xmit", BPF_PROG_TYPE_LWT_XMIT), BPF_PROG_SEC("sockops", BPF_PROG_TYPE_SOCK_OPS), BPF_PROG_SEC("sk_skb", BPF_PROG_TYPE_SK_SKB), BPF_PROG_SEC("sk_msg", BPF_PROG_TYPE_SK_MSG), }; #undef BPF_PROG_SEC Loading Loading
samples/bpf/bpf_load.c +6 −2 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size) bool is_cgroup_sk = strncmp(event, "cgroup/sock", 11) == 0; bool is_sockops = strncmp(event, "sockops", 7) == 0; bool is_sk_skb = strncmp(event, "sk_skb", 6) == 0; bool is_sk_msg = strncmp(event, "sk_msg", 6) == 0; size_t insns_cnt = size / sizeof(struct bpf_insn); enum bpf_prog_type prog_type; char buf[256]; Loading Loading @@ -96,6 +97,8 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size) prog_type = BPF_PROG_TYPE_SOCK_OPS; } else if (is_sk_skb) { prog_type = BPF_PROG_TYPE_SK_SKB; } else if (is_sk_msg) { prog_type = BPF_PROG_TYPE_SK_MSG; } else { printf("Unknown event '%s'\n", event); return -1; Loading @@ -113,7 +116,7 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size) if (is_xdp || is_perf_event || is_cgroup_skb || is_cgroup_sk) return 0; if (is_socket || is_sockops || is_sk_skb) { if (is_socket || is_sockops || is_sk_skb || is_sk_msg) { if (is_socket) event += 6; else Loading Loading @@ -589,7 +592,8 @@ static int do_load_bpf_file(const char *path, fixup_map_cb fixup_map) memcmp(shname, "socket", 6) == 0 || memcmp(shname, "cgroup/", 7) == 0 || memcmp(shname, "sockops", 7) == 0 || memcmp(shname, "sk_skb", 6) == 0) { memcmp(shname, "sk_skb", 6) == 0 || memcmp(shname, "sk_msg", 6) == 0) { ret = load_and_attach(shname, data->d_buf, data->d_size); if (ret != 0) Loading
samples/sockmap/sockmap_kern.c +52 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,20 @@ struct bpf_map_def SEC("maps") sock_map = { .max_entries = 20, }; struct bpf_map_def SEC("maps") sock_map_txmsg = { .type = BPF_MAP_TYPE_SOCKMAP, .key_size = sizeof(int), .value_size = sizeof(int), .max_entries = 20, }; struct bpf_map_def SEC("maps") sock_map_redir = { .type = BPF_MAP_TYPE_SOCKMAP, .key_size = sizeof(int), .value_size = sizeof(int), .max_entries = 1, }; SEC("sk_skb1") int bpf_prog1(struct __sk_buff *skb) { Loading Loading @@ -105,4 +119,42 @@ int bpf_sockmap(struct bpf_sock_ops *skops) return 0; } SEC("sk_msg1") int bpf_prog4(struct sk_msg_md *msg) { return SK_PASS; } SEC("sk_msg2") int bpf_prog5(struct sk_msg_md *msg) { void *data_end = (void *)(long) msg->data_end; void *data = (void *)(long) msg->data; bpf_printk("sk_msg2: data length %i\n", (__u32)data_end - (__u32)data); return SK_PASS; } SEC("sk_msg3") int bpf_prog6(struct sk_msg_md *msg) { void *data_end = (void *)(long) msg->data_end; void *data = (void *)(long) msg->data; int ret = 0; return bpf_msg_redirect_map(msg, &sock_map_redir, ret, 0); } SEC("sk_msg4") int bpf_prog7(struct sk_msg_md *msg) { void *data_end = (void *)(long) msg->data_end; void *data = (void *)(long) msg->data; int ret = 0; bpf_printk("sk_msg3: redirect(%iB)\n", (__u32)data_end - (__u32)data); return bpf_msg_redirect_map(msg, &sock_map_redir, ret, 0); } char _license[] SEC("license") = "GPL";
samples/sockmap/sockmap_user.c +61 −6 Original line number Diff line number Diff line Loading @@ -54,6 +54,11 @@ void running_handler(int a); /* global sockets */ int s1, s2, c1, c2, p1, p2; int txmsg_pass; int txmsg_noisy; int txmsg_redir; int txmsg_redir_noisy; static const struct option long_options[] = { {"help", no_argument, NULL, 'h' }, {"cgroup", required_argument, NULL, 'c' }, Loading @@ -62,6 +67,10 @@ static const struct option long_options[] = { {"iov_count", required_argument, NULL, 'i' }, {"length", required_argument, NULL, 'l' }, {"test", required_argument, NULL, 't' }, {"txmsg", no_argument, &txmsg_pass, 1 }, {"txmsg_noisy", no_argument, &txmsg_noisy, 1 }, {"txmsg_redir", no_argument, &txmsg_redir, 1 }, {"txmsg_redir_noisy", no_argument, &txmsg_redir_noisy, 1}, {0, 0, NULL, 0 } }; Loading Loading @@ -447,13 +456,13 @@ enum { int main(int argc, char **argv) { int iov_count = 1, length = 1024, rate = 1, verbose = 0; int iov_count = 1, length = 1024, rate = 1, verbose = 0, tx_prog_fd; struct rlimit r = {10 * 1024 * 1024, RLIM_INFINITY}; int opt, longindex, err, cg_fd = 0; int test = PING_PONG; char filename[256]; while ((opt = getopt_long(argc, argv, "hvc:r:i:l:t:", while ((opt = getopt_long(argc, argv, ":hvc:r:i:l:t:", long_options, &longindex)) != -1) { switch (opt) { /* Cgroup configuration */ Loading Loading @@ -490,6 +499,8 @@ int main(int argc, char **argv) return -1; } break; case 0: break; case 'h': default: usage(argv); Loading @@ -515,16 +526,16 @@ int main(int argc, char **argv) /* catch SIGINT */ signal(SIGINT, running_handler); /* If base test skip BPF setup */ if (test == BASE) goto run; if (load_bpf_file(filename)) { fprintf(stderr, "load_bpf_file: (%s) %s\n", filename, strerror(errno)); return 1; } /* If base test skip BPF setup */ if (test == BASE) goto run; /* Attach programs to sockmap */ err = bpf_prog_attach(prog_fd[0], map_fd[0], BPF_SK_SKB_STREAM_PARSER, 0); Loading Loading @@ -557,6 +568,50 @@ int main(int argc, char **argv) goto out; } /* Attach txmsg program to sockmap */ if (txmsg_pass) tx_prog_fd = prog_fd[3]; else if (txmsg_noisy) tx_prog_fd = prog_fd[4]; else if (txmsg_redir) tx_prog_fd = prog_fd[5]; else if (txmsg_redir_noisy) tx_prog_fd = prog_fd[6]; else tx_prog_fd = 0; if (tx_prog_fd) { int redir_fd, i = 0; err = bpf_prog_attach(tx_prog_fd, map_fd[1], BPF_SK_MSG_VERDICT, 0); if (err) { fprintf(stderr, "ERROR: bpf_prog_attach (txmsg): %d (%s)\n", err, strerror(errno)); return err; } err = bpf_map_update_elem(map_fd[1], &i, &c1, BPF_ANY); if (err) { fprintf(stderr, "ERROR: bpf_map_update_elem (txmsg): %d (%s\n", err, strerror(errno)); return err; } if (test == SENDMSG) redir_fd = c2; else redir_fd = c1; err = bpf_map_update_elem(map_fd[2], &i, &redir_fd, BPF_ANY); if (err) { fprintf(stderr, "ERROR: bpf_map_update_elem (txmsg): %d (%s\n", err, strerror(errno)); return err; } } if (test == PING_PONG) err = forever_ping_pong(rate, verbose); else if (test == SENDMSG) Loading
tools/include/uapi/linux/bpf.h +12 −1 Original line number Diff line number Diff line Loading @@ -720,6 +720,15 @@ union bpf_attr { * int bpf_override_return(pt_regs, rc) * @pt_regs: pointer to struct pt_regs * @rc: the return value to set * * int bpf_msg_redirect_map(map, key, flags) * Redirect msg to a sock in map using key as a lookup key for the * sock in map. * @map: pointer to sockmap * @key: key to lookup sock in map * @flags: reserved for future use * Return: SK_PASS * */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ Loading Loading @@ -781,7 +790,9 @@ union bpf_attr { FN(perf_prog_read_value), \ FN(getsockopt), \ FN(override_return), \ FN(sock_ops_cb_flags_set), FN(sock_ops_cb_flags_set), \ FN(msg_redirect_map), \ FN(msg_apply_bytes), /* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call Loading
tools/lib/bpf/libbpf.c +1 −0 Original line number Diff line number Diff line Loading @@ -1857,6 +1857,7 @@ static const struct { BPF_PROG_SEC("lwt_xmit", BPF_PROG_TYPE_LWT_XMIT), BPF_PROG_SEC("sockops", BPF_PROG_TYPE_SOCK_OPS), BPF_PROG_SEC("sk_skb", BPF_PROG_TYPE_SK_SKB), BPF_PROG_SEC("sk_msg", BPF_PROG_TYPE_SK_MSG), }; #undef BPF_PROG_SEC Loading