Commit 37081156 authored by Alexei Starovoitov's avatar Alexei Starovoitov
Browse files

Merge branch 'libbpf-minimize-feature-detection'



Andrii Nakryiko says:

====================
Get rid of two feature detectors: reallocarray and libelf-mmap. Optional
feature detections complicate libbpf Makefile and cause more troubles for
various applications that want to integrate libbpf as part of their build.

Patch #1 replaces all reallocarray() uses into libbpf-internal reallocarray()
implementation. Patches #2 and #3 makes sure we won't re-introduce
reallocarray() accidentally. Patch #2 also removes last use of
libbpf_internal.h header inside bpftool. There is still nlattr.h that's used
by both libbpf and bpftool, but that's left for a follow up patch to split.
Patch #4 removed libelf-mmap feature detector and all its uses, as it's
trivial to handle missing mmap support in libbpf, the way objtool has been
doing it for a while.

v1->v2 and v2->v3:
  - rebase to latest bpf-next (Alexei).
====================

Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parents 00b2e953 22dd1ac9
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -19,11 +19,9 @@
#include <sys/mman.h>
#include <bpf/btf.h>

#include "bpf/libbpf_internal.h"
#include "json_writer.h"
#include "main.h"


#define MAX_OBJ_NAME_LEN 64

static void sanitize_identifier(char *name)
+282 −17
Original line number Diff line number Diff line
@@ -6,22 +6,27 @@
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include <net/if.h>
#include <linux/if.h>
#include <linux/rtnetlink.h>
#include <linux/socket.h>
#include <linux/tc_act/tc_bpf.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>

#include "bpf/nlattr.h"
#include "bpf/libbpf_internal.h"
#include "main.h"
#include "netlink_dumper.h"

#ifndef SOL_NETLINK
#define SOL_NETLINK 270
#endif

struct ip_devname_ifindex {
	char	devname[64];
	int	ifindex;
@@ -85,6 +90,266 @@ static enum net_attach_type parse_attach_type(const char *str)
	return net_attach_type_size;
}

typedef int (*dump_nlmsg_t)(void *cookie, void *msg, struct nlattr **tb);

typedef int (*__dump_nlmsg_t)(struct nlmsghdr *nlmsg, dump_nlmsg_t, void *cookie);

static int netlink_open(__u32 *nl_pid)
{
	struct sockaddr_nl sa;
	socklen_t addrlen;
	int one = 1, ret;
	int sock;

	memset(&sa, 0, sizeof(sa));
	sa.nl_family = AF_NETLINK;

	sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
	if (sock < 0)
		return -errno;

	if (setsockopt(sock, SOL_NETLINK, NETLINK_EXT_ACK,
		       &one, sizeof(one)) < 0) {
		p_err("Netlink error reporting not supported");
	}

	if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
		ret = -errno;
		goto cleanup;
	}

	addrlen = sizeof(sa);
	if (getsockname(sock, (struct sockaddr *)&sa, &addrlen) < 0) {
		ret = -errno;
		goto cleanup;
	}

	if (addrlen != sizeof(sa)) {
		ret = -LIBBPF_ERRNO__INTERNAL;
		goto cleanup;
	}

	*nl_pid = sa.nl_pid;
	return sock;

cleanup:
	close(sock);
	return ret;
}

static int netlink_recv(int sock, __u32 nl_pid, __u32 seq,
			    __dump_nlmsg_t _fn, dump_nlmsg_t fn,
			    void *cookie)
{
	bool multipart = true;
	struct nlmsgerr *err;
	struct nlmsghdr *nh;
	char buf[4096];
	int len, ret;

	while (multipart) {
		multipart = false;
		len = recv(sock, buf, sizeof(buf), 0);
		if (len < 0) {
			ret = -errno;
			goto done;
		}

		if (len == 0)
			break;

		for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len);
		     nh = NLMSG_NEXT(nh, len)) {
			if (nh->nlmsg_pid != nl_pid) {
				ret = -LIBBPF_ERRNO__WRNGPID;
				goto done;
			}
			if (nh->nlmsg_seq != seq) {
				ret = -LIBBPF_ERRNO__INVSEQ;
				goto done;
			}
			if (nh->nlmsg_flags & NLM_F_MULTI)
				multipart = true;
			switch (nh->nlmsg_type) {
			case NLMSG_ERROR:
				err = (struct nlmsgerr *)NLMSG_DATA(nh);
				if (!err->error)
					continue;
				ret = err->error;
				libbpf_nla_dump_errormsg(nh);
				goto done;
			case NLMSG_DONE:
				return 0;
			default:
				break;
			}
			if (_fn) {
				ret = _fn(nh, fn, cookie);
				if (ret)
					return ret;
			}
		}
	}
	ret = 0;
done:
	return ret;
}

static int __dump_class_nlmsg(struct nlmsghdr *nlh,
			      dump_nlmsg_t dump_class_nlmsg,
			      void *cookie)
{
	struct nlattr *tb[TCA_MAX + 1], *attr;
	struct tcmsg *t = NLMSG_DATA(nlh);
	int len;

	len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t));
	attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t)));
	if (libbpf_nla_parse(tb, TCA_MAX, attr, len, NULL) != 0)
		return -LIBBPF_ERRNO__NLPARSE;

	return dump_class_nlmsg(cookie, t, tb);
}

static int netlink_get_class(int sock, unsigned int nl_pid, int ifindex,
			     dump_nlmsg_t dump_class_nlmsg, void *cookie)
{
	struct {
		struct nlmsghdr nlh;
		struct tcmsg t;
	} req = {
		.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)),
		.nlh.nlmsg_type = RTM_GETTCLASS,
		.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
		.t.tcm_family = AF_UNSPEC,
		.t.tcm_ifindex = ifindex,
	};
	int seq = time(NULL);

	req.nlh.nlmsg_seq = seq;
	if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0)
		return -errno;

	return netlink_recv(sock, nl_pid, seq, __dump_class_nlmsg,
			    dump_class_nlmsg, cookie);
}

static int __dump_qdisc_nlmsg(struct nlmsghdr *nlh,
			      dump_nlmsg_t dump_qdisc_nlmsg,
			      void *cookie)
{
	struct nlattr *tb[TCA_MAX + 1], *attr;
	struct tcmsg *t = NLMSG_DATA(nlh);
	int len;

	len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t));
	attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t)));
	if (libbpf_nla_parse(tb, TCA_MAX, attr, len, NULL) != 0)
		return -LIBBPF_ERRNO__NLPARSE;

	return dump_qdisc_nlmsg(cookie, t, tb);
}

static int netlink_get_qdisc(int sock, unsigned int nl_pid, int ifindex,
			     dump_nlmsg_t dump_qdisc_nlmsg, void *cookie)
{
	struct {
		struct nlmsghdr nlh;
		struct tcmsg t;
	} req = {
		.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)),
		.nlh.nlmsg_type = RTM_GETQDISC,
		.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
		.t.tcm_family = AF_UNSPEC,
		.t.tcm_ifindex = ifindex,
	};
	int seq = time(NULL);

	req.nlh.nlmsg_seq = seq;
	if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0)
		return -errno;

	return netlink_recv(sock, nl_pid, seq, __dump_qdisc_nlmsg,
			    dump_qdisc_nlmsg, cookie);
}

static int __dump_filter_nlmsg(struct nlmsghdr *nlh,
			       dump_nlmsg_t dump_filter_nlmsg,
			       void *cookie)
{
	struct nlattr *tb[TCA_MAX + 1], *attr;
	struct tcmsg *t = NLMSG_DATA(nlh);
	int len;

	len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t));
	attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t)));
	if (libbpf_nla_parse(tb, TCA_MAX, attr, len, NULL) != 0)
		return -LIBBPF_ERRNO__NLPARSE;

	return dump_filter_nlmsg(cookie, t, tb);
}

static int netlink_get_filter(int sock, unsigned int nl_pid, int ifindex, int handle,
			      dump_nlmsg_t dump_filter_nlmsg, void *cookie)
{
	struct {
		struct nlmsghdr nlh;
		struct tcmsg t;
	} req = {
		.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)),
		.nlh.nlmsg_type = RTM_GETTFILTER,
		.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
		.t.tcm_family = AF_UNSPEC,
		.t.tcm_ifindex = ifindex,
		.t.tcm_parent = handle,
	};
	int seq = time(NULL);

	req.nlh.nlmsg_seq = seq;
	if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0)
		return -errno;

	return netlink_recv(sock, nl_pid, seq, __dump_filter_nlmsg,
			    dump_filter_nlmsg, cookie);
}

static int __dump_link_nlmsg(struct nlmsghdr *nlh,
			     dump_nlmsg_t dump_link_nlmsg, void *cookie)
{
	struct nlattr *tb[IFLA_MAX + 1], *attr;
	struct ifinfomsg *ifi = NLMSG_DATA(nlh);
	int len;

	len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
	attr = (struct nlattr *) ((void *) ifi + NLMSG_ALIGN(sizeof(*ifi)));
	if (libbpf_nla_parse(tb, IFLA_MAX, attr, len, NULL) != 0)
		return -LIBBPF_ERRNO__NLPARSE;

	return dump_link_nlmsg(cookie, ifi, tb);
}

static int netlink_get_link(int sock, unsigned int nl_pid,
			    dump_nlmsg_t dump_link_nlmsg, void *cookie)
{
	struct {
		struct nlmsghdr nlh;
		struct ifinfomsg ifm;
	} req = {
		.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
		.nlh.nlmsg_type = RTM_GETLINK,
		.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
		.ifm.ifi_family = AF_PACKET,
	};
	int seq = time(NULL);

	req.nlh.nlmsg_seq = seq;
	if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0)
		return -errno;

	return netlink_recv(sock, nl_pid, seq, __dump_link_nlmsg,
			    dump_link_nlmsg, cookie);
}

static int dump_link_nlmsg(void *cookie, void *msg, struct nlattr **tb)
{
	struct bpf_netdev_t *netinfo = cookie;
@@ -168,13 +433,13 @@ static int show_dev_tc_bpf(int sock, unsigned int nl_pid,
	tcinfo.array_len = 0;

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

	tcinfo.is_qdisc = true;
	ret = libbpf_nl_get_qdisc(sock, nl_pid, dev->ifindex,
	ret = netlink_get_qdisc(sock, nl_pid, dev->ifindex,
				dump_class_qdisc_nlmsg, &tcinfo);
	if (ret)
		goto out;
@@ -183,7 +448,7 @@ 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 = libbpf_nl_get_filter(sock, nl_pid, dev->ifindex,
		ret = netlink_get_filter(sock, nl_pid, dev->ifindex,
					 tcinfo.handle_array[i].handle,
					 dump_filter_nlmsg, &filter_info);
		if (ret)
@@ -193,21 +458,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 = libbpf_nl_get_filter(sock, nl_pid, dev->ifindex, handle,
	ret = netlink_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 = libbpf_nl_get_filter(sock, nl_pid, dev->ifindex, handle,
	ret = netlink_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 = libbpf_nl_get_filter(sock, nl_pid, dev->ifindex, handle,
	ret = netlink_get_filter(sock, nl_pid, dev->ifindex, handle,
				 dump_filter_nlmsg, &filter_info);
	if (ret)
		goto out;
@@ -386,7 +651,7 @@ static int do_show(int argc, char **argv)
	struct bpf_attach_info attach_info = {};
	int i, sock, ret, filter_idx = -1;
	struct bpf_netdev_t dev_array;
	unsigned int nl_pid;
	unsigned int nl_pid = 0;
	char err_buf[256];

	if (argc == 2) {
@@ -401,7 +666,7 @@ static int do_show(int argc, char **argv)
	if (ret)
		return -1;

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

	if (!ret) {
+0 −1
Original line number Diff line number Diff line
@@ -46,7 +46,6 @@ FEATURE_TESTS_BASIC := \
        libelf-getphdrnum               \
        libelf-gelf_getnote             \
        libelf-getshdrstrndx            \
        libelf-mmap                     \
        libnuma                         \
        numa_num_possible_cpus          \
        libperl                         \
+0 −4
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ FILES= \
         test-libelf-getphdrnum.bin             \
         test-libelf-gelf_getnote.bin           \
         test-libelf-getshdrstrndx.bin          \
         test-libelf-mmap.bin                   \
         test-libdebuginfod.bin                 \
         test-libnuma.bin                       \
         test-numa_num_possible_cpus.bin        \
@@ -146,9 +145,6 @@ $(OUTPUT)test-dwarf.bin:
$(OUTPUT)test-dwarf_getlocations.bin:
	$(BUILD) $(DWARFLIBS)

$(OUTPUT)test-libelf-mmap.bin:
	$(BUILD) -lelf

$(OUTPUT)test-libelf-getphdrnum.bin:
	$(BUILD) -lelf

+0 −4
Original line number Diff line number Diff line
@@ -30,10 +30,6 @@
# include "test-libelf.c"
#undef main

#define main main_test_libelf_mmap
# include "test-libelf-mmap.c"
#undef main

#define main main_test_get_current_dir_name
# include "test-get_current_dir_name.c"
#undef main
Loading