[RFC PATCH bpf-next v2 13/17] tools/libbpf: libbpf support for bpfdump

Yonghong Song
2020-04-15T19:29:03Z

Add a few libbpf APIs for bpfdump pin.

Also, parse the dump program section name,
retrieve the dump target path and open the path
to get a fd and assignment to prog->attach_target_fd.
The implementation is absolutely minimum and hacky now.

Signed-off-by: Yonghong Song <yhs@fb.com>
---
tools/lib/bpf/bpf.c | 9 +++-
tools/lib/bpf/bpf.h | 1 +
tools/lib/bpf/libbpf.c | 88 +++++++++++++++++++++++++++++++++++++---
tools/lib/bpf/libbpf.h | 3 ++
tools/lib/bpf/libbpf.map | 2 +
5 files changed, 95 insertions(+), 8 deletions(-)

diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 5cc1b0785d18..b23f11c53109 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -238,10 +238,15 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
if (attr.prog_type == BPF_PROG_TYPE_STRUCT_OPS ||
attr.prog_type == BPF_PROG_TYPE_LSM) {
attr.attach_btf_id = load_attr->attach_btf_id;
- } else if (attr.prog_type == BPF_PROG_TYPE_TRACING ||
- attr.prog_type == BPF_PROG_TYPE_EXT) {
+ } else if (attr.prog_type == BPF_PROG_TYPE_EXT) {
attr.attach_btf_id = load_attr->attach_btf_id;
attr.attach_prog_fd = load_attr->attach_prog_fd;
+ } else if (attr.prog_type == BPF_PROG_TYPE_TRACING) {
+ attr.attach_btf_id = load_attr->attach_btf_id;
+ if (attr.expected_attach_type == BPF_TRACE_DUMP)
+ attr.attach_target_fd = load_attr->attach_target_fd;
+ else
+ attr.attach_prog_fd = load_attr->attach_prog_fd;
} else {
attr.prog_ifindex = load_attr->prog_ifindex;
attr.kern_version = load_attr->kern_version;
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 46d47afdd887..7f8d740afde9 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -81,6 +81,7 @@ struct bpf_load_program_attr {
union {
__u32 kern_version;
__u32 attach_prog_fd;
+ __u32 attach_target_fd;
};
union {
__u32 prog_ifindex;
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index ff9174282a8c..ad7726c0c1dc 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -79,6 +79,7 @@ static struct bpf_program *bpf_object__find_prog_by_idx(struct bpf_object *obj,
int idx);
static const struct btf_type *
skip_mods_and_typedefs(const struct btf *btf, __u32 id, __u32 *res_id);
+static int fill_dumper_info(struct bpf_program *prog);

static int __base_pr(enum libbpf_print_level level, const char *format,
va_list args)
@@ -229,6 +230,7 @@ struct bpf_program {
enum bpf_attach_type expected_attach_type;
__u32 attach_btf_id;
__u32 attach_prog_fd;
+ __u32 attach_target_fd;
void *func_info;
__u32 func_info_rec_size;
__u32 func_info_cnt;
@@ -2365,8 +2367,12 @@ static inline bool libbpf_prog_needs_vmlinux_btf(struct bpf_program *prog)
/* BPF_PROG_TYPE_TRACING programs which do not attach to other programs
* also need vmlinux BTF
*/
- if (prog->type == BPF_PROG_TYPE_TRACING && !prog->attach_prog_fd)
- return true;
+ if (prog->type == BPF_PROG_TYPE_TRACING) {
+ if (prog->expected_attach_type == BPF_TRACE_DUMP)
+ return false;
+ if (!prog->attach_prog_fd)
+ return true;
+ }

return false;
}
@@ -4870,10 +4876,15 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
if (prog->type == BPF_PROG_TYPE_STRUCT_OPS ||
prog->type == BPF_PROG_TYPE_LSM) {
load_attr.attach_btf_id = prog->attach_btf_id;
- } else if (prog->type == BPF_PROG_TYPE_TRACING ||
- prog->type == BPF_PROG_TYPE_EXT) {
+ } else if (prog->type == BPF_PROG_TYPE_EXT) {
load_attr.attach_prog_fd = prog->attach_prog_fd;
load_attr.attach_btf_id = prog->attach_btf_id;
+ } else if (prog->type == BPF_PROG_TYPE_TRACING) {
+ load_attr.attach_btf_id = prog->attach_btf_id;
+ if (load_attr.expected_attach_type == BPF_TRACE_DUMP)
+ load_attr.attach_target_fd = prog->attach_target_fd;
+ else
+ load_attr.attach_prog_fd = prog->attach_prog_fd;
} else {
load_attr.kern_version = kern_version;
load_attr.prog_ifindex = prog->prog_ifindex;
@@ -4958,7 +4969,7 @@ int bpf_program__load(struct bpf_program *prog, char *license, __u32 kern_ver)
{
int err = 0, fd, i, btf_id;

- if ((prog->type == BPF_PROG_TYPE_TRACING ||
+ if (((prog->type == BPF_PROG_TYPE_TRACING && prog->expected_attach_type != BPF_TRACE_DUMP) ||
prog->type == BPF_PROG_TYPE_LSM ||
prog->type == BPF_PROG_TYPE_EXT) && !prog->attach_btf_id) {
btf_id = libbpf_find_attach_btf_id(prog);
@@ -5319,6 +5330,7 @@ static int bpf_object__resolve_externs(struct bpf_object *obj,

int bpf_object__load_xattr(struct bpf_object_load_attr *attr)
{
+ struct bpf_program *prog;
struct bpf_object *obj;
int err, i;

@@ -5335,7 +5347,17 @@ int bpf_object__load_xattr(struct bpf_object_load_attr *attr)

obj->loaded = true;

- err = bpf_object__probe_caps(obj);
+ err = 0;
+ bpf_object__for_each_program(prog, obj) {
+ if (prog->type == BPF_PROG_TYPE_TRACING &&
+ prog->expected_attach_type == BPF_TRACE_DUMP) {
+ err = fill_dumper_info(prog);
+ if (err)
+ break;
+ }
+ }
+
+ err = err ? : bpf_object__probe_caps(obj);
err = err ? : bpf_object__resolve_externs(obj, obj->kconfig);
err = err ? : bpf_object__sanitize_and_load_btf(obj);
err = err ? : bpf_object__sanitize_maps(obj);
@@ -6322,6 +6344,8 @@ static const struct bpf_sec_def section_defs[] = {
.is_attach_btf = true,
.expected_attach_type = BPF_LSM_MAC,
.attach_fn = attach_lsm),
+ SEC_DEF("dump/", TRACING,
+ .expected_attach_type = BPF_TRACE_DUMP),
BPF_PROG_SEC("xdp", BPF_PROG_TYPE_XDP),
BPF_PROG_SEC("perf_event", BPF_PROG_TYPE_PERF_EVENT),
BPF_PROG_SEC("lwt_in", BPF_PROG_TYPE_LWT_IN),
@@ -6401,6 +6425,58 @@ static const struct bpf_sec_def *find_sec_def(const char *sec_name)
return NULL;
}

+static int fill_dumper_info(struct bpf_program *prog)
+{
+ const struct bpf_sec_def *sec;
+ const char *dump_target;
+ int fd;
+
+ sec = find_sec_def(bpf_program__title(prog, false));
+ if (sec) {
+ dump_target = bpf_program__title(prog, false) + sec->len;
+ fd = open(dump_target, O_RDONLY);
+ if (fd < 0)
+ return fd;
+ prog->attach_target_fd = fd;
+ }
+ return 0;
+}
+
+int bpf_dump__pin(struct bpf_program *prog, const char *dname)
+{
+ int len, prog_fd = bpf_program__fd(prog);
+ const struct bpf_sec_def *sec;
+ const char *dump_target;
+ char *name_buf;
+ int err;
+
+ if (dname[0] == '/')
+ return bpf_obj_pin(prog_fd, dname);
+
+ sec = find_sec_def(bpf_program__title(prog, false));
+ if (!sec)
+ return bpf_obj_pin(prog_fd, dname);
+
+ dump_target = bpf_program__title(prog, false) + sec->len;
+ len = strlen(dump_target) + strlen(dname) + 2;
+ name_buf = malloc(len);
+ if (!name_buf)
+ return -ENOMEM;
+
+ strcpy(name_buf, dump_target);
+ strcat(name_buf, "/");
+ strcat(name_buf, dname);
+
+ err = bpf_obj_pin(prog_fd, name_buf);
+ free(name_buf);
+ return err;
+}
+
+int bpf_dump__unpin(struct bpf_program *prog, const char *dname)
+{
+ return -EINVAL;
+}
+
static char *libbpf_get_type_names(bool attach_type)
{
int i, len = ARRAY_SIZE(section_defs) * MAX_TYPE_NAME_SIZE;
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 44df1d3e7287..e0d31e93d21c 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -217,6 +217,9 @@ LIBBPF_API int bpf_program__pin(struct bpf_program *prog, const char *path);
LIBBPF_API int bpf_program__unpin(struct bpf_program *prog, const char *path);
LIBBPF_API void bpf_program__unload(struct bpf_program *prog);

+LIBBPF_API int bpf_dump__pin(struct bpf_program *prog, const char *dname);
+LIBBPF_API int bpf_dump__unpin(struct bpf_program *prog, const char *dname);
+
struct bpf_link;

LIBBPF_API struct bpf_link *bpf_link__open(const char *path);
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index bb8831605b25..0beb70bfe65a 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -238,6 +238,8 @@ LIBBPF_0.0.7 {

LIBBPF_0.0.8 {
global:
+ bpf_dump__pin;
+ bpf_dump__unpin;
bpf_link__fd;
bpf_link__open;
bpf_link__pin;
--
2.24.1