Commit c09add2f authored by Yonghong Song's avatar Yonghong Song Committed by Alexei Starovoitov
Browse files

tools/libbpf: Add bpf_iter support



Two new libbpf APIs are added to support bpf_iter:
  - bpf_program__attach_iter
    Given a bpf program and additional parameters, which is
    none now, returns a bpf_link.
  - bpf_iter_create
    syscall level API to create a bpf iterator.

The macro BPF_SEQ_PRINTF are also introduced. The format
looks like:
  BPF_SEQ_PRINTF(seq, "task id %d\n", pid);

This macro can help bpf program writers with
nicer bpf_seq_printf syntax similar to the kernel one.

Signed-off-by: default avatarYonghong Song <yhs@fb.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Acked-by: default avatarAndrii Nakryiko <andriin@fb.com>
Link: https://lore.kernel.org/bpf/20200509175917.2476936-1-yhs@fb.com
parent 9c5f8a10
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -619,6 +619,16 @@ int bpf_link_update(int link_fd, int new_prog_fd,
	return sys_bpf(BPF_LINK_UPDATE, &attr, sizeof(attr));
}

int bpf_iter_create(int link_fd)
{
	union bpf_attr attr;

	memset(&attr, 0, sizeof(attr));
	attr.iter_create.link_fd = link_fd;

	return sys_bpf(BPF_ITER_CREATE, &attr, sizeof(attr));
}

int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
		   __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt)
{
+2 −0
Original line number Diff line number Diff line
@@ -187,6 +187,8 @@ struct bpf_link_update_opts {
LIBBPF_API int bpf_link_update(int link_fd, int new_prog_fd,
			       const struct bpf_link_update_opts *opts);

LIBBPF_API int bpf_iter_create(int link_fd);

struct bpf_prog_test_run_attr {
	int prog_fd;
	int repeat;
+16 −0
Original line number Diff line number Diff line
@@ -413,4 +413,20 @@ typeof(name(0)) name(struct pt_regs *ctx) \
}									    \
static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args)

/*
 * BPF_SEQ_PRINTF to wrap bpf_seq_printf to-be-printed values
 * in a structure.
 */
#define BPF_SEQ_PRINTF(seq, fmt, args...)				    \
	({								    \
		_Pragma("GCC diagnostic push")				    \
		_Pragma("GCC diagnostic ignored \"-Wint-conversion\"")	    \
		static const char ___fmt[] = fmt;			    \
		unsigned long long ___param[] = { args };		    \
		_Pragma("GCC diagnostic pop")				    \
		int ___ret = bpf_seq_printf(seq, ___fmt, sizeof(___fmt),    \
					    ___param, sizeof(___param));    \
		___ret;							    \
	})

#endif
+52 −0
Original line number Diff line number Diff line
@@ -6586,6 +6586,8 @@ static struct bpf_link *attach_trace(const struct bpf_sec_def *sec,
				     struct bpf_program *prog);
static struct bpf_link *attach_lsm(const struct bpf_sec_def *sec,
				   struct bpf_program *prog);
static struct bpf_link *attach_iter(const struct bpf_sec_def *sec,
				    struct bpf_program *prog);

static const struct bpf_sec_def section_defs[] = {
	BPF_PROG_SEC("socket",			BPF_PROG_TYPE_SOCKET_FILTER),
@@ -6629,6 +6631,10 @@ static const struct bpf_sec_def section_defs[] = {
		.is_attach_btf = true,
		.expected_attach_type = BPF_LSM_MAC,
		.attach_fn = attach_lsm),
	SEC_DEF("iter/", TRACING,
		.expected_attach_type = BPF_TRACE_ITER,
		.is_attach_btf = true,
		.attach_fn = attach_iter),
	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),
@@ -6891,6 +6897,7 @@ invalid_prog:

#define BTF_TRACE_PREFIX "btf_trace_"
#define BTF_LSM_PREFIX "bpf_lsm_"
#define BTF_ITER_PREFIX "__bpf_iter__"
#define BTF_MAX_NAME_SIZE 128

static int find_btf_by_prefix_kind(const struct btf *btf, const char *prefix,
@@ -6921,6 +6928,9 @@ static inline int __find_vmlinux_btf_id(struct btf *btf, const char *name,
	else if (attach_type == BPF_LSM_MAC)
		err = find_btf_by_prefix_kind(btf, BTF_LSM_PREFIX, name,
					      BTF_KIND_FUNC);
	else if (attach_type == BPF_TRACE_ITER)
		err = find_btf_by_prefix_kind(btf, BTF_ITER_PREFIX, name,
					      BTF_KIND_FUNC);
	else
		err = btf__find_by_name_kind(btf, name, BTF_KIND_FUNC);

@@ -7848,6 +7858,12 @@ static struct bpf_link *attach_lsm(const struct bpf_sec_def *sec,
	return bpf_program__attach_lsm(prog);
}

static struct bpf_link *attach_iter(const struct bpf_sec_def *sec,
				    struct bpf_program *prog)
{
	return bpf_program__attach_iter(prog, NULL);
}

struct bpf_link *
bpf_program__attach_cgroup(struct bpf_program *prog, int cgroup_fd)
{
@@ -7882,6 +7898,42 @@ bpf_program__attach_cgroup(struct bpf_program *prog, int cgroup_fd)
	return link;
}

struct bpf_link *
bpf_program__attach_iter(struct bpf_program *prog,
			 const struct bpf_iter_attach_opts *opts)
{
	char errmsg[STRERR_BUFSIZE];
	struct bpf_link *link;
	int prog_fd, link_fd;

	if (!OPTS_VALID(opts, bpf_iter_attach_opts))
		return ERR_PTR(-EINVAL);

	prog_fd = bpf_program__fd(prog);
	if (prog_fd < 0) {
		pr_warn("program '%s': can't attach before loaded\n",
			bpf_program__title(prog, false));
		return ERR_PTR(-EINVAL);
	}

	link = calloc(1, sizeof(*link));
	if (!link)
		return ERR_PTR(-ENOMEM);
	link->detach = &bpf_link__detach_fd;

	link_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_ITER, NULL);
	if (link_fd < 0) {
		link_fd = -errno;
		free(link);
		pr_warn("program '%s': failed to attach to iterator: %s\n",
			bpf_program__title(prog, false),
			libbpf_strerror_r(link_fd, errmsg, sizeof(errmsg)));
		return ERR_PTR(link_fd);
	}
	link->fd = link_fd;
	return link;
}

struct bpf_link *bpf_program__attach(struct bpf_program *prog)
{
	const struct bpf_sec_def *sec_def;
+9 −0
Original line number Diff line number Diff line
@@ -258,6 +258,15 @@ struct bpf_map;

LIBBPF_API struct bpf_link *bpf_map__attach_struct_ops(struct bpf_map *map);

struct bpf_iter_attach_opts {
	size_t sz; /* size of this struct for forward/backward compatibility */
};
#define bpf_iter_attach_opts__last_field sz

LIBBPF_API struct bpf_link *
bpf_program__attach_iter(struct bpf_program *prog,
			 const struct bpf_iter_attach_opts *opts);

struct bpf_insn;

/*
Loading