Commit fc1dc766 authored by Daniel Borkmann's avatar Daniel Borkmann
Browse files

Merge branch 'bpf-libbpf-consistent-iface'



Andrey Ignatov says:

====================
This patch set renames a few interfaces in libbpf, mostly netlink related,
so that all symbols provided by the library have only three possible
prefixes:

% nm -D tools/lib/bpf/libbpf.so  | \
    awk '$2 == "T" {sub(/[_\(].*/, "", $3); if ($3) print $3}' | \
    sort | \
    uniq -c
     91 bpf
      8 btf
     14 libbpf

libbpf is used more and more outside kernel tree. That means the library
should follow good practices in library design and implementation to
play well with third party code that uses it.

One of such practices is to have a common prefix (or a few) for every
interface, function or data structure, library provides. It helps to
avoid name conflicts with other libraries and keeps API/ABI consistent.

Inconsistent names in libbpf already cause problems in real life. E.g.
an application can't use both libbpf and libnl due to conflicting
symbols (specifically nla_parse, nla_parse_nested and a few others).

Some of problematic global symbols are not part of ABI and can be
restricted from export with either visibility attribute/pragma or export
map (what is useful by itself and can be done in addition). That won't
solve the problem for those that are part of ABI though. Also export
restrictions would help only in DSO case. If third party application links
libbpf statically it won't help, and people do it (e.g. Facebook links
most of libraries statically, including libbpf).

libbpf already uses the following prefixes for its interfaces:
* bpf_ for bpf system call wrappers, program/map/elf-object
  abstractions and a few other things;
* btf_ for BTF related API;
* libbpf_ for everything else.

The patch adds libbpf_ prefix to interfaces that use none of mentioned
above prefixes and don't fit well into the first two categories.

Long term benefits of having common prefix should outweigh possible
inconvenience of changing API for those functions now.

Patches 2-4 add libbpf_ prefix to libbpf interfaces: separate patch per
header. Other patches are simple improvements in API.
====================

Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parents d71019b5 e5b0863c
Loading
Loading
Loading
Loading
+22 −19
Original line number Diff line number Diff line
@@ -69,7 +69,9 @@ static int dump_link_nlmsg(void *cookie, void *msg, struct nlattr **tb)
	snprintf(netinfo->devices[netinfo->used_len].devname,
		 sizeof(netinfo->devices[netinfo->used_len].devname),
		 "%s",
		 tb[IFLA_IFNAME] ? nla_getattr_str(tb[IFLA_IFNAME]) : "");
		 tb[IFLA_IFNAME]
			 ? libbpf_nla_getattr_str(tb[IFLA_IFNAME])
			 : "");
	netinfo->used_len++;

	return do_xdp_dump(ifinfo, tb);
@@ -83,7 +85,7 @@ static int dump_class_qdisc_nlmsg(void *cookie, void *msg, struct nlattr **tb)
	if (tcinfo->is_qdisc) {
		/* skip clsact qdisc */
		if (tb[TCA_KIND] &&
		    strcmp(nla_data(tb[TCA_KIND]), "clsact") == 0)
		    strcmp(libbpf_nla_data(tb[TCA_KIND]), "clsact") == 0)
			return 0;
		if (info->tcm_handle == 0)
			return 0;
@@ -101,7 +103,9 @@ static int dump_class_qdisc_nlmsg(void *cookie, void *msg, struct nlattr **tb)
	snprintf(tcinfo->handle_array[tcinfo->used_len].kind,
		 sizeof(tcinfo->handle_array[tcinfo->used_len].kind),
		 "%s",
		 tb[TCA_KIND] ? nla_getattr_str(tb[TCA_KIND]) : "unknown");
		 tb[TCA_KIND]
			 ? libbpf_nla_getattr_str(tb[TCA_KIND])
			 : "unknown");
	tcinfo->used_len++;

	return 0;
@@ -127,14 +131,14 @@ static int show_dev_tc_bpf(int sock, unsigned int nl_pid,
	tcinfo.array_len = 0;

	tcinfo.is_qdisc = false;
	ret = nl_get_class(sock, nl_pid, dev->ifindex, dump_class_qdisc_nlmsg,
			   &tcinfo);
	ret = libbpf_nl_get_class(sock, nl_pid, dev->ifindex,
				  dump_class_qdisc_nlmsg, &tcinfo);
	if (ret)
		goto out;

	tcinfo.is_qdisc = true;
	ret = nl_get_qdisc(sock, nl_pid, dev->ifindex, dump_class_qdisc_nlmsg,
			   &tcinfo);
	ret = libbpf_nl_get_qdisc(sock, nl_pid, dev->ifindex,
				  dump_class_qdisc_nlmsg, &tcinfo);
	if (ret)
		goto out;

@@ -142,10 +146,9 @@ static int show_dev_tc_bpf(int sock, unsigned int nl_pid,
	filter_info.ifindex = dev->ifindex;
	for (i = 0; i < tcinfo.used_len; i++) {
		filter_info.kind = tcinfo.handle_array[i].kind;
		ret = nl_get_filter(sock, nl_pid, dev->ifindex,
		ret = libbpf_nl_get_filter(sock, nl_pid, dev->ifindex,
					   tcinfo.handle_array[i].handle,
				    dump_filter_nlmsg,
				    &filter_info);
					   dump_filter_nlmsg, &filter_info);
		if (ret)
			goto out;
	}
@@ -153,21 +156,21 @@ static int show_dev_tc_bpf(int sock, unsigned int nl_pid,
	/* root, ingress and egress handle */
	handle = TC_H_ROOT;
	filter_info.kind = "root";
	ret = nl_get_filter(sock, nl_pid, dev->ifindex, handle,
	ret = libbpf_nl_get_filter(sock, nl_pid, dev->ifindex, handle,
				   dump_filter_nlmsg, &filter_info);
	if (ret)
		goto out;

	handle = TC_H_MAKE(TC_H_CLSACT, TC_H_MIN_INGRESS);
	filter_info.kind = "clsact/ingress";
	ret = nl_get_filter(sock, nl_pid, dev->ifindex, handle,
	ret = libbpf_nl_get_filter(sock, nl_pid, dev->ifindex, handle,
				   dump_filter_nlmsg, &filter_info);
	if (ret)
		goto out;

	handle = TC_H_MAKE(TC_H_CLSACT, TC_H_MIN_EGRESS);
	filter_info.kind = "clsact/egress";
	ret = nl_get_filter(sock, nl_pid, dev->ifindex, handle,
	ret = libbpf_nl_get_filter(sock, nl_pid, dev->ifindex, handle,
				   dump_filter_nlmsg, &filter_info);
	if (ret)
		goto out;
@@ -196,7 +199,7 @@ static int do_show(int argc, char **argv)
		usage();
	}

	sock = bpf_netlink_open(&nl_pid);
	sock = libbpf_netlink_open(&nl_pid);
	if (sock < 0) {
		fprintf(stderr, "failed to open netlink sock\n");
		return -1;
@@ -211,7 +214,7 @@ static int do_show(int argc, char **argv)
		jsonw_start_array(json_wtr);
	NET_START_OBJECT;
	NET_START_ARRAY("xdp", "%s:\n");
	ret = nl_get_link(sock, nl_pid, dump_link_nlmsg, &dev_array);
	ret = libbpf_nl_get_link(sock, nl_pid, dump_link_nlmsg, &dev_array);
	NET_END_ARRAY("\n");

	if (!ret) {
+18 −14
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ static void xdp_dump_prog_id(struct nlattr **tb, int attr,
	if (new_json_object)
		NET_START_OBJECT
	NET_DUMP_STR("mode", " %s", mode);
	NET_DUMP_UINT("id", " id %u", nla_getattr_u32(tb[attr]))
	NET_DUMP_UINT("id", " id %u", libbpf_nla_getattr_u32(tb[attr]))
	if (new_json_object)
		NET_END_OBJECT
}
@@ -32,13 +32,13 @@ static int do_xdp_dump_one(struct nlattr *attr, unsigned int ifindex,
	struct nlattr *tb[IFLA_XDP_MAX + 1];
	unsigned char mode;

	if (nla_parse_nested(tb, IFLA_XDP_MAX, attr, NULL) < 0)
	if (libbpf_nla_parse_nested(tb, IFLA_XDP_MAX, attr, NULL) < 0)
		return -1;

	if (!tb[IFLA_XDP_ATTACHED])
		return 0;

	mode = nla_getattr_u8(tb[IFLA_XDP_ATTACHED]);
	mode = libbpf_nla_getattr_u8(tb[IFLA_XDP_ATTACHED]);
	if (mode == XDP_ATTACHED_NONE)
		return 0;

@@ -75,14 +75,14 @@ int do_xdp_dump(struct ifinfomsg *ifinfo, struct nlattr **tb)
		return 0;

	return do_xdp_dump_one(tb[IFLA_XDP], ifinfo->ifi_index,
			       nla_getattr_str(tb[IFLA_IFNAME]));
			       libbpf_nla_getattr_str(tb[IFLA_IFNAME]));
}

static int do_bpf_dump_one_act(struct nlattr *attr)
{
	struct nlattr *tb[TCA_ACT_BPF_MAX + 1];

	if (nla_parse_nested(tb, TCA_ACT_BPF_MAX, attr, NULL) < 0)
	if (libbpf_nla_parse_nested(tb, TCA_ACT_BPF_MAX, attr, NULL) < 0)
		return -LIBBPF_ERRNO__NLPARSE;

	if (!tb[TCA_ACT_BPF_PARMS])
@@ -91,10 +91,10 @@ static int do_bpf_dump_one_act(struct nlattr *attr)
	NET_START_OBJECT_NESTED2;
	if (tb[TCA_ACT_BPF_NAME])
		NET_DUMP_STR("name", "%s",
			     nla_getattr_str(tb[TCA_ACT_BPF_NAME]));
			     libbpf_nla_getattr_str(tb[TCA_ACT_BPF_NAME]));
	if (tb[TCA_ACT_BPF_ID])
		NET_DUMP_UINT("id", " id %u",
			      nla_getattr_u32(tb[TCA_ACT_BPF_ID]));
			      libbpf_nla_getattr_u32(tb[TCA_ACT_BPF_ID]));
	NET_END_OBJECT_NESTED;
	return 0;
}
@@ -106,10 +106,11 @@ static int do_dump_one_act(struct nlattr *attr)
	if (!attr)
		return 0;

	if (nla_parse_nested(tb, TCA_ACT_MAX, attr, NULL) < 0)
	if (libbpf_nla_parse_nested(tb, TCA_ACT_MAX, attr, NULL) < 0)
		return -LIBBPF_ERRNO__NLPARSE;

	if (tb[TCA_ACT_KIND] && strcmp(nla_data(tb[TCA_ACT_KIND]), "bpf") == 0)
	if (tb[TCA_ACT_KIND] &&
	    strcmp(libbpf_nla_data(tb[TCA_ACT_KIND]), "bpf") == 0)
		return do_bpf_dump_one_act(tb[TCA_ACT_OPTIONS]);

	return 0;
@@ -120,7 +121,7 @@ static int do_bpf_act_dump(struct nlattr *attr)
	struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
	int act, ret;

	if (nla_parse_nested(tb, TCA_ACT_MAX_PRIO, attr, NULL) < 0)
	if (libbpf_nla_parse_nested(tb, TCA_ACT_MAX_PRIO, attr, NULL) < 0)
		return -LIBBPF_ERRNO__NLPARSE;

	NET_START_ARRAY("act", " %s [");
@@ -139,13 +140,15 @@ static int do_bpf_filter_dump(struct nlattr *attr)
	struct nlattr *tb[TCA_BPF_MAX + 1];
	int ret;

	if (nla_parse_nested(tb, TCA_BPF_MAX, attr, NULL) < 0)
	if (libbpf_nla_parse_nested(tb, TCA_BPF_MAX, attr, NULL) < 0)
		return -LIBBPF_ERRNO__NLPARSE;

	if (tb[TCA_BPF_NAME])
		NET_DUMP_STR("name", " %s", nla_getattr_str(tb[TCA_BPF_NAME]));
		NET_DUMP_STR("name", " %s",
			     libbpf_nla_getattr_str(tb[TCA_BPF_NAME]));
	if (tb[TCA_BPF_ID])
		NET_DUMP_UINT("id", " id %u", nla_getattr_u32(tb[TCA_BPF_ID]));
		NET_DUMP_UINT("id", " id %u",
			      libbpf_nla_getattr_u32(tb[TCA_BPF_ID]));
	if (tb[TCA_BPF_ACT]) {
		ret = do_bpf_act_dump(tb[TCA_BPF_ACT]);
		if (ret)
@@ -160,7 +163,8 @@ int do_filter_dump(struct tcmsg *info, struct nlattr **tb, const char *kind,
{
	int ret = 0;

	if (tb[TCA_OPTIONS] && strcmp(nla_data(tb[TCA_KIND]), "bpf") == 0) {
	if (tb[TCA_OPTIONS] &&
	    strcmp(libbpf_nla_data(tb[TCA_KIND]), "bpf") == 0) {
		NET_START_OBJECT;
		if (devname[0] != '\0')
			NET_DUMP_STR("devname", "%s", devname);
+3 −3
Original line number Diff line number Diff line
@@ -20,8 +20,8 @@
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not,  see <http://www.gnu.org/licenses>
 */
#ifndef __BPF_BPF_H
#define __BPF_BPF_H
#ifndef __LIBBPF_BPF_H
#define __LIBBPF_BPF_H

#include <linux/bpf.h>
#include <stdbool.h>
@@ -111,4 +111,4 @@ int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size,
int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len,
		      __u32 *prog_id, __u32 *fd_type, __u64 *probe_offset,
		      __u64 *probe_addr);
#endif
#endif /* __LIBBPF_BPF_H */
+3 −3
Original line number Diff line number Diff line
/* SPDX-License-Identifier: LGPL-2.1 */
/* Copyright (c) 2018 Facebook */

#ifndef __BPF_BTF_H
#define __BPF_BTF_H
#ifndef __LIBBPF_BTF_H
#define __LIBBPF_BTF_H

#include <linux/types.h>

@@ -23,4 +23,4 @@ int btf__resolve_type(const struct btf *btf, __u32 type_id);
int btf__fd(const struct btf *btf);
const char *btf__name_by_offset(const struct btf *btf, __u32 offset);

#endif
#endif /* __LIBBPF_BTF_H */
+12 −10
Original line number Diff line number Diff line
@@ -470,7 +470,8 @@ static int bpf_object__elf_init(struct bpf_object *obj)
		obj->efile.fd = open(obj->path, O_RDONLY);
		if (obj->efile.fd < 0) {
			char errmsg[STRERR_BUFSIZE];
			char *cp = str_error(errno, errmsg, sizeof(errmsg));
			char *cp = libbpf_strerror_r(errno, errmsg,
						     sizeof(errmsg));

			pr_warning("failed to open %s: %s\n", obj->path, cp);
			return -errno;
@@ -811,7 +812,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
						      data->d_size, name, idx);
			if (err) {
				char errmsg[STRERR_BUFSIZE];
				char *cp = str_error(-err, errmsg, sizeof(errmsg));
				char *cp = libbpf_strerror_r(-err, errmsg,
							     sizeof(errmsg));

				pr_warning("failed to alloc program %s (%s): %s",
					   name, obj->path, cp);
@@ -1140,7 +1142,7 @@ bpf_object__create_maps(struct bpf_object *obj)

		*pfd = bpf_create_map_xattr(&create_attr);
		if (*pfd < 0 && create_attr.btf_key_type_id) {
			cp = str_error(errno, errmsg, sizeof(errmsg));
			cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg));
			pr_warning("Error in bpf_create_map_xattr(%s):%s(%d). Retrying without BTF.\n",
				   map->name, cp, errno);
			create_attr.btf_fd = 0;
@@ -1155,7 +1157,7 @@ bpf_object__create_maps(struct bpf_object *obj)
			size_t j;

			err = *pfd;
			cp = str_error(errno, errmsg, sizeof(errmsg));
			cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg));
			pr_warning("failed to create map (name: '%s'): %s\n",
				   map->name, cp);
			for (j = 0; j < i; j++)
@@ -1339,7 +1341,7 @@ load_program(enum bpf_prog_type type, enum bpf_attach_type expected_attach_type,
	}

	ret = -LIBBPF_ERRNO__LOAD;
	cp = str_error(errno, errmsg, sizeof(errmsg));
	cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg));
	pr_warning("load bpf program failed: %s\n", cp);

	if (log_buf && log_buf[0] != '\0') {
@@ -1377,7 +1379,7 @@ out:

int
bpf_program__load(struct bpf_program *prog,
		  char *license, u32 kern_version)
		  char *license, __u32 kern_version)
{
	int err = 0, fd, i;

@@ -1655,7 +1657,7 @@ static int check_path(const char *path)

	dir = dirname(dname);
	if (statfs(dir, &st_fs)) {
		cp = str_error(errno, errmsg, sizeof(errmsg));
		cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg));
		pr_warning("failed to statfs %s: %s\n", dir, cp);
		err = -errno;
	}
@@ -1691,7 +1693,7 @@ int bpf_program__pin_instance(struct bpf_program *prog, const char *path,
	}

	if (bpf_obj_pin(prog->instances.fds[instance], path)) {
		cp = str_error(errno, errmsg, sizeof(errmsg));
		cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg));
		pr_warning("failed to pin program: %s\n", cp);
		return -errno;
	}
@@ -1709,7 +1711,7 @@ static int make_dir(const char *path)
		err = -errno;

	if (err) {
		cp = str_error(-err, errmsg, sizeof(errmsg));
		cp = libbpf_strerror_r(-err, errmsg, sizeof(errmsg));
		pr_warning("failed to mkdir %s: %s\n", path, cp);
	}
	return err;
@@ -1771,7 +1773,7 @@ int bpf_map__pin(struct bpf_map *map, const char *path)
	}

	if (bpf_obj_pin(map->fd, path)) {
		cp = str_error(errno, errmsg, sizeof(errmsg));
		cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg));
		pr_warning("failed to pin map: %s\n", cp);
		return -errno;
	}
Loading