bpf: sockmap sample support for bpf_msg_cork_bytes()
authorJohn Fastabend <john.fastabend@gmail.com>
Sun, 18 Mar 2018 19:58:02 +0000 (12:58 -0700)
committerDaniel Borkmann <daniel@iogearbox.net>
Mon, 19 Mar 2018 20:14:40 +0000 (21:14 +0100)
Add sample application support for the bpf_msg_cork_bytes helper. This
lets the user specify how many bytes each verdict should apply to.

Similar to apply_bytes() tests these can be run as a stand-alone test
when used without other options or inline with other tests by using
the txmsg_cork option along with any of the basic tests txmsg,
txmsg_redir, txmsg_drop.

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>
samples/sockmap/sockmap_kern.c
samples/sockmap/sockmap_user.c
tools/include/uapi/linux/bpf.h
tools/testing/selftests/bpf/bpf_helpers.h

index 205ec36449d194dc492105ea94a39044e28e6d33..735226794ce1bee4a580aad6e9cd6dc888052f93 100644 (file)
@@ -64,6 +64,13 @@ struct bpf_map_def SEC("maps") sock_apply_bytes = {
        .max_entries = 1
 };
 
+struct bpf_map_def SEC("maps") sock_cork_bytes = {
+       .type = BPF_MAP_TYPE_ARRAY,
+       .key_size = sizeof(int),
+       .value_size = sizeof(int),
+       .max_entries = 1
+};
+
 SEC("sk_skb1")
 int bpf_prog1(struct __sk_buff *skb)
 {
@@ -135,6 +142,9 @@ int bpf_prog4(struct sk_msg_md *msg)
        bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
        if (bytes)
                bpf_msg_apply_bytes(msg, *bytes);
+       bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
+       if (bytes)
+               bpf_msg_cork_bytes(msg, *bytes);
        return SK_PASS;
 }
 
@@ -143,13 +153,16 @@ int bpf_prog5(struct sk_msg_md *msg)
 {
        void *data_end = (void *)(long) msg->data_end;
        void *data = (void *)(long) msg->data;
-       int *bytes, err = 0, zero = 0;
+       int *bytes, err1 = -1, err2 = -1, zero = 0;
 
        bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
        if (bytes)
-               err = bpf_msg_apply_bytes(msg, *bytes);
-       bpf_printk("sk_msg2: data length %i err %i\n",
-                  (__u64)data_end - (__u64)data, err);
+               err1 = bpf_msg_apply_bytes(msg, *bytes);
+       bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
+       if (bytes)
+               err2 = bpf_msg_cork_bytes(msg, *bytes);
+       bpf_printk("sk_msg2: data length %i err1 %i err2 %i\n",
+                  (__u64)data_end - (__u64)data, err1, err2);
        return SK_PASS;
 }
 
@@ -163,6 +176,9 @@ int bpf_prog6(struct sk_msg_md *msg)
        bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
        if (bytes)
                bpf_msg_apply_bytes(msg, *bytes);
+       bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
+       if (bytes)
+               bpf_msg_cork_bytes(msg, *bytes);
        return bpf_msg_redirect_map(msg, &sock_map_redir, zero, 0);
 }
 
@@ -171,13 +187,17 @@ int bpf_prog7(struct sk_msg_md *msg)
 {
        void *data_end = (void *)(long) msg->data_end;
        void *data = (void *)(long) msg->data;
-       int *bytes, err = 0, zero = 0;
+       int *bytes, err1 = 0, err2 = 0, zero = 0;
 
        bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
        if (bytes)
-               err = bpf_msg_apply_bytes(msg, *bytes);
-       bpf_printk("sk_msg3: redirect(%iB) err=%i\n",
-                  (__u64)data_end - (__u64)data, err);
+               err1 = bpf_msg_apply_bytes(msg, *bytes);
+       bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
+       if (bytes)
+               err2 = bpf_msg_cork_bytes(msg, *bytes);
+
+       bpf_printk("sk_msg3: redirect(%iB) err1=%i err2=%i\n",
+                  (__u64)data_end - (__u64)data, err1, err2);
        return bpf_msg_redirect_map(msg, &sock_map_redir, zero, 0);
 }
 
@@ -198,5 +218,22 @@ int bpf_prog8(struct sk_msg_md *msg)
        }
        return SK_PASS;
 }
+SEC("sk_msg6")
+int bpf_prog9(struct sk_msg_md *msg)
+{
+       void *data_end = (void *)(long) msg->data_end;
+       void *data = (void *)(long) msg->data;
+       int ret = 0, *bytes, zero = 0;
+
+       bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
+       if (bytes) {
+               if (((__u64)data_end - (__u64)data) >= *bytes)
+                       return SK_PASS;
+               ret = bpf_msg_cork_bytes(msg, *bytes);
+               if (ret)
+                       return SK_DROP;
+       }
+       return SK_PASS;
+}
 
 char _license[] SEC("license") = "GPL";
index 41774ec0f0b3d6c6ebefe589157d47637fc6935d..4e0a3d87881fddd144888c95624ec250f007272e 100644 (file)
@@ -60,6 +60,7 @@ int txmsg_noisy;
 int txmsg_redir;
 int txmsg_redir_noisy;
 int txmsg_apply;
+int txmsg_cork;
 
 static const struct option long_options[] = {
        {"help",        no_argument,            NULL, 'h' },
@@ -75,6 +76,7 @@ static const struct option long_options[] = {
        {"txmsg_redir",         no_argument,    &txmsg_redir, 1  },
        {"txmsg_redir_noisy",   no_argument,    &txmsg_redir_noisy, 1},
        {"txmsg_apply", required_argument,      NULL, 'a'},
+       {"txmsg_cork",  required_argument,      NULL, 'k'},
        {0, 0, NULL, 0 }
 };
 
@@ -551,6 +553,9 @@ int main(int argc, char **argv)
                case 'a':
                        txmsg_apply = atoi(optarg);
                        break;
+               case 'k':
+                       txmsg_cork = atoi(optarg);
+                       break;
                case 'c':
                        cg_fd = open(optarg, O_DIRECTORY, O_RDONLY);
                        if (cg_fd < 0) {
@@ -671,6 +676,8 @@ run:
                tx_prog_fd = prog_fd[6];
        else if (txmsg_apply)
                tx_prog_fd = prog_fd[7];
+       else if (txmsg_cork)
+               tx_prog_fd = prog_fd[8];
        else
                tx_prog_fd = 0;
 
@@ -716,6 +723,18 @@ run:
                                return err;
                        }
                }
+
+               if (txmsg_cork) {
+                       err = bpf_map_update_elem(map_fd[4],
+                                                 &i, &txmsg_cork, BPF_ANY);
+                       if (err) {
+                               fprintf(stderr,
+                                       "ERROR: bpf_map_update_elem (cork_bytes):  %d (%s\n",
+                                       err, strerror(errno));
+                               return err;
+                       }
+               }
+
        }
        if (test == PING_PONG)
                err = forever_ping_pong(rate, &options);
index 01b9c97b172ebd3e3def7d58f1a543758859105d..e6924ab20fc359461c87648be066aef18da55d0a 100644 (file)
@@ -792,7 +792,8 @@ union bpf_attr {
        FN(override_return),            \
        FN(sock_ops_cb_flags_set),      \
        FN(msg_redirect_map),           \
-       FN(msg_apply_bytes),
+       FN(msg_apply_bytes),            \
+       FN(msg_cork_bytes),
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
  * function eBPF program intends to call
index 4713de48cf888d52013ddd997cc18e9782fc2819..b5b45ff705fffa68f02de67b4608a846321e05d4 100644 (file)
@@ -90,6 +90,8 @@ static int (*bpf_msg_redirect_map)(void *ctx, void *map, int key, int flags) =
        (void *) BPF_FUNC_msg_redirect_map;
 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;
 
 /* llvm builtin functions that eBPF C program may use to
  * emit BPF_LD_ABS and BPF_LD_IND instructions