Commit 46a4a970 authored by Daniel Borkmann's avatar Daniel Borkmann
Browse files

Merge branch 'bpf-libbpf-cleanups'



Andrii Nakryiko says:

====================
This patch set's main goal is to teach bpf_object__open() (and its variants)
to automatically derive BPF program type/expected attach type from section
names, similarly to how bpf_prog_load() was doing it. This significantly
improves user experience by eliminating yet another
obvious-only-in-the-hindsight surprise, when using libbpf APIs.

There are a bunch of auxiliary clean-ups and improvements. E.g.,
bpf_program__get_type() and bpf_program__get_expected_attach_type() are added
for completeness and symmetry with corresponding setter APIs. Some clean up
and fixes in selftests/bpf are done as well.
====================

Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parents be18010e 1678e33c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -167,6 +167,8 @@ enum {
	IFLA_NEW_IFINDEX,
	IFLA_MIN_MTU,
	IFLA_MAX_MTU,
	IFLA_PROP_LIST,
	IFLA_ALT_IFNAME, /* Alternative ifname */
	__IFLA_MAX
};

+51 −29
Original line number Diff line number Diff line
@@ -3611,6 +3611,7 @@ static struct bpf_object *
__bpf_object__open(const char *path, const void *obj_buf, size_t obj_buf_sz,
		   struct bpf_object_open_opts *opts)
{
	struct bpf_program *prog;
	struct bpf_object *obj;
	const char *obj_name;
	char tmp_name[64];
@@ -3650,8 +3651,24 @@ __bpf_object__open(const char *path, const void *obj_buf, size_t obj_buf_sz,
	CHECK_ERR(bpf_object__probe_caps(obj), err, out);
	CHECK_ERR(bpf_object__elf_collect(obj, relaxed_maps), err, out);
	CHECK_ERR(bpf_object__collect_reloc(obj), err, out);

	bpf_object__elf_finish(obj);

	bpf_object__for_each_program(prog, obj) {
		enum bpf_prog_type prog_type;
		enum bpf_attach_type attach_type;

		err = libbpf_prog_type_by_name(prog->section_name, &prog_type,
					       &attach_type);
		if (err == -ESRCH)
			/* couldn't guess, but user might manually specify */
			continue;
		if (err)
			goto out;

		bpf_program__set_type(prog, prog_type);
		bpf_program__set_expected_attach_type(prog, attach_type);
	}

	return obj;
out:
	bpf_object__close(obj);
@@ -4463,6 +4480,11 @@ int bpf_program__nth_fd(const struct bpf_program *prog, int n)
	return fd;
}

enum bpf_prog_type bpf_program__get_type(struct bpf_program *prog)
{
	return prog->type;
}

void bpf_program__set_type(struct bpf_program *prog, enum bpf_prog_type type)
{
	prog->type = type;
@@ -4497,6 +4519,12 @@ BPF_PROG_TYPE_FNS(raw_tracepoint, BPF_PROG_TYPE_RAW_TRACEPOINT);
BPF_PROG_TYPE_FNS(xdp, BPF_PROG_TYPE_XDP);
BPF_PROG_TYPE_FNS(perf_event, BPF_PROG_TYPE_PERF_EVENT);

enum bpf_attach_type
bpf_program__get_expected_attach_type(struct bpf_program *prog)
{
	return prog->expected_attach_type;
}

void bpf_program__set_expected_attach_type(struct bpf_program *prog,
					   enum bpf_attach_type type)
{
@@ -4536,11 +4564,15 @@ static const struct {
} section_names[] = {
	BPF_PROG_SEC("socket",			BPF_PROG_TYPE_SOCKET_FILTER),
	BPF_PROG_SEC("kprobe/",			BPF_PROG_TYPE_KPROBE),
	BPF_PROG_SEC("uprobe/",			BPF_PROG_TYPE_KPROBE),
	BPF_PROG_SEC("kretprobe/",		BPF_PROG_TYPE_KPROBE),
	BPF_PROG_SEC("uretprobe/",		BPF_PROG_TYPE_KPROBE),
	BPF_PROG_SEC("classifier",		BPF_PROG_TYPE_SCHED_CLS),
	BPF_PROG_SEC("action",			BPF_PROG_TYPE_SCHED_ACT),
	BPF_PROG_SEC("tracepoint/",		BPF_PROG_TYPE_TRACEPOINT),
	BPF_PROG_SEC("tp/",			BPF_PROG_TYPE_TRACEPOINT),
	BPF_PROG_SEC("raw_tracepoint/",		BPF_PROG_TYPE_RAW_TRACEPOINT),
	BPF_PROG_SEC("raw_tp/",			BPF_PROG_TYPE_RAW_TRACEPOINT),
	BPF_PROG_BTF("tp_btf/",			BPF_PROG_TYPE_RAW_TRACEPOINT),
	BPF_PROG_SEC("xdp",			BPF_PROG_TYPE_XDP),
	BPF_PROG_SEC("perf_event",		BPF_PROG_TYPE_PERF_EVENT),
@@ -4676,7 +4708,7 @@ int libbpf_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type,
		free(type_names);
	}

	return -EINVAL;
	return -ESRCH;
}

int libbpf_attach_type_by_name(const char *name,
@@ -4706,15 +4738,6 @@ int libbpf_attach_type_by_name(const char *name,
	return -EINVAL;
}

static int
bpf_program__identify_section(struct bpf_program *prog,
			      enum bpf_prog_type *prog_type,
			      enum bpf_attach_type *expected_attach_type)
{
	return libbpf_prog_type_by_name(prog->section_name, prog_type,
					expected_attach_type);
}

int bpf_map__fd(const struct bpf_map *map)
{
	return map ? map->fd : -EINVAL;
@@ -4882,8 +4905,6 @@ int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
{
	struct bpf_object_open_attr open_attr = {};
	struct bpf_program *prog, *first_prog = NULL;
	enum bpf_attach_type expected_attach_type;
	enum bpf_prog_type prog_type;
	struct bpf_object *obj;
	struct bpf_map *map;
	int err;
@@ -4901,26 +4922,27 @@ int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
		return -ENOENT;

	bpf_object__for_each_program(prog, obj) {
		enum bpf_attach_type attach_type = attr->expected_attach_type;
		/*
		 * If type is not specified, try to guess it based on
		 * section name.
		 * to preserve backwards compatibility, bpf_prog_load treats
		 * attr->prog_type, if specified, as an override to whatever
		 * bpf_object__open guessed
		 */
		if (attr->prog_type != BPF_PROG_TYPE_UNSPEC) {
			bpf_program__set_type(prog, attr->prog_type);
			bpf_program__set_expected_attach_type(prog,
							      attach_type);
		}
		if (bpf_program__get_type(prog) == BPF_PROG_TYPE_UNSPEC) {
			/*
			 * we haven't guessed from section name and user
			 * didn't provide a fallback type, too bad...
			 */
		prog_type = attr->prog_type;
		prog->prog_ifindex = attr->ifindex;
		expected_attach_type = attr->expected_attach_type;
		if (prog_type == BPF_PROG_TYPE_UNSPEC) {
			err = bpf_program__identify_section(prog, &prog_type,
							    &expected_attach_type);
			if (err < 0) {
			bpf_object__close(obj);
			return -EINVAL;
		}
		}

		bpf_program__set_type(prog, prog_type);
		bpf_program__set_expected_attach_type(prog,
						      expected_attach_type);

		prog->prog_ifindex = attr->ifindex;
		prog->log_level = attr->log_level;
		prog->prog_flags = attr->prog_flags;
		if (!first_prog)
+5 −0
Original line number Diff line number Diff line
@@ -302,8 +302,13 @@ LIBBPF_API int bpf_program__set_sched_cls(struct bpf_program *prog);
LIBBPF_API int bpf_program__set_sched_act(struct bpf_program *prog);
LIBBPF_API int bpf_program__set_xdp(struct bpf_program *prog);
LIBBPF_API int bpf_program__set_perf_event(struct bpf_program *prog);

LIBBPF_API enum bpf_prog_type bpf_program__get_type(struct bpf_program *prog);
LIBBPF_API void bpf_program__set_type(struct bpf_program *prog,
				      enum bpf_prog_type type);

LIBBPF_API enum bpf_attach_type
bpf_program__get_expected_attach_type(struct bpf_program *prog);
LIBBPF_API void
bpf_program__set_expected_attach_type(struct bpf_program *prog,
				      enum bpf_attach_type type);
+2 −0
Original line number Diff line number Diff line
@@ -195,4 +195,6 @@ LIBBPF_0.0.6 {
	global:
		bpf_object__open_file;
		bpf_object__open_mem;
		bpf_program__get_expected_attach_type;
		bpf_program__get_type;
} LIBBPF_0.0.5;
+0 −5
Original line number Diff line number Diff line
@@ -99,11 +99,6 @@ void test_attach_probe(void)
		  "prog '%s' not found\n", uretprobe_name))
		goto cleanup;

	bpf_program__set_kprobe(kprobe_prog);
	bpf_program__set_kprobe(kretprobe_prog);
	bpf_program__set_kprobe(uprobe_prog);
	bpf_program__set_kprobe(uretprobe_prog);

	/* create maps && load programs */
	err = bpf_object__load(obj);
	if (CHECK(err, "obj_load", "err %d\n", err))
Loading