netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Yonghong Song <yhs@fb.com>
To: Andrii Nakryiko <andriin@fb.com>, <bpf@vger.kernel.org>,
	Martin KaFai Lau <kafai@fb.com>, <netdev@vger.kernel.org>
Cc: Alexei Starovoitov <ast@fb.com>,
	Daniel Borkmann <daniel@iogearbox.net>, <kernel-team@fb.com>
Subject: [RFC PATCH bpf-next v2 13/17] tools/libbpf: libbpf support for bpfdump
Date: Wed, 15 Apr 2020 12:27:55 -0700	[thread overview]
Message-ID: <20200415192755.4083842-1-yhs@fb.com> (raw)
In-Reply-To: <20200415192740.4082659-1-yhs@fb.com>

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


  parent reply	other threads:[~2020-04-15 19:29 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-15 19:27 [RFC PATCH bpf-next v2 00/17] bpf: implement bpf based dumping of kernel data structures Yonghong Song
2020-04-15 19:27 ` [RFC PATCH bpf-next v2 01/17] net: refactor net assignment for seq_net_private structure Yonghong Song
2020-04-15 19:27 ` [RFC PATCH bpf-next v2 02/17] bpf: create /sys/kernel/bpfdump mount file system Yonghong Song
2020-04-15 19:27 ` [RFC PATCH bpf-next v2 03/17] bpf: provide a way for targets to register themselves Yonghong Song
2020-04-15 19:27 ` [RFC PATCH bpf-next v2 04/17] bpf: allow loading of a dumper program Yonghong Song
2020-04-15 19:27 ` [RFC PATCH bpf-next v2 05/17] bpf: create file or anonymous dumpers Yonghong Song
2020-04-15 19:27 ` [RFC PATCH bpf-next v2 06/17] bpf: add PTR_TO_BTF_ID_OR_NULL support Yonghong Song
2020-04-15 19:27 ` [RFC PATCH bpf-next v2 07/17] bpf: add netlink and ipv6_route targets Yonghong Song
2020-04-15 19:27 ` [RFC PATCH bpf-next v2 08/17] bpf: add bpf_map target Yonghong Song
2020-04-15 19:27 ` [RFC PATCH bpf-next v2 09/17] bpf: add task and task/file targets Yonghong Song
2020-04-15 19:27 ` [RFC PATCH bpf-next v2 10/17] bpf: add bpf_seq_printf and bpf_seq_write helpers Yonghong Song
2020-04-15 19:27 ` [RFC PATCH bpf-next v2 11/17] bpf: support variable length array in tracing programs Yonghong Song
2020-04-15 19:27 ` [RFC PATCH bpf-next v2 12/17] bpf: implement query for target_proto and file dumper prog_id Yonghong Song
2020-04-15 19:27 ` Yonghong Song [this message]
2020-04-15 19:27 ` [RFC PATCH bpf-next v2 14/17] tools/bpftool: add bpf dumper support Yonghong Song
2020-04-15 19:27 ` [RFC PATCH bpf-next v2 15/17] tools/bpf: selftests: add dumper programs for ipv6_route and netlink Yonghong Song
2020-04-15 19:27 ` [RFC PATCH bpf-next v2 16/17] tools/bpf: selftests: add dumper progs for bpf_map/task/task_file Yonghong Song
2020-04-15 19:28 ` [RFC PATCH bpf-next v2 17/17] tools/bpf: selftests: add a selftest for anonymous dumper Yonghong Song
2020-04-16  2:23 ` [RFC PATCH bpf-next v2 00/17] bpf: implement bpf based dumping of kernel data structures David Ahern
2020-04-16  6:41   ` Yonghong Song
2020-04-17 15:02     ` Alan Maguire
2020-04-19  5:34       ` Yonghong Song
2020-04-17 10:54   ` Alan Maguire
2020-04-19  5:30     ` Yonghong Song

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200415192755.4083842-1-yhs@fb.com \
    --to=yhs@fb.com \
    --cc=andriin@fb.com \
    --cc=ast@fb.com \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=kafai@fb.com \
    --cc=kernel-team@fb.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).