bpftool: Match programs by name
authorPaul Chaignon <paul.chaignon@orange.com>
Fri, 13 Dec 2019 19:10:17 +0000 (20:10 +0100)
committerAlexei Starovoitov <ast@kernel.org>
Sun, 15 Dec 2019 17:03:18 +0000 (09:03 -0800)
When working with frequently modified BPF programs, both the ID and the
tag may change.  bpftool currently doesn't provide a "stable" way to match
such programs.

This patch implements lookup by name for programs.  The show and dump
commands will return all programs with the given name, whereas other
commands will error out if several programs have the same name.

Signed-off-by: Paul Chaignon <paul.chaignon@orange.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
Link: https://lore.kernel.org/bpf/b5fc1a5dcfaeb5f16fc80295cdaa606dd2d91534.1576263640.git.paul.chaignon@gmail.com
tools/bpf/bpftool/Documentation/bpftool-map.rst
tools/bpf/bpftool/Documentation/bpftool-prog.rst
tools/bpf/bpftool/bash-completion/bpftool
tools/bpf/bpftool/main.h
tools/bpf/bpftool/prog.c

index 1c0f7146aab0a8fc749f6ec87aae642fd3552783..90d848b5b7d355aa5d1920e04dd686b26b06604e 100644 (file)
@@ -41,7 +41,7 @@ MAP COMMANDS
 |
 |      *MAP* := { **id** *MAP_ID* | **pinned** *FILE* }
 |      *DATA* := { [**hex**] *BYTES* }
-|      *PROG* := { **id** *PROG_ID* | **pinned** *FILE* | **tag** *PROG_TAG* }
+|      *PROG* := { **id** *PROG_ID* | **pinned** *FILE* | **tag** *PROG_TAG* | **name** *PROG_NAME* }
 |      *VALUE* := { *DATA* | *MAP* | *PROG* }
 |      *UPDATE_FLAGS* := { **any** | **exist** | **noexist** }
 |      *TYPE* := { **hash** | **array** | **prog_array** | **perf_event_array** | **percpu_hash**
index d377d0cb792313078393be37d7b9d8ebedf1a1d1..64ddf8a4c518b0caadd6bf7bca3ba2b745ef2a02 100644 (file)
@@ -33,7 +33,7 @@ PROG COMMANDS
 |      **bpftool** **prog help**
 |
 |      *MAP* := { **id** *MAP_ID* | **pinned** *FILE* }
-|      *PROG* := { **id** *PROG_ID* | **pinned** *FILE* | **tag** *PROG_TAG* }
+|      *PROG* := { **id** *PROG_ID* | **pinned** *FILE* | **tag** *PROG_TAG* | **name** *PROG_NAME* }
 |      *TYPE* := {
 |              **socket** | **kprobe** | **kretprobe** | **classifier** | **action** |
 |              **tracepoint** | **raw_tracepoint** | **xdp** | **perf_event** | **cgroup/skb** |
@@ -55,8 +55,8 @@ DESCRIPTION
                  Show information about loaded programs.  If *PROG* is
                  specified show information only about given programs,
                  otherwise list all programs currently loaded on the system.
-                 In case of **tag**, *PROG* may match several programs which
-                 will all be shown.
+                 In case of **tag** or **name**, *PROG* may match several
+                 programs which will all be shown.
 
                  Output will start with program ID followed by program type and
                  zero or more named attributes (depending on kernel version).
@@ -75,9 +75,9 @@ DESCRIPTION
                  output in human-readable format. In this case, **opcodes**
                  controls if raw opcodes should be printed as well.
 
-                 In case of **tag**, *PROG* may match several programs which
-                 will all be dumped.  However, if **file** or **visual** is
-                 specified, *PROG* must match a single program.
+                 In case of **tag** or **name**, *PROG* may match several
+                 programs which will all be dumped.  However, if **file** or
+                 **visual** is specified, *PROG* must match a single program.
 
                  If **file** is specified, the binary image will instead be
                  written to *FILE*.
index 70493a6da206728112149cbb7aa31f3b8448197a..05b5be4a6ef961af5352bef1ac2b2ac9c0469ef4 100644 (file)
@@ -71,6 +71,12 @@ _bpftool_get_prog_tags()
         command sed -n 's/.*"tag": "\(.*\)",$/\1/p' )" -- "$cur" ) )
 }
 
+_bpftool_get_prog_names()
+{
+    COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \
+        command sed -n 's/.*"name": "\(.*\)",$/\1/p' )" -- "$cur" ) )
+}
+
 _bpftool_get_btf_ids()
 {
     COMPREPLY+=( $( compgen -W "$( bpftool -jp btf 2>&1 | \
@@ -201,6 +207,10 @@ _bpftool()
             _bpftool_get_prog_tags
             return 0
             ;;
+        name)
+            _bpftool_get_prog_names
+            return 0
+            ;;
         dev)
             _sysfs_get_netdevs
             return 0
@@ -263,7 +273,7 @@ _bpftool()
                     ;;
             esac
 
-            local PROG_TYPE='id pinned tag'
+            local PROG_TYPE='id pinned tag name'
             local MAP_TYPE='id pinned'
             case $command in
                 show|list)
@@ -559,7 +569,7 @@ _bpftool()
                                     return 0
                                     ;;
                                 prog_array)
-                                    local PROG_TYPE='id pinned tag'
+                                    local PROG_TYPE='id pinned tag name'
                                     COMPREPLY+=( $( compgen -W "$PROG_TYPE" \
                                         -- "$cur" ) )
                                     return 0
@@ -644,7 +654,7 @@ _bpftool()
             esac
             ;;
         btf)
-            local PROG_TYPE='id pinned tag'
+            local PROG_TYPE='id pinned tag name'
             local MAP_TYPE='id pinned'
             case $command in
                 dump)
@@ -735,7 +745,7 @@ _bpftool()
                         connect6 sendmsg4 sendmsg6 recvmsg4 recvmsg6 sysctl \
                         getsockopt setsockopt'
                     local ATTACH_FLAGS='multi override'
-                    local PROG_TYPE='id pinned tag'
+                    local PROG_TYPE='id pinned tag name'
                     case $prev in
                         $command)
                             _filedir
@@ -760,7 +770,7 @@ _bpftool()
                             elif [[ "$command" == "attach" ]]; then
                                 # We have an attach type on the command line,
                                 # but it is not the previous word, or
-                                # "id|pinned|tag" (we already checked for
+                                # "id|pinned|tag|name" (we already checked for
                                 # that). This should only leave the case when
                                 # we need attach flags for "attach" commamnd.
                                 _bpftool_one_of_list "$ATTACH_FLAGS"
@@ -786,7 +796,7 @@ _bpftool()
             esac
             ;;
         net)
-            local PROG_TYPE='id pinned tag'
+            local PROG_TYPE='id pinned tag name'
             local ATTACH_TYPES='xdp xdpgeneric xdpdrv xdpoffload'
             case $command in
                 show|list)
index 2899095f8254f8539b2b0b88a57fed39fe20e679..a7ead7bb94470be2bce22f20969e87cc51722219 100644 (file)
@@ -42,7 +42,7 @@
 #define BPF_TAG_FMT    "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
 
 #define HELP_SPEC_PROGRAM                                              \
-       "PROG := { id PROG_ID | pinned FILE | tag PROG_TAG }"
+       "PROG := { id PROG_ID | pinned FILE | tag PROG_TAG | name PROG_NAME }"
 #define HELP_SPEC_OPTIONS                                              \
        "OPTIONS := { {-j|--json} [{-p|--pretty}] | {-f|--bpffs} |\n"   \
        "\t            {-m|--mapcompat} | {-n|--nomount} }"
index 37948c47aabda80480f2ccdabebcd7a42041fb01..2221bae037f16c14b09987be1a15b83959d5a875 100644 (file)
@@ -82,7 +82,7 @@ static void print_boot_time(__u64 nsecs, char *buf, unsigned int size)
                strftime(buf, size, "%FT%T%z", &load_tm);
 }
 
-static int prog_fd_by_tag(unsigned char *tag, int **fds)
+static int prog_fd_by_nametag(void *nametag, int **fds, bool tag)
 {
        unsigned int id = 0;
        int fd, nb_fds = 0;
@@ -116,7 +116,8 @@ static int prog_fd_by_tag(unsigned char *tag, int **fds)
                        goto err_close_fd;
                }
 
-               if (memcmp(tag, info.tag, BPF_TAG_SIZE)) {
+               if ((tag && memcmp(nametag, info.tag, BPF_TAG_SIZE)) ||
+                   (!tag && strncmp(nametag, info.name, BPF_OBJ_NAME_LEN))) {
                        close(fd);
                        continue;
                }
@@ -174,7 +175,20 @@ static int prog_parse_fds(int *argc, char ***argv, int **fds)
                }
                NEXT_ARGP();
 
-               return prog_fd_by_tag(tag, fds);
+               return prog_fd_by_nametag(tag, fds, true);
+       } else if (is_prefix(**argv, "name")) {
+               char *name;
+
+               NEXT_ARGP();
+
+               name = **argv;
+               if (strlen(name) > BPF_OBJ_NAME_LEN - 1) {
+                       p_err("can't parse name");
+                       return -1;
+               }
+               NEXT_ARGP();
+
+               return prog_fd_by_nametag(name, fds, false);
        } else if (is_prefix(**argv, "pinned")) {
                char *path;
 
@@ -189,7 +203,7 @@ static int prog_parse_fds(int *argc, char ***argv, int **fds)
                return 1;
        }
 
-       p_err("expected 'id', 'tag' or 'pinned', got: '%s'?", **argv);
+       p_err("expected 'id', 'tag', 'name' or 'pinned', got: '%s'?", **argv);
        return -1;
 }