Commit 12f96823 authored by Alexei Starovoitov's avatar Alexei Starovoitov

Merge branch 'bpftool: Add autoattach for bpf prog load|loadall'

Wang Yufen says:

====================

This patchset add "autoattach" optional for "bpftool prog load(_all)" to support
one-step load-attach-pin_link.

v8 -> v9: fix link leak, and change pathname_concat(specify not just buffer
	  pointer, but also it's size)
v7 -> v8: for the programs not supporting autoattach, fall back to reguler pinning
	  instead of skipping
v6 -> v7: add info msg print and update doc for the skip program
v5 -> v6: skip the programs not supporting auto-attach,
	  and change optional name from "auto_attach" to "autoattach"
v4 -> v5: some formatting nits of doc
v3 -> v4: rename functions, update doc, bash and do_help()
v2 -> v3: switch to extend prog load command instead of extend perf
v2: https://patchwork.kernel.org/project/netdevbpf/patch/20220824033837.458197-1-weiyongjun1@huawei.com/
v1: https://patchwork.kernel.org/project/netdevbpf/patch/20220816151725.153343-1-weiyongjun1@huawei.com/
====================
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parents 98af3746 b81a6774
......@@ -31,7 +31,7 @@ PROG COMMANDS
| **bpftool** **prog dump xlated** *PROG* [{**file** *FILE* | **opcodes** | **visual** | **linum**}]
| **bpftool** **prog dump jited** *PROG* [{**file** *FILE* | **opcodes** | **linum**}]
| **bpftool** **prog pin** *PROG* *FILE*
| **bpftool** **prog** { **load** | **loadall** } *OBJ* *PATH* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*] [**pinmaps** *MAP_DIR*]
| **bpftool** **prog** { **load** | **loadall** } *OBJ* *PATH* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*] [**pinmaps** *MAP_DIR*] [**autoattach**]
| **bpftool** **prog attach** *PROG* *ATTACH_TYPE* [*MAP*]
| **bpftool** **prog detach** *PROG* *ATTACH_TYPE* [*MAP*]
| **bpftool** **prog tracelog**
......@@ -131,7 +131,7 @@ DESCRIPTION
contain a dot character ('.'), which is reserved for future
extensions of *bpffs*.
**bpftool prog { load | loadall }** *OBJ* *PATH* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*] [**pinmaps** *MAP_DIR*]
**bpftool prog { load | loadall }** *OBJ* *PATH* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*] [**pinmaps** *MAP_DIR*] [**autoattach**]
Load bpf program(s) from binary *OBJ* and pin as *PATH*.
**bpftool prog load** pins only the first program from the
*OBJ* as *PATH*. **bpftool prog loadall** pins all programs
......@@ -150,6 +150,17 @@ DESCRIPTION
Optional **pinmaps** argument can be provided to pin all
maps under *MAP_DIR* directory.
If **autoattach** is specified program will be attached
before pin. In that case, only the link (representing the
program attached to its hook) is pinned, not the program as
such, so the path won't show in **bpftool prog show -f**,
only show in **bpftool link show -f**. Also, this only works
when bpftool (libbpf) is able to infer all necessary
information from the object file, in particular, it's not
supported for all program types. If a program does not
support autoattach, bpftool falls back to regular pinning
for that program instead.
Note: *PATH* must be located in *bpffs* mount. It must not
contain a dot character ('.'), which is reserved for future
extensions of *bpffs*.
......
......@@ -505,6 +505,7 @@ _bpftool()
_bpftool_once_attr 'type'
_bpftool_once_attr 'dev'
_bpftool_once_attr 'pinmaps'
_bpftool_once_attr 'autoattach'
return 0
;;
esac
......
......@@ -1453,6 +1453,67 @@ get_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type,
return ret;
}
static int
auto_attach_program(struct bpf_program *prog, const char *path)
{
struct bpf_link *link;
int err;
link = bpf_program__attach(prog);
if (!link) {
p_info("Program %s does not support autoattach, falling back to pinning",
bpf_program__name(prog));
return bpf_obj_pin(bpf_program__fd(prog), path);
}
err = bpf_link__pin(link, path);
bpf_link__destroy(link);
return err;
}
static int pathname_concat(char *buf, size_t buf_sz, const char *path, const char *name)
{
int len;
len = snprintf(buf, buf_sz, "%s/%s", path, name);
if (len < 0)
return -EINVAL;
if ((size_t)len >= buf_sz)
return -ENAMETOOLONG;
return 0;
}
static int
auto_attach_programs(struct bpf_object *obj, const char *path)
{
struct bpf_program *prog;
char buf[PATH_MAX];
int err;
bpf_object__for_each_program(prog, obj) {
err = pathname_concat(buf, sizeof(buf), path, bpf_program__name(prog));
if (err)
goto err_unpin_programs;
err = auto_attach_program(prog, buf);
if (err)
goto err_unpin_programs;
}
return 0;
err_unpin_programs:
while ((prog = bpf_object__prev_program(obj, prog))) {
if (pathname_concat(buf, sizeof(buf), path, bpf_program__name(prog)))
continue;
bpf_program__unpin(prog, buf);
}
return err;
}
static int load_with_options(int argc, char **argv, bool first_prog_only)
{
enum bpf_prog_type common_prog_type = BPF_PROG_TYPE_UNSPEC;
......@@ -1464,6 +1525,7 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
struct bpf_program *prog = NULL, *pos;
unsigned int old_map_fds = 0;
const char *pinmaps = NULL;
bool auto_attach = false;
struct bpf_object *obj;
struct bpf_map *map;
const char *pinfile;
......@@ -1583,6 +1645,9 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
goto err_free_reuse_maps;
pinmaps = GET_ARG();
} else if (is_prefix(*argv, "autoattach")) {
auto_attach = true;
NEXT_ARG();
} else {
p_err("expected no more arguments, 'type', 'map' or 'dev', got: '%s'?",
*argv);
......@@ -1692,14 +1757,20 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
goto err_close_obj;
}
err = bpf_obj_pin(bpf_program__fd(prog), pinfile);
if (auto_attach)
err = auto_attach_program(prog, pinfile);
else
err = bpf_obj_pin(bpf_program__fd(prog), pinfile);
if (err) {
p_err("failed to pin program %s",
bpf_program__section_name(prog));
goto err_close_obj;
}
} else {
err = bpf_object__pin_programs(obj, pinfile);
if (auto_attach)
err = auto_attach_programs(obj, pinfile);
else
err = bpf_object__pin_programs(obj, pinfile);
if (err) {
p_err("failed to pin all programs");
goto err_close_obj;
......@@ -2338,6 +2409,7 @@ static int do_help(int argc, char **argv)
" [type TYPE] [dev NAME] \\\n"
" [map { idx IDX | name NAME } MAP]\\\n"
" [pinmaps MAP_DIR]\n"
" [autoattach]\n"
" %1$s %2$s attach PROG ATTACH_TYPE [MAP]\n"
" %1$s %2$s detach PROG ATTACH_TYPE [MAP]\n"
" %1$s %2$s run PROG \\\n"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment