diff --git a/samples/sockmap/sockmap_kern.c b/samples/sockmap/sockmap_kern.c index 8b6c34cd5f465635b78d04e991b0bd1e6f2794e6..9ad5ba79c85ae1a16710a337e32d4aaf08bfe776 100644 --- a/samples/sockmap/sockmap_kern.c +++ b/samples/sockmap/sockmap_kern.c @@ -71,6 +71,14 @@ struct bpf_map_def SEC("maps") sock_cork_bytes = { .max_entries = 1 }; +struct bpf_map_def SEC("maps") sock_pull_bytes = { + .type = BPF_MAP_TYPE_ARRAY, + .key_size = sizeof(int), + .value_size = sizeof(int), + .max_entries = 2 +}; + + SEC("sk_skb1") int bpf_prog1(struct __sk_buff *skb) { @@ -137,7 +145,8 @@ int bpf_sockmap(struct bpf_sock_ops *skops) SEC("sk_msg1") int bpf_prog4(struct sk_msg_md *msg) { - int *bytes, zero = 0; + int *bytes, zero = 0, one = 1; + int *start, *end; bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero); if (bytes) @@ -145,15 +154,18 @@ int bpf_prog4(struct sk_msg_md *msg) bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero); if (bytes) bpf_msg_cork_bytes(msg, *bytes); + start = bpf_map_lookup_elem(&sock_pull_bytes, &zero); + end = bpf_map_lookup_elem(&sock_pull_bytes, &one); + if (start && end) + bpf_msg_pull_data(msg, *start, *end, 0); 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; - int *bytes, err1 = -1, err2 = -1, zero = 0; + int err1 = -1, err2 = -1, zero = 0, one = 1; + int *bytes, *start, *end, len1, len2; bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero); if (bytes) @@ -161,17 +173,32 @@ int bpf_prog5(struct sk_msg_md *msg) bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero); if (bytes) err2 = bpf_msg_cork_bytes(msg, *bytes); + len1 = (__u64)msg->data_end - (__u64)msg->data; + start = bpf_map_lookup_elem(&sock_pull_bytes, &zero); + end = bpf_map_lookup_elem(&sock_pull_bytes, &one); + if (start && end) { + int err; + + bpf_printk("sk_msg2: pull(%i:%i)\n", + start ? *start : 0, end ? *end : 0); + err = bpf_msg_pull_data(msg, *start, *end, 0); + if (err) + bpf_printk("sk_msg2: pull_data err %i\n", + err); + len2 = (__u64)msg->data_end - (__u64)msg->data; + bpf_printk("sk_msg2: length update %i->%i\n", + len1, len2); + } bpf_printk("sk_msg2: data length %i err1 %i err2 %i\n", - (__u64)data_end - (__u64)data, err1, err2); + len1, err1, err2); 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 *bytes, zero = 0; + int *bytes, zero = 0, one = 1; + int *start, *end; bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero); if (bytes) @@ -179,15 +206,18 @@ int bpf_prog6(struct sk_msg_md *msg) bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero); if (bytes) bpf_msg_cork_bytes(msg, *bytes); + start = bpf_map_lookup_elem(&sock_pull_bytes, &zero); + end = bpf_map_lookup_elem(&sock_pull_bytes, &one); + if (start && end) + bpf_msg_pull_data(msg, *start, *end, 0); return bpf_msg_redirect_map(msg, &sock_map_redir, zero, 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 *bytes, err1 = 0, err2 = 0, zero = 0; + int err1 = 0, err2 = 0, zero = 0, one = 1; + int *bytes, *start, *end, len1, len2; bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero); if (bytes) @@ -195,9 +225,24 @@ int bpf_prog7(struct sk_msg_md *msg) bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero); if (bytes) err2 = bpf_msg_cork_bytes(msg, *bytes); - + len1 = (__u64)msg->data_end - (__u64)msg->data; + start = bpf_map_lookup_elem(&sock_pull_bytes, &zero); + end = bpf_map_lookup_elem(&sock_pull_bytes, &one); + if (start && end) { + int err; + + bpf_printk("sk_msg2: pull(%i:%i)\n", + start ? *start : 0, end ? *end : 0); + err = bpf_msg_pull_data(msg, *start, *end, 0); + if (err) + bpf_printk("sk_msg2: pull_data err %i\n", + err); + len2 = (__u64)msg->data_end - (__u64)msg->data; + bpf_printk("sk_msg2: length update %i->%i\n", + len1, len2); + } bpf_printk("sk_msg3: redirect(%iB) err1=%i err2=%i\n", - (__u64)data_end - (__u64)data, err1, err2); + len1, err1, err2); return bpf_msg_redirect_map(msg, &sock_map_redir, zero, 0); } @@ -239,7 +284,8 @@ int bpf_prog9(struct sk_msg_md *msg) SEC("sk_msg7") int bpf_prog10(struct sk_msg_md *msg) { - int *bytes, zero = 0; + int *bytes, zero = 0, one = 1; + int *start, *end; bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero); if (bytes) @@ -247,6 +293,11 @@ int bpf_prog10(struct sk_msg_md *msg) bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero); if (bytes) bpf_msg_cork_bytes(msg, *bytes); + start = bpf_map_lookup_elem(&sock_pull_bytes, &zero); + end = bpf_map_lookup_elem(&sock_pull_bytes, &one); + if (start && end) + bpf_msg_pull_data(msg, *start, *end, 0); + return SK_DROP; } diff --git a/samples/sockmap/sockmap_user.c b/samples/sockmap/sockmap_user.c index 52c4ed7774d4d51fc657aba09c744271bea9e2e1..07aa237221d12c46bf3f07e5cb17cb7aebe9a4c3 100644 --- a/samples/sockmap/sockmap_user.c +++ b/samples/sockmap/sockmap_user.c @@ -62,6 +62,8 @@ int txmsg_redir_noisy; int txmsg_drop; int txmsg_apply; int txmsg_cork; +int txmsg_start; +int txmsg_end; static const struct option long_options[] = { {"help", no_argument, NULL, 'h' }, @@ -79,6 +81,8 @@ static const struct option long_options[] = { {"txmsg_drop", no_argument, &txmsg_drop, 1 }, {"txmsg_apply", required_argument, NULL, 'a'}, {"txmsg_cork", required_argument, NULL, 'k'}, + {"txmsg_start", required_argument, NULL, 's'}, + {"txmsg_end", required_argument, NULL, 'e'}, {0, 0, NULL, 0 } }; @@ -572,6 +576,12 @@ int main(int argc, char **argv) while ((opt = getopt_long(argc, argv, ":dhvc:r:i:l:t:", long_options, &longindex)) != -1) { switch (opt) { + case 's': + txmsg_start = atoi(optarg); + break; + case 'e': + txmsg_end = atoi(optarg); + break; case 'a': txmsg_apply = atoi(optarg); break; @@ -761,6 +771,28 @@ int main(int argc, char **argv) } } + if (txmsg_start) { + err = bpf_map_update_elem(map_fd[5], + &i, &txmsg_start, BPF_ANY); + if (err) { + fprintf(stderr, + "ERROR: bpf_map_update_elem (txmsg_start): %d (%s)\n", + err, strerror(errno)); + return err; + } + } + + if (txmsg_end) { + i = 1; + err = bpf_map_update_elem(map_fd[5], + &i, &txmsg_end, BPF_ANY); + if (err) { + fprintf(stderr, + "ERROR: bpf_map_update_elem (txmsg_end): %d (%s)\n", + err, strerror(errno)); + return err; + } + } } if (txmsg_drop) diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index e6924ab20fc359461c87648be066aef18da55d0a..d245c41213ac20850a1b9b58f1925b827899ff04 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -793,7 +793,8 @@ union bpf_attr { FN(sock_ops_cb_flags_set), \ FN(msg_redirect_map), \ FN(msg_apply_bytes), \ - FN(msg_cork_bytes), + FN(msg_cork_bytes), \ + FN(msg_pull_data), /* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h index b5b45ff705fffa68f02de67b4608a846321e05d4..7cae376d8d0c76c556dee7e6ce3c2a2de448a16e 100644 --- a/tools/testing/selftests/bpf/bpf_helpers.h +++ b/tools/testing/selftests/bpf/bpf_helpers.h @@ -92,6 +92,8 @@ static int (*bpf_msg_apply_bytes)(void *ctx, int len) = (void *) BPF_FUNC_msg_apply_bytes; static int (*bpf_msg_cork_bytes)(void *ctx, int len) = (void *) BPF_FUNC_msg_cork_bytes; +static int (*bpf_msg_pull_data)(void *ctx, int start, int end, int flags) = + (void *) BPF_FUNC_msg_pull_data; /* llvm builtin functions that eBPF C program may use to * emit BPF_LD_ABS and BPF_LD_IND instructions