bpftool: implement prog load command
authorRoman Gushchin <guro@fb.com>
Wed, 13 Dec 2017 15:18:53 +0000 (15:18 +0000)
committerDaniel Borkmann <daniel@iogearbox.net>
Thu, 14 Dec 2017 12:37:13 +0000 (13:37 +0100)
Add the prog load command to load a bpf program from a specified
binary file and pin it to bpffs.

Usage description and examples are given in the corresponding man
page.

Syntax:
$ bpftool prog load OBJ FILE

FILE is a non-existing file on bpffs.

Signed-off-by: Roman Gushchin <guro@fb.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Cc: Martin KaFai Lau <kafai@fb.com>
Cc: Quentin Monnet <quentin.monnet@netronome.com>
Cc: David Ahern <dsahern@gmail.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
tools/bpf/bpftool/Documentation/bpftool-prog.rst
tools/bpf/bpftool/Documentation/bpftool.rst
tools/bpf/bpftool/common.c
tools/bpf/bpftool/main.h
tools/bpf/bpftool/prog.c

index 36e8d1c3c40d15e3b9cca40c2780393977d77cfa..ffdb20e8280f07543ba38ca080049eaea6b2a9eb 100644 (file)
@@ -15,7 +15,7 @@ SYNOPSIS
        *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-f** | **--bpffs** } }
 
        *COMMANDS* :=
-       { **show** | **dump xlated** | **dump jited** | **pin** | **help** }
+       { **show** | **dump xlated** | **dump jited** | **pin** | **load** | **help** }
 
 MAP COMMANDS
 =============
@@ -24,6 +24,7 @@ MAP COMMANDS
 |      **bpftool** **prog dump xlated** *PROG* [{**file** *FILE* | **opcodes**}]
 |      **bpftool** **prog dump jited**  *PROG* [{**file** *FILE* | **opcodes**}]
 |      **bpftool** **prog pin** *PROG* *FILE*
+|      **bpftool** **prog load** *OBJ* *FILE*
 |      **bpftool** **prog help**
 |
 |      *PROG* := { **id** *PROG_ID* | **pinned** *FILE* | **tag** *PROG_TAG* }
@@ -57,6 +58,11 @@ DESCRIPTION
 
                  Note: *FILE* must be located in *bpffs* mount.
 
+       **bpftool prog load** *OBJ* *FILE*
+                 Load bpf program from binary *OBJ* and pin as *FILE*.
+
+                 Note: *FILE* must be located in *bpffs* mount.
+
        **bpftool prog help**
                  Print short help message.
 
@@ -126,8 +132,10 @@ EXAMPLES
 |
 | **# mount -t bpf none /sys/fs/bpf/**
 | **# bpftool prog pin id 10 /sys/fs/bpf/prog**
+| **# bpftool prog load ./my_prog.o /sys/fs/bpf/prog2**
 | **# ls -l /sys/fs/bpf/**
 |   -rw------- 1 root root 0 Jul 22 01:43 prog
+|   -rw------- 1 root root 0 Jul 22 01:44 prog2
 
 **# bpftool prog dum jited pinned /sys/fs/bpf/prog opcodes**
 
index 926c03d5a8da05dc932b20f9a148e39c8aff5900..f547a0c0aa3490bd086087a147d037561b2f367c 100644 (file)
@@ -26,7 +26,7 @@ SYNOPSIS
        | **pin** | **help** }
 
        *PROG-COMMANDS* := { **show** | **dump jited** | **dump xlated** | **pin**
-       | **help** }
+       | **load** | **help** }
 
 DESCRIPTION
 ===========
index 2bd3b280e6dd24292cb30dca71b9db9ef18ac804..b62c94e3997a3e0e443e349a8cf32707bb40bdb0 100644 (file)
@@ -163,13 +163,49 @@ int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type)
        return fd;
 }
 
-int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
+int do_pin_fd(int fd, const char *name)
 {
        char err_str[ERR_MAX_LEN];
-       unsigned int id;
-       char *endptr;
        char *file;
        char *dir;
+       int err = 0;
+
+       err = bpf_obj_pin(fd, name);
+       if (!err)
+               goto out;
+
+       file = malloc(strlen(name) + 1);
+       strcpy(file, name);
+       dir = dirname(file);
+
+       if (errno != EPERM || is_bpffs(dir)) {
+               p_err("can't pin the object (%s): %s", name, strerror(errno));
+               goto out_free;
+       }
+
+       /* Attempt to mount bpffs, then retry pinning. */
+       err = mnt_bpffs(dir, err_str, ERR_MAX_LEN);
+       if (!err) {
+               err = bpf_obj_pin(fd, name);
+               if (err)
+                       p_err("can't pin the object (%s): %s", name,
+                             strerror(errno));
+       } else {
+               err_str[ERR_MAX_LEN - 1] = '\0';
+               p_err("can't mount BPF file system to pin the object (%s): %s",
+                     name, err_str);
+       }
+
+out_free:
+       free(file);
+out:
+       return err;
+}
+
+int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
+{
+       unsigned int id;
+       char *endptr;
        int err;
        int fd;
 
@@ -195,35 +231,8 @@ int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
                return -1;
        }
 
-       err = bpf_obj_pin(fd, *argv);
-       if (!err)
-               goto out_close;
-
-       file = malloc(strlen(*argv) + 1);
-       strcpy(file, *argv);
-       dir = dirname(file);
-
-       if (errno != EPERM || is_bpffs(dir)) {
-               p_err("can't pin the object (%s): %s", *argv, strerror(errno));
-               goto out_free;
-       }
+       err = do_pin_fd(fd, *argv);
 
-       /* Attempt to mount bpffs, then retry pinning. */
-       err = mnt_bpffs(dir, err_str, ERR_MAX_LEN);
-       if (!err) {
-               err = bpf_obj_pin(fd, *argv);
-               if (err)
-                       p_err("can't pin the object (%s): %s", *argv,
-                             strerror(errno));
-       } else {
-               err_str[ERR_MAX_LEN - 1] = '\0';
-               p_err("can't mount BPF file system to pin the object (%s): %s",
-                     *argv, err_str);
-       }
-
-out_free:
-       free(file);
-out_close:
        close(fd);
        return err;
 }
index bff330b49791e5bc6021d8188bd0e637db20ea3b..bec1ccbb49c706158fa0bd241b8e1e9581f684f5 100644 (file)
@@ -111,6 +111,7 @@ char *get_fdinfo(int fd, const char *key);
 int open_obj_pinned(char *path);
 int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type);
 int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32));
+int do_pin_fd(int fd, const char *name);
 
 int do_prog(int argc, char **arg);
 int do_map(int argc, char **arg);
index ad619b96c27664300df9a78bc28958c4d8662a4b..037484ceaeaf7fec83e5ccce426c5913f8f8e7e5 100644 (file)
@@ -45,6 +45,7 @@
 #include <sys/stat.h>
 
 #include <bpf.h>
+#include <libbpf.h>
 
 #include "main.h"
 #include "disasm.h"
@@ -635,6 +636,30 @@ static int do_pin(int argc, char **argv)
        return err;
 }
 
+static int do_load(int argc, char **argv)
+{
+       struct bpf_object *obj;
+       int prog_fd;
+
+       if (argc != 2)
+               usage();
+
+       if (bpf_prog_load(argv[0], BPF_PROG_TYPE_UNSPEC, &obj, &prog_fd)) {
+               p_err("failed to load program\n");
+               return -1;
+       }
+
+       if (do_pin_fd(prog_fd, argv[1])) {
+               p_err("failed to pin program\n");
+               return -1;
+       }
+
+       if (json_output)
+               jsonw_null(json_wtr);
+
+       return 0;
+}
+
 static int do_help(int argc, char **argv)
 {
        if (json_output) {
@@ -647,13 +672,14 @@ static int do_help(int argc, char **argv)
                "       %s %s dump xlated PROG [{ file FILE | opcodes }]\n"
                "       %s %s dump jited  PROG [{ file FILE | opcodes }]\n"
                "       %s %s pin   PROG FILE\n"
+               "       %s %s load  OBJ  FILE\n"
                "       %s %s help\n"
                "\n"
                "       " HELP_SPEC_PROGRAM "\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]);
 
        return 0;
 }
@@ -663,6 +689,7 @@ static const struct cmd cmds[] = {
        { "help",       do_help },
        { "dump",       do_dump },
        { "pin",        do_pin },
+       { "load",       do_load },
        { 0 }
 };