bpf: bpftool, add support for attaching programs to maps
authorJohn Fastabend <john.fastabend@gmail.com>
Mon, 15 Oct 2018 18:19:50 +0000 (11:19 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Mon, 15 Oct 2018 23:13:14 +0000 (16:13 -0700)
Sock map/hash introduce support for attaching programs to maps. To
date I have been doing this with custom tooling but this is less than
ideal as we shift to using bpftool as the single CLI for our BPF uses.
This patch adds new sub commands 'attach' and 'detach' to the 'prog'
command to attach programs to maps and then detach them.

Signed-off-by: John Fastabend <john.fastabend@gmail.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/bpf/bpftool/Documentation/bpftool-prog.rst
tools/bpf/bpftool/Documentation/bpftool.rst
tools/bpf/bpftool/bash-completion/bpftool
tools/bpf/bpftool/prog.c

index 64156a16d5300b64e0d9c2f5297605b88e6265b2..12c803003ab29fea648801c09b2e063621e8aa96 100644 (file)
@@ -25,6 +25,8 @@ MAP COMMANDS
 |      **bpftool** **prog dump jited**  *PROG* [{**file** *FILE* | **opcodes**}]
 |      **bpftool** **prog pin** *PROG* *FILE*
 |      **bpftool** **prog load** *OBJ* *FILE* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*]
+|       **bpftool** **prog attach** *PROG* *ATTACH_TYPE* *MAP*
+|       **bpftool** **prog detach** *PROG* *ATTACH_TYPE* *MAP*
 |      **bpftool** **prog help**
 |
 |      *MAP* := { **id** *MAP_ID* | **pinned** *FILE* }
@@ -37,6 +39,7 @@ MAP COMMANDS
 |              **cgroup/bind4** | **cgroup/bind6** | **cgroup/post_bind4** | **cgroup/post_bind6** |
 |              **cgroup/connect4** | **cgroup/connect6** | **cgroup/sendmsg4** | **cgroup/sendmsg6**
 |      }
+|       *ATTACH_TYPE* := { **msg_verdict** | **skb_verdict** | **skb_parse** }
 
 
 DESCRIPTION
@@ -90,6 +93,14 @@ DESCRIPTION
 
                  Note: *FILE* must be located in *bpffs* mount.
 
+        **bpftool prog attach** *PROG* *ATTACH_TYPE* *MAP*
+                  Attach bpf program *PROG* (with type specified by *ATTACH_TYPE*)
+                  to the map *MAP*.
+
+        **bpftool prog detach** *PROG* *ATTACH_TYPE* *MAP*
+                  Detach bpf program *PROG* (with type specified by *ATTACH_TYPE*)
+                  from the map *MAP*.
+
        **bpftool prog help**
                  Print short help message.
 
index 8dda77daeda968cc0cbfdf33c8d6537bc1842cf4..25c08728ca8002598d14ec2ed326417c9400c4b2 100644 (file)
@@ -26,7 +26,7 @@ SYNOPSIS
        | **pin** | **event_pipe** | **help** }
 
        *PROG-COMMANDS* := { **show** | **list** | **dump jited** | **dump xlated** | **pin**
-       | **load** | **help** }
+       | **load** | **attach** | **detach** | **help** }
 
        *CGROUP-COMMANDS* := { **show** | **list** | **attach** | **detach** | **help** }
 
index df1060b852c1db09bd733bcd7c3e072ff2d67ddc..0826519318249cae3566df48dc67f7261463c3e6 100644 (file)
@@ -292,6 +292,23 @@ _bpftool()
                     fi
                     return 0
                     ;;
+                attach|detach)
+                    if [[ ${#words[@]} == 7 ]]; then
+                        COMPREPLY=( $( compgen -W "id pinned" -- "$cur" ) )
+                        return 0
+                    fi
+
+                    if [[ ${#words[@]} == 6 ]]; then
+                        COMPREPLY=( $( compgen -W "msg_verdict skb_verdict skb_parse" -- "$cur" ) )
+                        return 0
+                    fi
+
+                    if [[ $prev == "$command" ]]; then
+                        COMPREPLY=( $( compgen -W "id pinned" -- "$cur" ) )
+                        return 0
+                    fi
+                    return 0
+                    ;;
                 load)
                     local obj
 
@@ -347,7 +364,7 @@ _bpftool()
                     ;;
                 *)
                     [[ $prev == $object ]] && \
-                        COMPREPLY=( $( compgen -W 'dump help pin load \
+                        COMPREPLY=( $( compgen -W 'dump help pin attach detach load \
                             show list' -- "$cur" ) )
                     ;;
             esac
index b1cd3bc8db7055020006b1da2bb6843dcdbb0bcc..99ab42c56724e24efe5a9ac3ac8d50c453a0d17c 100644 (file)
@@ -77,6 +77,26 @@ static const char * const prog_type_name[] = {
        [BPF_PROG_TYPE_FLOW_DISSECTOR]  = "flow_dissector",
 };
 
+static const char * const attach_type_strings[] = {
+       [BPF_SK_SKB_STREAM_PARSER] = "stream_parser",
+       [BPF_SK_SKB_STREAM_VERDICT] = "stream_verdict",
+       [BPF_SK_MSG_VERDICT] = "msg_verdict",
+       [__MAX_BPF_ATTACH_TYPE] = NULL,
+};
+
+enum bpf_attach_type parse_attach_type(const char *str)
+{
+       enum bpf_attach_type type;
+
+       for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++) {
+               if (attach_type_strings[type] &&
+                   is_prefix(str, attach_type_strings[type]))
+                       return type;
+       }
+
+       return __MAX_BPF_ATTACH_TYPE;
+}
+
 static void print_boot_time(__u64 nsecs, char *buf, unsigned int size)
 {
        struct timespec real_time_ts, boot_time_ts;
@@ -697,6 +717,77 @@ int map_replace_compar(const void *p1, const void *p2)
        return a->idx - b->idx;
 }
 
+static int do_attach(int argc, char **argv)
+{
+       enum bpf_attach_type attach_type;
+       int err, mapfd, progfd;
+
+       if (!REQ_ARGS(5)) {
+               p_err("too few parameters for map attach");
+               return -EINVAL;
+       }
+
+       progfd = prog_parse_fd(&argc, &argv);
+       if (progfd < 0)
+               return progfd;
+
+       attach_type = parse_attach_type(*argv);
+       if (attach_type == __MAX_BPF_ATTACH_TYPE) {
+               p_err("invalid attach type");
+               return -EINVAL;
+       }
+       NEXT_ARG();
+
+       mapfd = map_parse_fd(&argc, &argv);
+       if (mapfd < 0)
+               return mapfd;
+
+       err = bpf_prog_attach(progfd, mapfd, attach_type, 0);
+       if (err) {
+               p_err("failed prog attach to map");
+               return -EINVAL;
+       }
+
+       if (json_output)
+               jsonw_null(json_wtr);
+       return 0;
+}
+
+static int do_detach(int argc, char **argv)
+{
+       enum bpf_attach_type attach_type;
+       int err, mapfd, progfd;
+
+       if (!REQ_ARGS(5)) {
+               p_err("too few parameters for map detach");
+               return -EINVAL;
+       }
+
+       progfd = prog_parse_fd(&argc, &argv);
+       if (progfd < 0)
+               return progfd;
+
+       attach_type = parse_attach_type(*argv);
+       if (attach_type == __MAX_BPF_ATTACH_TYPE) {
+               p_err("invalid attach type");
+               return -EINVAL;
+       }
+       NEXT_ARG();
+
+       mapfd = map_parse_fd(&argc, &argv);
+       if (mapfd < 0)
+               return mapfd;
+
+       err = bpf_prog_detach2(progfd, mapfd, attach_type);
+       if (err) {
+               p_err("failed prog detach from map");
+               return -EINVAL;
+       }
+
+       if (json_output)
+               jsonw_null(json_wtr);
+       return 0;
+}
 static int do_load(int argc, char **argv)
 {
        enum bpf_attach_type expected_attach_type;
@@ -942,6 +1033,8 @@ static int do_help(int argc, char **argv)
                "       %s %s pin   PROG FILE\n"
                "       %s %s load  OBJ  FILE [type TYPE] [dev NAME] \\\n"
                "                         [map { idx IDX | name NAME } MAP]\n"
+               "       %s %s attach PROG ATTACH_TYPE MAP\n"
+               "       %s %s detach PROG ATTACH_TYPE MAP\n"
                "       %s %s help\n"
                "\n"
                "       " HELP_SPEC_MAP "\n"
@@ -953,10 +1046,12 @@ static int do_help(int argc, char **argv)
                "                 cgroup/bind4 | cgroup/bind6 | cgroup/post_bind4 |\n"
                "                 cgroup/post_bind6 | cgroup/connect4 | cgroup/connect6 |\n"
                "                 cgroup/sendmsg4 | cgroup/sendmsg6 }\n"
+               "       ATTACH_TYPE := { msg_verdict | skb_verdict | skb_parse }\n"
                "       " HELP_SPEC_OPTIONS "\n"
                "",
                bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
-               bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2]);
+               bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
+               bin_name, argv[-2], bin_name, argv[-2]);
 
        return 0;
 }
@@ -968,6 +1063,8 @@ static const struct cmd cmds[] = {
        { "dump",       do_dump },
        { "pin",        do_pin },
        { "load",       do_load },
+       { "attach",     do_attach },
+       { "detach",     do_detach },
        { 0 }
 };