--- /dev/null
+#
+# Copyright (C) 2020 Tony Ambardar <itugrok@yahoo.com>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bpftools
+PKG_VERSION:=5.8.3
+PKG_RELEASE:=1
+
+PKG_SOURCE:=linux-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@KERNEL/linux/kernel/v5.x
+PKG_HASH:=8ea27e1ed38981f772cc6d5f16ab8dbb8052c3800ba0494bd798fbb95dcc1779
+
+PKG_MAINTAINER:=Tony Ambardar <itugrok@yahoo.com>
+
+PKG_USE_MIPS16:=0
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+LINUX_VERSION:=$(PKG_VERSION)
+LINUX_TLD:=linux-$(LINUX_VERSION)
+
+BPF_FILES:= \
+ kernel/bpf scripts tools/Makefile tools/bpf tools/perf/perf-sys.h \
+ tools/arch tools/build tools/include tools/lib tools/scripts
+TAR_OPTIONS+= \
+ --transform="s;$(LINUX_TLD)/;$(PKG_NAME)-$(PKG_VERSION)/;" \
+ $(addprefix $(LINUX_TLD)/,$(BPF_FILES))
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/bpftool/Default
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=bpftool - eBPF subsystem utility
+ LICENSE:=GPL-2.0-only OR BSD-2-Clause
+ URL:=http://www.kernel.org
+ DEPENDS:=+libelf
+endef
+
+define Package/bpftool-minimal
+ $(call Package/bpftool/Default)
+ TITLE+= (Minimal)
+ VARIANT:=minimal
+ DEFAULT_VARIANT:=1
+ PROVIDES:=bpftool
+ ALTERNATIVES:=200:/usr/sbin/bpftool:/usr/libexec/bpftool-minimal
+endef
+
+define Package/bpftool-full
+ $(call Package/bpftool/Default)
+ TITLE+= (Full)
+ VARIANT:=full
+ PROVIDES:=bpftool
+ ALTERNATIVES:=300:/usr/sbin/bpftool:/usr/libexec/bpftool-full
+ DEPENDS+= +libbfd +libopcodes
+endef
+
+define Package/bpftool-minimal/description
+ A tool for inspection and simple manipulation of eBPF programs and maps.
+endef
+
+define Package/bpftool-full/description
+ A tool for inspection and simple manipulation of eBPF programs and maps.
+ This full version uses libbfd and libopcodes to support disassembly of
+ eBPF programs and jited code.
+endef
+
+define Package/libbpf
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=libbpf - eBPF helper library
+ VARIANT:=lib
+ LICENSE:=LGPL-2.1 OR BSD-2-Clause
+ ABI_VERSION:=0
+ URL:=http://www.kernel.org
+ DEPENDS:=+libelf
+endef
+
+define Package/libbpf/description
+ libbpf is a library for loading eBPF programs and reading and manipulating eBPF objects from user-space.
+endef
+
+
+# LTO not compatible with DSO using PIC
+ifneq ($(BUILD_VARIANT),lib)
+ TARGET_CFLAGS += -ffunction-sections -fdata-sections -flto
+ TARGET_LDFLAGS += -Wl,--gc-sections
+endif
+
+MAKE_FLAGS += \
+ EXTRA_CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \
+ LDFLAGS="$(TARGET_LDFLAGS)" \
+ BPFTOOL_VERSION="$(LINUX_VERSION)" \
+ FEATURES_DUMP="$(PKG_BUILD_DIR)/FEATURE-DUMP.openwrt" \
+ OUTPUT="$(PKG_BUILD_DIR)/" \
+ prefix="/usr" \
+ $(if $(findstring c,$(OPENWRT_VERBOSE)),V=1,V='')
+
+ifeq ($(BUILD_VARIANT),full)
+ HAVE_LIBBFD:=1
+ HAVE_LIBCAP:=0
+ HAVE_CLANG:=0
+ MAKE_PATH:=tools/bpf/bpftool
+else ifeq ($(BUILD_VARIANT),minimal)
+ HAVE_LIBBFD:=0
+ HAVE_LIBCAP:=0
+ HAVE_CLANG:=0
+ MAKE_PATH:=tools/bpf/bpftool
+else ifeq ($(BUILD_VARIANT),lib)
+ HAVE_LIBBFD:=0
+ HAVE_LIBCAP:=0
+ HAVE_CLANG:=0
+ MAKE_PATH:=tools/lib/bpf
+endif
+
+# Perform a "throw-away" make to create a FEATURE-DUMP.* file to edit later.
+# The "//" in the make target is actually needed, very unPOSIXly.
+define Build/Configure
+ +$(MAKE_VARS) $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/tools/bpf/bpftool \
+ $(MAKE_FLAGS) FEATURES_DUMP= $(PKG_BUILD_DIR)//libbpf/libbpf.a
+ (cd $(PKG_BUILD_DIR); cat FEATURE-DUMP.bpftool libbpf/FEATURE-DUMP.libbpf \
+ | sort | uniq > FEATURE-DUMP.openwrt)
+ $(SED) 's/feature-libbfd=[01]/feature-libbfd=$(HAVE_LIBBFD)/' \
+ -e 's/feature-libcap=[01]/feature-libcap=$(HAVE_LIBCAP)/' \
+ -e 's/feature-clang-bpf-global-var=[01]/feature-clang-bpf-global-var=$(HAVE_CLANG)/' \
+ $(PKG_BUILD_DIR)/FEATURE-DUMP.openwrt
+endef
+
+define Build/InstallDev/libbpf
+ $(INSTALL_DIR) $(1)/usr/include/bpf
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/bpf/*.h $(1)/usr/include/bpf/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib$(LIB_SUFFIX)/libbpf.{a,so*} \
+ $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib$(LIB_SUFFIX)/pkgconfig/libbpf.pc \
+ $(1)/usr/lib/pkgconfig/
+endef
+
+ifeq ($(BUILD_VARIANT),lib)
+ Build/InstallDev=$(Build/InstallDev/libbpf)
+endif
+
+define Package/bpftool-$(BUILD_VARIANT)/install
+ $(INSTALL_DIR) $(1)/usr/libexec
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/bpftool \
+ $(1)/usr/libexec/bpftool-$(BUILD_VARIANT)
+endef
+
+define Package/libbpf/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib$(LIB_SUFFIX)/libbpf.so.* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,bpftool-full))
+$(eval $(call BuildPackage,bpftool-minimal))
+$(eval $(call BuildPackage,libbpf))
--- /dev/null
+From fafb2e7eaec6d33ce16e28f481edf781219d5d27 Mon Sep 17 00:00:00 2001
+From: Tony Ambardar <Tony.Ambardar@gmail.com>
+Date: Fri, 24 Jul 2020 23:58:17 -0700
+Subject: [PATCH] tools/libbpf: ensure no local symbols counted in ABI check
+
+This avoids finding versioned local symbols such as _init and _fini in
+the libbpf.so file.
+
+Signed-off-by: Tony Ambardar <Tony.Ambardar@gmail.com>
+---
+ tools/lib/bpf/Makefile | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
+index bf8ed134cb8a..c820b0be9d63 100644
+--- a/tools/lib/bpf/Makefile
++++ b/tools/lib/bpf/Makefile
+@@ -152,6 +152,7 @@ GLOBAL_SYM_COUNT = $(shell readelf -s --wide $(BPF_IN_SHARED) | \
+ awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {print $$NF}' | \
+ sort -u | wc -l)
+ VERSIONED_SYM_COUNT = $(shell readelf --dyn-syms --wide $(OUTPUT)libbpf.so | \
++ awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {print $$NF}' | \
+ grep -Eo '[^ ]+@LIBBPF_' | cut -d@ -f1 | sort -u | wc -l)
+
+ CMD_TARGETS = $(LIB_TARGET) $(PC_FILE)
+@@ -219,6 +220,7 @@ check_abi: $(OUTPUT)libbpf.so
+ awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {print $$NF}'| \
+ sort -u > $(OUTPUT)libbpf_global_syms.tmp; \
+ readelf --dyn-syms --wide $(OUTPUT)libbpf.so | \
++ awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {print $$NF}'| \
+ grep -Eo '[^ ]+@LIBBPF_' | cut -d@ -f1 | \
+ sort -u > $(OUTPUT)libbpf_versioned_syms.tmp; \
+ diff -u $(OUTPUT)libbpf_global_syms.tmp \
+--
+2.25.1
+
--- /dev/null
+From 74d0dcf7608b1bab116e297468ac51b57eb97ce0 Mon Sep 17 00:00:00 2001
+From: Tony Ambardar <Tony.Ambardar@gmail.com>
+Date: Thu, 20 Aug 2020 10:06:24 -0700
+Subject: [PATCH] libbpf: fix build failure from uninitialized variable warning
+
+While compiling libbpf, some GCC versions (at least 8.4.0) have difficulty
+determining control flow and a emit warning for potentially uninitialized
+usage of 'map', which results in a build error if using "-Werror":
+
+In file included from libbpf.c:56:
+libbpf.c: In function '__bpf_object__open':
+libbpf_internal.h:59:2: warning: 'map' may be used uninitialized in this function [-Wmaybe-uninitialized]
+ libbpf_print(level, "libbpf: " fmt, ##__VA_ARGS__); \
+ ^~~~~~~~~~~~
+libbpf.c:5032:18: note: 'map' was declared here
+ struct bpf_map *map, *targ_map;
+ ^~~
+
+The warning/error is false based on code inspection, so silence it with a
+NULL initialization.
+
+Fixes: 646f02ffdd49 ("libbpf: Add BTF-defined map-in-map support")
+Ref: 063e68813391 ("libbpf: Fix false uninitialized variable warning")
+
+Signed-off-by: Tony Ambardar <Tony.Ambardar@gmail.com>
+---
+ tools/lib/bpf/libbpf.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
+index 11e4725b8b1c..a72296797357 100644
+--- a/tools/lib/bpf/libbpf.c
++++ b/tools/lib/bpf/libbpf.c
+@@ -5028,8 +5028,8 @@ static int bpf_object__collect_map_relos(struct bpf_object *obj,
+ int i, j, nrels, new_sz, ptr_sz = sizeof(void *);
+ const struct btf_var_secinfo *vi = NULL;
+ const struct btf_type *sec, *var, *def;
++ struct bpf_map *map = NULL, *targ_map;
+ const struct btf_member *member;
+- struct bpf_map *map, *targ_map;
+ const char *name, *mname;
+ Elf_Data *symbols;
+ unsigned int moff;
+--
+2.25.1
+
--- /dev/null
+From 668d1c2951e18512a27aec20b80dea627d01bf04 Mon Sep 17 00:00:00 2001
+From: Tony Ambardar <Tony.Ambardar@gmail.com>
+Date: Thu, 20 Aug 2020 16:05:48 -0700
+Subject: [PATCH] tools/bpftool: allow passing BPFTOOL_VERSION to make
+
+Signed-off-by: Tony Ambardar <Tony.Ambardar@gmail.com>
+---
+ tools/bpf/bpftool/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile
+index 9e85f101be85..d9d821736c31 100644
+--- a/tools/bpf/bpftool/Makefile
++++ b/tools/bpf/bpftool/Makefile
+@@ -25,7 +25,7 @@ endif
+
+ LIBBPF = $(LIBBPF_PATH)libbpf.a
+
+-BPFTOOL_VERSION := $(shell make -rR --no-print-directory -sC ../../.. kernelversion)
++BPFTOOL_VERSION ?= $(shell make -rR --no-print-directory -sC ../../.. kernelversion)
+
+ $(LIBBPF): FORCE
+ $(if $(LIBBPF_OUTPUT),@mkdir -p $(LIBBPF_OUTPUT))
+--
+2.25.1
+
--- /dev/null
+From 6edda7633e4fdf33b91c2e86c05cab805a0dabb3 Mon Sep 17 00:00:00 2001
+From: Tony Ambardar <tony.ambardar@gmail.com>
+Date: Mon, 20 Jul 2020 19:48:16 -0700
+Subject: [PATCH] bpftool: Use only nftw for file tree parsing
+
+The bpftool sources include code to walk file trees, but use multiple
+frameworks to do so: nftw and fts. While nftw conforms to POSIX/SUSv3 and
+is widely available, fts is not conformant and less common, especially on
+non-glibc systems. The inconsistent framework usage hampers maintenance
+and portability of bpftool, in particular for embedded systems.
+
+Standardize code usage by rewriting one fts-based function to use nftw and
+clean up some related function warnings by extending use of "const char *"
+arguments. This change helps in building bpftool against musl for OpenWrt.
+
+Also fix an unsafe call to dirname() by duplicating the string to pass,
+since some implementations may directly alter it. The same approach is
+used in libbpf.c.
+
+Signed-off-by: Tony Ambardar <Tony.Ambardar@gmail.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Reviewed-by: Quentin Monnet <quentin@isovalent.com>
+Link: https://lore.kernel.org/bpf/20200721024817.13701-1-Tony.Ambardar@gmail.com
+---
+ tools/bpf/bpftool/common.c | 137 ++++++++++++++++++++++---------------
+ tools/bpf/bpftool/main.h | 4 +-
+ 2 files changed, 82 insertions(+), 59 deletions(-)
+
+diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
+index 88264abaa738..d8bb4dd18c8a 100644
+--- a/tools/bpf/bpftool/common.c
++++ b/tools/bpf/bpftool/common.c
+@@ -1,10 +1,11 @@
+ // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+ /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
+
++#define _GNU_SOURCE
+ #include <ctype.h>
+ #include <errno.h>
+ #include <fcntl.h>
+-#include <fts.h>
++#include <ftw.h>
+ #include <libgen.h>
+ #include <mntent.h>
+ #include <stdbool.h>
+@@ -123,24 +124,35 @@ int mount_tracefs(const char *target)
+ return err;
+ }
+
+-int open_obj_pinned(char *path, bool quiet)
++int open_obj_pinned(const char *path, bool quiet)
+ {
+- int fd;
++ char *pname;
++ int fd = -1;
+
+- fd = bpf_obj_get(path);
++ pname = strdup(path);
++ if (!pname) {
++ if (!quiet)
++ p_err("mem alloc failed");
++ goto out_ret;
++ }
++
++ fd = bpf_obj_get(pname);
+ if (fd < 0) {
+ if (!quiet)
+- p_err("bpf obj get (%s): %s", path,
+- errno == EACCES && !is_bpffs(dirname(path)) ?
++ p_err("bpf obj get (%s): %s", pname,
++ errno == EACCES && !is_bpffs(dirname(pname)) ?
+ "directory not in bpf file system (bpffs)" :
+ strerror(errno));
+- return -1;
++ goto out_free;
+ }
+
++out_free:
++ free(pname);
++out_ret:
+ return fd;
+ }
+
+-int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type)
++int open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type)
+ {
+ enum bpf_obj_type type;
+ int fd;
+@@ -353,71 +365,82 @@ void print_hex_data_json(uint8_t *data, size_t len)
+ jsonw_end_array(json_wtr);
+ }
+
++/* extra params for nftw cb */
++static struct pinned_obj_table *build_fn_table;
++static enum bpf_obj_type build_fn_type;
++
++static int do_build_table_cb(const char *fpath, const struct stat *sb,
++ int typeflag, struct FTW *ftwbuf)
++{
++ struct bpf_prog_info pinned_info;
++ __u32 len = sizeof(pinned_info);
++ struct pinned_obj *obj_node;
++ enum bpf_obj_type objtype;
++ int fd, err = 0;
++
++ if (typeflag != FTW_F)
++ goto out_ret;
++
++ fd = open_obj_pinned(fpath, true);
++ if (fd < 0)
++ goto out_ret;
++
++ objtype = get_fd_type(fd);
++ if (objtype != build_fn_type)
++ goto out_close;
++
++ memset(&pinned_info, 0, sizeof(pinned_info));
++ if (bpf_obj_get_info_by_fd(fd, &pinned_info, &len))
++ goto out_close;
++
++ obj_node = calloc(1, sizeof(*obj_node));
++ if (!obj_node) {
++ err = -1;
++ goto out_close;
++ }
++
++ obj_node->id = pinned_info.id;
++ obj_node->path = strdup(fpath);
++ if (!obj_node->path) {
++ err = -1;
++ free(obj_node);
++ goto out_close;
++ }
++
++ hash_add(build_fn_table->table, &obj_node->hash, obj_node->id);
++out_close:
++ close(fd);
++out_ret:
++ return err;
++}
++
+ int build_pinned_obj_table(struct pinned_obj_table *tab,
+ enum bpf_obj_type type)
+ {
+- struct bpf_prog_info pinned_info = {};
+- struct pinned_obj *obj_node = NULL;
+- __u32 len = sizeof(pinned_info);
+ struct mntent *mntent = NULL;
+- enum bpf_obj_type objtype;
+ FILE *mntfile = NULL;
+- FTSENT *ftse = NULL;
+- FTS *fts = NULL;
+- int fd, err;
++ int flags = FTW_PHYS;
++ int nopenfd = 16;
++ int err = 0;
+
+ mntfile = setmntent("/proc/mounts", "r");
+ if (!mntfile)
+ return -1;
+
++ build_fn_table = tab;
++ build_fn_type = type;
++
+ while ((mntent = getmntent(mntfile))) {
+- char *path[] = { mntent->mnt_dir, NULL };
++ char *path = mntent->mnt_dir;
+
+ if (strncmp(mntent->mnt_type, "bpf", 3) != 0)
+ continue;
+-
+- fts = fts_open(path, 0, NULL);
+- if (!fts)
+- continue;
+-
+- while ((ftse = fts_read(fts))) {
+- if (!(ftse->fts_info & FTS_F))
+- continue;
+- fd = open_obj_pinned(ftse->fts_path, true);
+- if (fd < 0)
+- continue;
+-
+- objtype = get_fd_type(fd);
+- if (objtype != type) {
+- close(fd);
+- continue;
+- }
+- memset(&pinned_info, 0, sizeof(pinned_info));
+- err = bpf_obj_get_info_by_fd(fd, &pinned_info, &len);
+- if (err) {
+- close(fd);
+- continue;
+- }
+-
+- obj_node = malloc(sizeof(*obj_node));
+- if (!obj_node) {
+- close(fd);
+- fts_close(fts);
+- fclose(mntfile);
+- return -1;
+- }
+-
+- memset(obj_node, 0, sizeof(*obj_node));
+- obj_node->id = pinned_info.id;
+- obj_node->path = strdup(ftse->fts_path);
+- hash_add(tab->table, &obj_node->hash, obj_node->id);
+-
+- close(fd);
+- }
+- fts_close(fts);
++ err = nftw(path, do_build_table_cb, nopenfd, flags);
++ if (err)
++ break;
+ }
+ fclose(mntfile);
+- return 0;
++ return err;
+ }
+
+ void delete_pinned_obj_table(struct pinned_obj_table *tab)
+diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
+index af9ad56c303a..b02e763f1e9c 100644
+--- a/tools/bpf/bpftool/main.h
++++ b/tools/bpf/bpftool/main.h
+@@ -140,8 +140,8 @@ int cmd_select(const struct cmd *cmds, int argc, char **argv,
+ int get_fd_type(int fd);
+ const char *get_fd_type_name(enum bpf_obj_type type);
+ char *get_fdinfo(int fd, const char *key);
+-int open_obj_pinned(char *path, bool quiet);
+-int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type);
++int open_obj_pinned(const char *path, bool quiet);
++int open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type);
+ int mount_bpffs_for_pin(const char *name);
+ int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32));
+ int do_pin_fd(int fd, const char *name);
+--
+2.17.1
+