bpf: sockmap sample, add option to attach SK_MSG program
authorJohn Fastabend <john.fastabend@gmail.com>
Sun, 18 Mar 2018 19:57:41 +0000 (12:57 -0700)
committerDaniel Borkmann <daniel@iogearbox.net>
Mon, 19 Mar 2018 20:14:40 +0000 (21:14 +0100)
Add sockmap option to use SK_MSG program types.

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

index 69806d74fa53bac11aa4b113661539777a300a6b..b1a310c3ae899b043c70085fc71a08b698ea0308 100644 (file)
@@ -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];
@@ -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;
@@ -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
@@ -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)
index 52b0053274f425a6a07eb70dfbce89ca9c32d4fb..75edb2f151d46422091aa11b242323a877ae485b 100644 (file)
@@ -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)
 {
@@ -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";
index 95a54a89a5322a44ec17d727f78c8ec795c8631c..bbfe3a2b988592d64331d6461b12e45e23a24382 100644 (file)
@@ -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' },
@@ -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 }
 };
 
@@ -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 */
@@ -490,6 +499,8 @@ int main(int argc, char **argv)
                                return -1;
                        }
                        break;
+               case 0:
+                       break;
                case 'h':
                default:
                        usage(argv);
@@ -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);
@@ -557,6 +568,50 @@ run:
                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)
index 13d9c59d79ceddb9331b293a0bc419c2907d360a..01b9c97b172ebd3e3def7d58f1a543758859105d 100644 (file)
@@ -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),                     \
@@ -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
index 5bbbf285af74a0afb01ae4dcaba9a7cdbb3a3e93..64a8fc38418610b8f80a0476e75a8024bc2167fa 100644 (file)
@@ -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
 
index 1558fe8bcf3eae537b5807684c23643b4941544f..bba7ee6d93ab7b8fe07296137cad161c9ac84bf2 100644 (file)
@@ -86,6 +86,9 @@ static int (*bpf_perf_prog_read_value)(void *ctx, void *buf,
        (void *) BPF_FUNC_perf_prog_read_value;
 static int (*bpf_override_return)(void *ctx, unsigned long rc) =
        (void *) BPF_FUNC_override_return;
+static int (*bpf_msg_redirect_map)(void *ctx, void *map, int key, int flags) =
+       (void *) BPF_FUNC_msg_redirect_map;
+
 
 /* llvm builtin functions that eBPF C program may use to
  * emit BPF_LD_ABS and BPF_LD_IND instructions