Add map tests to attach BPF_PROG_TYPE_SK_MSG types to a sockmap.

Signed-off-by: John Fastabend <john.fastab...@gmail.com>
Acked-by: David S. Miller <da...@davemloft.net>
---
 tools/include/uapi/linux/bpf.h                     |   10 ++++
 tools/testing/selftests/bpf/Makefile               |    3 +
 tools/testing/selftests/bpf/bpf_helpers.h          |    2 +
 tools/testing/selftests/bpf/sockmap_parse_prog.c   |   15 +++++
 tools/testing/selftests/bpf/sockmap_tcp_msg_prog.c |   33 ++++++++++++
 tools/testing/selftests/bpf/sockmap_verdict_prog.c |    7 +++
 tools/testing/selftests/bpf/test_maps.c            |   55 +++++++++++++++++++-
 7 files changed, 118 insertions(+), 7 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/sockmap_tcp_msg_prog.c

diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 1944d0a..13d9c59 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -133,6 +133,7 @@ enum bpf_prog_type {
        BPF_PROG_TYPE_SOCK_OPS,
        BPF_PROG_TYPE_SK_SKB,
        BPF_PROG_TYPE_CGROUP_DEVICE,
+       BPF_PROG_TYPE_SK_MSG,
 };
 
 enum bpf_attach_type {
@@ -143,6 +144,7 @@ enum bpf_attach_type {
        BPF_SK_SKB_STREAM_PARSER,
        BPF_SK_SKB_STREAM_VERDICT,
        BPF_CGROUP_DEVICE,
+       BPF_SK_MSG_VERDICT,
        __MAX_BPF_ATTACH_TYPE
 };
 
@@ -941,6 +943,14 @@ enum sk_action {
        SK_PASS,
 };
 
+/* user accessible metadata for SK_MSG packet hook, new fields must
+ * be added to the end of this structure
+ */
+struct sk_msg_md {
+       void *data;
+       void *data_end;
+};
+
 #define BPF_TAG_SIZE   8
 
 struct bpf_prog_info {
diff --git a/tools/testing/selftests/bpf/Makefile 
b/tools/testing/selftests/bpf/Makefile
index b0d29fd..f35fb02 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -29,7 +29,8 @@ TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o 
test_tcp_estats.o test
        test_pkt_md_access.o test_xdp_redirect.o test_xdp_meta.o 
sockmap_parse_prog.o     \
        sockmap_verdict_prog.o dev_cgroup.o sample_ret0.o test_tracepoint.o \
        test_l4lb_noinline.o test_xdp_noinline.o test_stacktrace_map.o \
-       sample_map_ret0.o test_tcpbpf_kern.o test_stacktrace_build_id.o
+       sample_map_ret0.o test_tcpbpf_kern.o test_stacktrace_build_id.o \
+       sockmap_tcp_msg_prog.o
 
 # Order correspond to 'make run_tests' order
 TEST_PROGS := test_kmod.sh \
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h 
b/tools/testing/selftests/bpf/bpf_helpers.h
index dde2c11..1558fe8 100644
--- a/tools/testing/selftests/bpf/bpf_helpers.h
+++ b/tools/testing/selftests/bpf/bpf_helpers.h
@@ -123,6 +123,8 @@ static int (*bpf_skb_under_cgroup)(void *ctx, void *map, 
int index) =
        (void *) BPF_FUNC_skb_under_cgroup;
 static int (*bpf_skb_change_head)(void *, int len, int flags) =
        (void *) BPF_FUNC_skb_change_head;
+static int (*bpf_skb_pull_data)(void *, int len) =
+       (void *) BPF_FUNC_skb_pull_data;
 
 /* Scan the ARCH passed in from ARCH env variable (see Makefile) */
 #if defined(__TARGET_ARCH_x86)
diff --git a/tools/testing/selftests/bpf/sockmap_parse_prog.c 
b/tools/testing/selftests/bpf/sockmap_parse_prog.c
index a1dec2b..0f92858 100644
--- a/tools/testing/selftests/bpf/sockmap_parse_prog.c
+++ b/tools/testing/selftests/bpf/sockmap_parse_prog.c
@@ -20,14 +20,25 @@ int bpf_prog1(struct __sk_buff *skb)
        __u32 lport = skb->local_port;
        __u32 rport = skb->remote_port;
        __u8 *d = data;
+       __u32 len = (__u32) data_end - (__u32) data;
+       int err;
 
-       if (data + 10 > data_end)
-               return skb->len;
+       if (data + 10 > data_end) {
+               err = bpf_skb_pull_data(skb, 10);
+               if (err)
+                       return SK_DROP;
+
+               data_end = (void *)(long)skb->data_end;
+               data = (void *)(long)skb->data;
+               if (data + 10 > data_end)
+                       return SK_DROP;
+       }
 
        /* This write/read is a bit pointless but tests the verifier and
         * strparser handler for read/write pkt data and access into sk
         * fields.
         */
+       d = data;
        d[7] = 1;
        return skb->len;
 }
diff --git a/tools/testing/selftests/bpf/sockmap_tcp_msg_prog.c 
b/tools/testing/selftests/bpf/sockmap_tcp_msg_prog.c
new file mode 100644
index 0000000..12a7b5c
--- /dev/null
+++ b/tools/testing/selftests/bpf/sockmap_tcp_msg_prog.c
@@ -0,0 +1,33 @@
+#include <linux/bpf.h>
+#include "bpf_helpers.h"
+#include "bpf_util.h"
+#include "bpf_endian.h"
+
+int _version SEC("version") = 1;
+
+#define bpf_printk(fmt, ...)                                   \
+({                                                             \
+              char ____fmt[] = fmt;                            \
+              bpf_trace_printk(____fmt, sizeof(____fmt),       \
+                               ##__VA_ARGS__);                 \
+})
+
+SEC("sk_msg1")
+int bpf_prog1(struct sk_msg_md *msg)
+{
+       void *data_end = (void *)(long) msg->data_end;
+       void *data = (void *)(long) msg->data;
+
+       char *d;
+
+       if (data + 8 > data_end)
+               return SK_DROP;
+
+       bpf_printk("data length %i\n", (__u64)msg->data_end - (__u64)msg->data);
+       d = (char *)data;
+       bpf_printk("hello sendmsg hook %i %i\n", d[0], d[1]);
+
+       return SK_PASS;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/sockmap_verdict_prog.c 
b/tools/testing/selftests/bpf/sockmap_verdict_prog.c
index d7bea97..2ce7634 100644
--- a/tools/testing/selftests/bpf/sockmap_verdict_prog.c
+++ b/tools/testing/selftests/bpf/sockmap_verdict_prog.c
@@ -26,6 +26,13 @@ struct bpf_map_def SEC("maps") sock_map_tx = {
        .max_entries = 20,
 };
 
+struct bpf_map_def SEC("maps") sock_map_msg = {
+       .type = BPF_MAP_TYPE_SOCKMAP,
+       .key_size = sizeof(int),
+       .value_size = sizeof(int),
+       .max_entries = 20,
+};
+
 struct bpf_map_def SEC("maps") sock_map_break = {
        .type = BPF_MAP_TYPE_ARRAY,
        .key_size = sizeof(int),
diff --git a/tools/testing/selftests/bpf/test_maps.c 
b/tools/testing/selftests/bpf/test_maps.c
index 1238733..6c25334 100644
--- a/tools/testing/selftests/bpf/test_maps.c
+++ b/tools/testing/selftests/bpf/test_maps.c
@@ -464,15 +464,17 @@ static void test_devmap(int task, void *data)
 #include <linux/err.h>
 #define SOCKMAP_PARSE_PROG "./sockmap_parse_prog.o"
 #define SOCKMAP_VERDICT_PROG "./sockmap_verdict_prog.o"
+#define SOCKMAP_TCP_MSG_PROG "./sockmap_tcp_msg_prog.o"
 static void test_sockmap(int tasks, void *data)
 {
-       int one = 1, map_fd_rx = 0, map_fd_tx = 0, map_fd_break, s, sc, rc;
-       struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_break;
+       struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_msg, *bpf_map_break;
+       int map_fd_msg = 0, map_fd_rx = 0, map_fd_tx = 0, map_fd_break;
        int ports[] = {50200, 50201, 50202, 50204};
        int err, i, fd, udp, sfd[6] = {0xdeadbeef};
        u8 buf[20] = {0x0, 0x5, 0x3, 0x2, 0x1, 0x0};
-       int parse_prog, verdict_prog;
+       int parse_prog, verdict_prog, msg_prog;
        struct sockaddr_in addr;
+       int one = 1, s, sc, rc;
        struct bpf_object *obj;
        struct timeval to;
        __u32 key, value;
@@ -584,6 +586,12 @@ static void test_sockmap(int tasks, void *data)
                goto out_sockmap;
        }
 
+       err = bpf_prog_attach(-1, fd, BPF_SK_MSG_VERDICT, 0);
+       if (!err) {
+               printf("Failed invalid msg verdict prog attach\n");
+               goto out_sockmap;
+       }
+
        err = bpf_prog_attach(-1, fd, __MAX_BPF_ATTACH_TYPE, 0);
        if (!err) {
                printf("Failed unknown prog attach\n");
@@ -602,6 +610,12 @@ static void test_sockmap(int tasks, void *data)
                goto out_sockmap;
        }
 
+       err = bpf_prog_detach(fd, BPF_SK_MSG_VERDICT);
+       if (err) {
+               printf("Failed empty msg verdict prog detach\n");
+               goto out_sockmap;
+       }
+
        err = bpf_prog_detach(fd, __MAX_BPF_ATTACH_TYPE);
        if (!err) {
                printf("Detach invalid prog successful\n");
@@ -616,6 +630,13 @@ static void test_sockmap(int tasks, void *data)
                goto out_sockmap;
        }
 
+       err = bpf_prog_load(SOCKMAP_TCP_MSG_PROG,
+                           BPF_PROG_TYPE_SK_MSG, &obj, &msg_prog);
+       if (err) {
+               printf("Failed to load SK_SKB msg prog\n");
+               goto out_sockmap;
+       }
+
        err = bpf_prog_load(SOCKMAP_VERDICT_PROG,
                            BPF_PROG_TYPE_SK_SKB, &obj, &verdict_prog);
        if (err) {
@@ -631,7 +652,7 @@ static void test_sockmap(int tasks, void *data)
 
        map_fd_rx = bpf_map__fd(bpf_map_rx);
        if (map_fd_rx < 0) {
-               printf("Failed to get map fd\n");
+               printf("Failed to get map rx fd\n");
                goto out_sockmap;
        }
 
@@ -647,6 +668,18 @@ static void test_sockmap(int tasks, void *data)
                goto out_sockmap;
        }
 
+       bpf_map_msg = bpf_object__find_map_by_name(obj, "sock_map_msg");
+       if (IS_ERR(bpf_map_msg)) {
+               printf("Failed to load map msg from msg_verdict prog\n");
+               goto out_sockmap;
+       }
+
+       map_fd_msg = bpf_map__fd(bpf_map_msg);
+       if (map_fd_msg < 0) {
+               printf("Failed to get map msg fd\n");
+               goto out_sockmap;
+       }
+
        bpf_map_break = bpf_object__find_map_by_name(obj, "sock_map_break");
        if (IS_ERR(bpf_map_break)) {
                printf("Failed to load map tx from verdict prog\n");
@@ -680,6 +713,12 @@ static void test_sockmap(int tasks, void *data)
                goto out_sockmap;
        }
 
+       err = bpf_prog_attach(msg_prog, map_fd_msg, BPF_SK_MSG_VERDICT, 0);
+       if (err) {
+               printf("Failed msg verdict bpf prog attach\n");
+               goto out_sockmap;
+       }
+
        err = bpf_prog_attach(verdict_prog, map_fd_rx,
                              __MAX_BPF_ATTACH_TYPE, 0);
        if (!err) {
@@ -719,6 +758,14 @@ static void test_sockmap(int tasks, void *data)
                }
        }
 
+       /* Put sfd[2] (sending fd below) into msg map to test sendmsg bpf */
+       i = 0;
+       err = bpf_map_update_elem(map_fd_msg, &i, &sfd[2], BPF_ANY);
+       if (err) {
+               printf("Failed map_fd_msg update sockmap %i\n", err);
+               goto out_sockmap;
+       }
+
        /* Test map send/recv */
        for (i = 0; i < 2; i++) {
                buf[0] = i;

Reply via email to