From 41db5534d8fa55a2880b5b0d02abc7c503beff71 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 4 Aug 2021 16:22:30 -0700 Subject: [PATCH 01/28] sync: latest libbpf changes from kernel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Syncing latest libbpf commits from kernel repository. Baseline bpf-next commit: 807b8f0e24e6004984094e1bcbbd2b297011a085 Checkpoint bpf-next commit: 372642ea83ff1c71a5d567a704c912359eb59776 Baseline bpf commit: d6371c76e20d7d3f61b05fd67b596af4d14a8886 Checkpoint bpf commit: a02215ce72a37a19a690803b23b091186ee4f7b2 Alexei Starovoitov (4): libbpf: Cleanup the layering between CORE and bpf_program. libbpf: Split bpf_core_apply_relo() into bpf_program independent helper. libbpf: Move CO-RE types into relo_core.h. libbpf: Split CO-RE logic into relo_core.c. Daniel Xu (1): libbpf: Do not close un-owned FD 0 on errors Evgeniy Litvinenko (1): libbpf: Add bpf_map__pin_path function Hengqi Chen (1): libbpf: Add btf__load_vmlinux_btf/btf__load_module_btf Jason Wang (1): libbpf: Fix comment typo Jiri Olsa (3): libbpf: Fix func leak in attach_kprobe libbpf: Allow decimal offset for kprobes libbpf: Export bpf_program__attach_kprobe_opts function Martynas Pumputis (1): libbpf: Fix race when pinning maps in parallel Quentin Monnet (4): libbpf: Return non-null error on failures in libbpf_find_prog_btf_id() libbpf: Rename btf__load() as btf__load_into_kernel() libbpf: Rename btf__get_from_id() as btf__load_from_kernel_by_id() libbpf: Add split BTF support for btf__load_from_kernel_by_id() Robin Gögge (1): libbpf: Fix probe for BPF_PROG_TYPE_CGROUP_SOCKOPT src/btf.c | 50 +- src/btf.h | 12 +- src/libbpf.c | 1419 +++-------------------------------------- src/libbpf.h | 16 + src/libbpf.map | 7 + src/libbpf_internal.h | 81 +-- src/libbpf_probes.c | 4 +- src/relo_core.c | 1295 +++++++++++++++++++++++++++++++++++++ src/relo_core.h | 100 +++ 9 files changed, 1561 insertions(+), 1423 deletions(-) create mode 100644 src/relo_core.c create mode 100644 src/relo_core.h -- 2.30.2 --- BPF-CHECKPOINT-COMMIT | 2 +- CHECKPOINT-COMMIT | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/BPF-CHECKPOINT-COMMIT b/BPF-CHECKPOINT-COMMIT index 1feda21..93b676d 100644 --- a/BPF-CHECKPOINT-COMMIT +++ b/BPF-CHECKPOINT-COMMIT @@ -1 +1 @@ -d6371c76e20d7d3f61b05fd67b596af4d14a8886 +7c4a22339e7ce7b6ed473a8e682da622c3a774ee diff --git a/CHECKPOINT-COMMIT b/CHECKPOINT-COMMIT index 2e43e1b..74ab33c 100644 --- a/CHECKPOINT-COMMIT +++ b/CHECKPOINT-COMMIT @@ -1 +1 @@ -807b8f0e24e6004984094e1bcbbd2b297011a085 +372642ea83ff1c71a5d567a704c912359eb59776 From 52e96052a23a409cbad82ed829c5466d0bf1a4ae Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 4 Aug 2021 17:32:11 -0700 Subject: [PATCH 02/28] ci: blacklist newly migrated netcnt selftest Seems like netcnt uses some map operations not supported by 5.5. Signed-off-by: Andrii Nakryiko --- travis-ci/vmtest/configs/blacklist/BLACKLIST-5.5.0 | 1 + 1 file changed, 1 insertion(+) diff --git a/travis-ci/vmtest/configs/blacklist/BLACKLIST-5.5.0 b/travis-ci/vmtest/configs/blacklist/BLACKLIST-5.5.0 index a8b26d3..0b774ea 100644 --- a/travis-ci/vmtest/configs/blacklist/BLACKLIST-5.5.0 +++ b/travis-ci/vmtest/configs/blacklist/BLACKLIST-5.5.0 @@ -43,6 +43,7 @@ migrate_reuseport # v5.14+ mmap # 5.5 kernel is too permissive with re-mmaping modify_return # fmod_ret support is missing module_attach # module BTF support missing (v5.11+) +netcnt ns_current_pid_tgid # bpf_get_ns_current_pid_tgid() helper is missing pe_preserve_elems # v5.10+ perf_branches # bpf_read_branch_records() helper is missing From dbdd8f3b343fdee4cae4504b200b28ac02aabd7e Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 4 Aug 2021 18:32:14 -0700 Subject: [PATCH 03/28] ci: make CI build log less verbose Only keep stderr output in case of errors for kernel and selftests builds. Having a multi-thousand-line output isn't useful and slows down Github Actions' log view UI. Also quiet down wget's "progress bar" output. While at the same time see some totals from tar, just for the fun of it. Signed-off-by: Andrii Nakryiko --- travis-ci/vmtest/build_selftests.sh | 2 +- travis-ci/vmtest/checkout_latest_kernel.sh | 2 +- travis-ci/vmtest/prepare_selftests.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/travis-ci/vmtest/build_selftests.sh b/travis-ci/vmtest/build_selftests.sh index 9f07878..9952e48 100755 --- a/travis-ci/vmtest/build_selftests.sh +++ b/travis-ci/vmtest/build_selftests.sh @@ -30,7 +30,7 @@ make \ VMLINUX_BTF="${VMLINUX_BTF}" \ VMLINUX_H=${VMLINUX_H} \ -C "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" \ - -j $((4*$(nproc))) + -j $((4*$(nproc))) >/dev/null mkdir ${LIBBPF_PATH}/selftests cp -R "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" \ ${LIBBPF_PATH}/selftests diff --git a/travis-ci/vmtest/checkout_latest_kernel.sh b/travis-ci/vmtest/checkout_latest_kernel.sh index 16d8320..6cc3c3a 100755 --- a/travis-ci/vmtest/checkout_latest_kernel.sh +++ b/travis-ci/vmtest/checkout_latest_kernel.sh @@ -32,7 +32,7 @@ if [ ! -d "${REPO_PATH}" ]; then mkdir -p $(dirname "${REPO_PATH}") cd $(dirname "${REPO_PATH}") # attempt to fetch desired bpf-next repo snapshot - if wget ${SNAPSHOT_URL} && tar xf bpf-next-${LINUX_SHA}.tar.gz ; then + if wget -nv ${SNAPSHOT_URL} && tar xf bpf-next-${LINUX_SHA}.tar.gz --totals ; then mv bpf-next-${LINUX_SHA} $(basename ${REPO_PATH}) else # but fallback to git fetch approach if that fails diff --git a/travis-ci/vmtest/prepare_selftests.sh b/travis-ci/vmtest/prepare_selftests.sh index 1c74e5c..52239e3 100755 --- a/travis-ci/vmtest/prepare_selftests.sh +++ b/travis-ci/vmtest/prepare_selftests.sh @@ -13,7 +13,7 @@ if [[ "${KERNEL}" = 'LATEST' ]]; then travis_fold start build_kernel "Kernel build" cp ${VMTEST_ROOT}/configs/latest.config .config - make -j $((4*$(nproc))) olddefconfig all + make -j $((4*$(nproc))) olddefconfig all >/dev/null travis_fold end build_kernel fi From 70ad3e831482db7409599c159d99d3939702e57f Mon Sep 17 00:00:00 2001 From: Rafael David Tinoco Date: Fri, 6 Aug 2021 15:31:24 -0300 Subject: [PATCH 04/28] makefile: fix missing object for static compilation Makefile needs relo_core object added to objects list to avoid static linking errors when doing static compilation: /bin/ld: .../libbpf.a(libbpf.o): in function `bpf_core_apply_relo': .../libbpf/src/libbpf.c:5134: undefined reference to `bpf_core_apply_relo_insn' Signed-off-by: Rafael David Tinoco --- src/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 8bf1d8a..913082d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -36,7 +36,8 @@ SHARED_OBJDIR := $(OBJDIR)/sharedobjs STATIC_OBJDIR := $(OBJDIR)/staticobjs OBJS := bpf.o btf.o libbpf.o libbpf_errno.o netlink.o \ nlattr.o str_error.o libbpf_probes.o bpf_prog_linfo.o xsk.o \ - btf_dump.o hashmap.o ringbuf.o strset.o linker.o gen_loader.o + btf_dump.o hashmap.o ringbuf.o strset.o linker.o gen_loader.o \ + relo_core.o SHARED_OBJS := $(addprefix $(SHARED_OBJDIR)/,$(OBJS)) STATIC_OBJS := $(addprefix $(STATIC_OBJDIR)/,$(OBJS)) From 6bf8babb335303afca65d1109c6706b9d10bea56 Mon Sep 17 00:00:00 2001 From: Yucong Sun Date: Wed, 4 Aug 2021 12:38:18 -0700 Subject: [PATCH 05/28] Add a test step to produce a minimal binary using libbpf. This patch adds a test step to link a minimal program to libbpf library produced, making sure that the library works. --- travis-ci/managers/debian.sh | 6 ++++-- travis-ci/managers/test_compile.sh | 14 ++++++++++++++ travis-ci/managers/ubuntu.sh | 2 +- 3 files changed, 19 insertions(+), 3 deletions(-) create mode 100755 travis-ci/managers/test_compile.sh diff --git a/travis-ci/managers/debian.sh b/travis-ci/managers/debian.sh index 55f990b..759bb78 100755 --- a/travis-ci/managers/debian.sh +++ b/travis-ci/managers/debian.sh @@ -48,6 +48,7 @@ for phase in "${PHASES[@]}"; do echo -e "::endgroup::" ;; RUN|RUN_CLANG|RUN_GCC10|RUN_ASAN|RUN_CLANG_ASAN|RUN_GCC10_ASAN) + CC="cc" if [[ "$phase" = *"CLANG"* ]]; then ENV_VARS="-e CC=clang -e CXX=clang++" CC="clang" @@ -62,7 +63,7 @@ for phase in "${PHASES[@]}"; do CFLAGS="${CFLAGS} -fsanitize=address,undefined" fi docker_exec mkdir build install - docker_exec ${CC:-cc} --version + docker_exec ${CC} --version info "build" docker_exec make -j$((4*$(nproc))) CFLAGS="${CFLAGS}" -C ./src -B OBJDIR=../build info "ldd build/libbpf.so:" @@ -73,7 +74,8 @@ for phase in "${PHASES[@]}"; do fi info "install" docker_exec make -j$((4*$(nproc))) -C src OBJDIR=../build DESTDIR=../install install - docker_exec rm -rf build install + info "link binary" + docker_exec bash -c "CFLAGS=\"${CFLAGS}\" ./travis-ci/managers/test_compile.sh" ;; CLEANUP) info "Cleanup phase" diff --git a/travis-ci/managers/test_compile.sh b/travis-ci/managers/test_compile.sh new file mode 100755 index 0000000..01b7fed --- /dev/null +++ b/travis-ci/managers/test_compile.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -euox pipefail + +CFLAGS=${CFLAGS:-} + +cat << EOF > main.c +#include +int main() { + return bpf_object__open(0) < 0; +} +EOF + +# static linking +${CC:-cc} ${CFLAGS} -o main -I./install/usr/include main.c ./build/libbpf.a -lelf -lz diff --git a/travis-ci/managers/ubuntu.sh b/travis-ci/managers/ubuntu.sh index 6c38ca1..8af229e 100755 --- a/travis-ci/managers/ubuntu.sh +++ b/travis-ci/managers/ubuntu.sh @@ -20,4 +20,4 @@ if ! ldd build/libbpf.so | grep -q libelf; then exit 1 fi make -j$((4*$(nproc))) -C src OBJDIR=../build DESTDIR=../install install -rm -rf build install +CFLAGS=${CFLAGS} $(dirname $0)/test_compile.sh From 64f027efda548dd918e7de471af72202b1402764 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Fri, 6 Aug 2021 17:40:18 -0700 Subject: [PATCH 06/28] ci: restore all temporary disabled tests Upstream bpf-next should be good, so no temporary blocked tests should remain. Signed-off-by: Andrii Nakryiko --- travis-ci/vmtest/configs/blacklist/BLACKLIST-latest | 1 - travis-ci/vmtest/run_selftests.sh | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/travis-ci/vmtest/configs/blacklist/BLACKLIST-latest b/travis-ci/vmtest/configs/blacklist/BLACKLIST-latest index 8d49647..688dcae 100644 --- a/travis-ci/vmtest/configs/blacklist/BLACKLIST-latest +++ b/travis-ci/vmtest/configs/blacklist/BLACKLIST-latest @@ -1,2 +1 @@ # TEMPORARY -tc_bpf diff --git a/travis-ci/vmtest/run_selftests.sh b/travis-ci/vmtest/run_selftests.sh index f334b43..b2d4b5b 100755 --- a/travis-ci/vmtest/run_selftests.sh +++ b/travis-ci/vmtest/run_selftests.sh @@ -46,6 +46,6 @@ cd libbpf/selftests/bpf test_progs if [[ "${KERNEL}" == 'latest' ]]; then - #test_maps + # test_maps test_verifier fi From 1778e0b1bdd924c27e8e877bcd22520c0590862b Mon Sep 17 00:00:00 2001 From: Sergei Iudin Date: Tue, 10 Aug 2021 19:20:58 -0700 Subject: [PATCH 07/28] Make CI tests compatible with vanilla kernel tree This is required to migrate kernel-patches CI to use this code instead of fork --- travis-ci/vmtest/build_selftests.sh | 1 - travis-ci/vmtest/prepare_selftests.sh | 9 +++++---- travis-ci/vmtest/run.sh | 24 ++++++++++++++++-------- travis-ci/vmtest/run_vmtest.sh | 19 ++++++++++++++++--- 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/travis-ci/vmtest/build_selftests.sh b/travis-ci/vmtest/build_selftests.sh index 9952e48..4b0b0b7 100755 --- a/travis-ci/vmtest/build_selftests.sh +++ b/travis-ci/vmtest/build_selftests.sh @@ -10,7 +10,6 @@ sudo apt-get -y install python-docutils # for rst2man LLVM_VER=14 LIBBPF_PATH="${REPO_ROOT}" -REPO_PATH="travis-ci/vmtest/bpf-next" PREPARE_SELFTESTS_SCRIPT=${VMTEST_ROOT}/prepare_selftests-${KERNEL}.sh if [ -f "${PREPARE_SELFTESTS_SCRIPT}" ]; then diff --git a/travis-ci/vmtest/prepare_selftests.sh b/travis-ci/vmtest/prepare_selftests.sh index 52239e3..0dcb7ea 100755 --- a/travis-ci/vmtest/prepare_selftests.sh +++ b/travis-ci/vmtest/prepare_selftests.sh @@ -4,17 +4,18 @@ set -eu source $(cd $(dirname $0) && pwd)/helpers.sh -REPO_PATH=$1 +REPO_PATH=${1:-} -${VMTEST_ROOT}/checkout_latest_kernel.sh ${REPO_PATH} -cd ${REPO_PATH} +if [[ ! -z "$REPO_PATH" ]]; then + ${VMTEST_ROOT}/checkout_latest_kernel.sh ${REPO_PATH} + cd ${REPO_PATH} +fi if [[ "${KERNEL}" = 'LATEST' ]]; then travis_fold start build_kernel "Kernel build" cp ${VMTEST_ROOT}/configs/latest.config .config make -j $((4*$(nproc))) olddefconfig all >/dev/null - travis_fold end build_kernel fi diff --git a/travis-ci/vmtest/run.sh b/travis-ci/vmtest/run.sh index ed2d329..e88daf3 100755 --- a/travis-ci/vmtest/run.sh +++ b/travis-ci/vmtest/run.sh @@ -92,6 +92,12 @@ SKIPSOURCE=0 APPEND="" DIR="$PWD" LIST=0 + +# by default will copy all files that aren't listed in git exclusions +# but it doesn't work for entire kernel tree very well +# so for full kernel tree you may need to SOURCE_FULLCOPY=0 +SOURCE_FULLCOPY=${SOURCE_FULLCOPY:-1} + while true; do case "$1" in -k|--kernel) @@ -374,9 +380,10 @@ fi travis_fold end vmlinux_setup +REPO_PATH="${SELFTEST_REPO_PATH:-travis-ci/vmtest/bpf-next}" LIBBPF_PATH="${REPO_ROOT}" \ - REPO_PATH="travis-ci/vmtest/bpf-next" \ VMTEST_ROOT="${VMTEST_ROOT}" \ + REPO_PATH="${REPO_PATH}" \ VMLINUX_BTF=${vmlinux} ${VMTEST_ROOT}/build_selftests.sh travis_fold start vm_init "Starting virtual machine..." @@ -385,16 +392,17 @@ if (( SKIPSOURCE )); then echo "Not copying source files..." >&2 else echo "Copying source files..." >&2 - # Copy the source files in. sudo mkdir -p -m 0755 "$mnt/${PROJECT_NAME}" - { - if [[ -e .git ]]; then - git ls-files -z + if [[ "${SOURCE_FULLCOPY}" == "1" ]]; then + git ls-files -z | sudo rsync --files-from=- -0cpt . "$mnt/${PROJECT_NAME}" else - tr '\n' '\0' < "${PROJECT_NAME}.egg-info/SOURCES.txt" - fi - } | sudo rsync --files-from=- -0cpt . "$mnt/${PROJECT_NAME}" + sudo mkdir -p -m 0755 ${mnt}/${PROJECT_NAME}/{selftests,travis-ci} + tree --du -shaC "${REPO_ROOT}/selftests/bpf" + sudo rsync -avm "${REPO_ROOT}/selftests/bpf" "$mnt/${PROJECT_NAME}/selftests/" + sudo rsync -avm "${REPO_ROOT}/travis-ci/vmtest" "$mnt/${PROJECT_NAME}/travis-ci/" + fi + fi setup_script="#!/bin/sh diff --git a/travis-ci/vmtest/run_vmtest.sh b/travis-ci/vmtest/run_vmtest.sh index 7728e6d..91d201c 100755 --- a/travis-ci/vmtest/run_vmtest.sh +++ b/travis-ci/vmtest/run_vmtest.sh @@ -6,6 +6,10 @@ source $(cd $(dirname $0) && pwd)/helpers.sh VMTEST_SETUPCMD="GITHUB_WORKFLOW=${GITHUB_WORKFLOW:-} PROJECT_NAME=${PROJECT_NAME} ./${PROJECT_NAME}/travis-ci/vmtest/run_selftests.sh" +# if CHECKOUT_KERNEL is 1 code will consider that kernel code lives elsewhere +# if 0 it will consider that REPO_ROOT is a kernel tree +CHECKOUT_KERNEL=${CHECKOUT_KERNEL:-1} + echo "KERNEL: $KERNEL" echo @@ -24,7 +28,12 @@ sudo aptitude install -y clang-14 lld-14 llvm-14 travis_fold end install_clang # Build selftests (and latest kernel, if necessary) -${VMTEST_ROOT}/prepare_selftests.sh travis-ci/vmtest/bpf-next + +if [[ "$CHECKOUT_KERNEL" == "1" ]]; then + ${VMTEST_ROOT}/prepare_selftests.sh travis-ci/vmtest/bpf-next +else + ${VMTEST_ROOT}/prepare_selftests.sh +fi # Escape whitespace characters. setup_cmd=$(sed 's/\([[:space:]]\)/\\\1/g' <<< "${VMTEST_SETUPCMD}") @@ -32,7 +41,11 @@ setup_cmd=$(sed 's/\([[:space:]]\)/\\\1/g' <<< "${VMTEST_SETUPCMD}") sudo adduser "${USER}" kvm if [[ "${KERNEL}" = 'LATEST' ]]; then - sudo -E sudo -E -u "${USER}" "${VMTEST_ROOT}/run.sh" -b travis-ci/vmtest/bpf-next -o -d ~ -s "${setup_cmd}" ~/root.img; + if [[ "$CHECKOUT_KERNEL" == "1" ]]; then + sudo -E sudo -E -u "${USER}" "${VMTEST_ROOT}/run.sh" -b travis-ci/vmtest/bpf-next -o -d ~ -s "${setup_cmd}" ~/root.img + else + sudo -E sudo -E -u "${USER}" "${VMTEST_ROOT}/run.sh" -b "${REPO_ROOT}" -o -d ~ -s "${setup_cmd}" ~/root.img + fi else - sudo -E sudo -E -u "${USER}" "${VMTEST_ROOT}/run.sh" -k "${KERNEL}*" -o -d ~ -s "${setup_cmd}" ~/root.img; + sudo -E sudo -E -u "${USER}" "${VMTEST_ROOT}/run.sh" -k "${KERNEL}*" -o -d ~ -s "${setup_cmd}" ~/root.img fi From 88649fe655b8bc387216ffc563aeb2dbf9544fe8 Mon Sep 17 00:00:00 2001 From: Quentin Monnet Date: Sun, 15 Aug 2021 22:15:49 +0100 Subject: [PATCH 08/28] ci: run script to test bpftool types/options sync When new eBPF program, map, or attach types are added to the kernel, bpftool needs to be updated in order to support the related features. These updates should add the new types to the code itself, but also to the help messages, documentation, and bash completion. Given that it is easy to omit one of those, a script has been created to attempt to validate that all parts have been consistently updated. This new script for bpftool is hosted in the kernel repository, amongst the BPF selftests. But it is not called from the Makefile, and not run along with the other selftests. If it was, all patches updating the BPF UAPI would require the relevant changes in bpftool at the same time, _in the same patches_, which is not desirable. To ensure that bpftool's parts remain in sync, let's run this script from the CI. This patch adds a new section to the run.sh script, focused on bpftool, and calling the new test_bpftool_synctypes.py. --- travis-ci/vmtest/run.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/travis-ci/vmtest/run.sh b/travis-ci/vmtest/run.sh index e88daf3..5309e66 100755 --- a/travis-ci/vmtest/run.sh +++ b/travis-ci/vmtest/run.sh @@ -386,6 +386,15 @@ LIBBPF_PATH="${REPO_ROOT}" \ REPO_PATH="${REPO_PATH}" \ VMLINUX_BTF=${vmlinux} ${VMTEST_ROOT}/build_selftests.sh +travis_fold start bpftool_checks "Running bpftool checks..." +if [[ "${KERNEL}" = 'LATEST' ]]; then + "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf/test_bpftool_synctypes.py" && \ + echo "Consistency checks passed successfully." +else + echo "Consistency checks skipped." +fi +travis_fold end bpftool_checks + travis_fold start vm_init "Starting virtual machine..." if (( SKIPSOURCE )); then From b2a63c974dea402f68f080c5a8fbd2937fd5d4b4 Mon Sep 17 00:00:00 2001 From: grantseltzer Date: Mon, 9 Aug 2021 20:32:09 -0400 Subject: [PATCH 09/28] docs: reconfigure libbpf documentation syncing This adds documentation files, including ones for autogenerating API documentation based on code comments in the source code that's pulled in via the mirror. Signed-off-by: Grant Seltzer --- .readthedocs.yaml | 17 +++ docs/.gitignore | 2 + docs/api.rst | 51 +++++++ docs/conf.py | 40 +++++ docs/sphinx/Makefile | 9 ++ docs/sphinx/doxygen/Doxyfile | 277 +++++++++++++++++++++++++++++++++++ docs/sphinx/requirements.txt | 1 + scripts/sync-kernel.sh | 1 + 8 files changed, 398 insertions(+) create mode 100644 .readthedocs.yaml create mode 100644 docs/.gitignore create mode 100644 docs/api.rst create mode 100644 docs/conf.py create mode 100644 docs/sphinx/Makefile create mode 100644 docs/sphinx/doxygen/Doxyfile create mode 100644 docs/sphinx/requirements.txt diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..2e49eff --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,17 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Build documentation in the docs/ directory with Sphinx +sphinx: + builder: html + configuration: docs/conf.py + +# Optionally set the version of Python and requirements required to build your docs +python: + version: 3.7 + install: + - requirements: docs/sphinx/requirements.txt \ No newline at end of file diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..dd08fae --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,2 @@ +sphinx/build +sphinx/doxygen/build \ No newline at end of file diff --git a/docs/api.rst b/docs/api.rst new file mode 100644 index 0000000..56aa72f --- /dev/null +++ b/docs/api.rst @@ -0,0 +1,51 @@ +.. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) + +.. _api: + +.. toctree:: Table of Contents + + +LIBBPF API +================== + +libbpf.h +-------- +.. doxygenfile:: libbpf.h + :project: libbpf + :sections: func define public-type + +bpf.h +----- +.. doxygenfile:: bpf.h + :project: libbpf + :sections: func define public-type + +btf.h +----- +.. doxygenfile:: btf.h + :project: libbpf + :sections: func define public-type + +xsk.h +----- +.. doxygenfile:: xsk.h + :project: libbpf + :sections: func define public-type + +bpf_tracing.h +------------- +.. doxygenfile:: bpf_tracing.h + :project: libbpf + :sections: func define public-type + +bpf_core_read.h +--------------- +.. doxygenfile:: bpf_core_read.h + :project: libbpf + :sections: func define public-type + +bpf_endian.h +------------ +.. doxygenfile:: bpf_endian.h + :project: libbpf + :sections: func define public-type diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..1d8714e --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +import os +import subprocess + +project = "libbpf" + +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.doctest', + 'sphinx.ext.mathjax', + 'sphinx.ext.viewcode', + 'sphinx.ext.imgmath', + 'sphinx.ext.todo', + 'breathe', +] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [] + +read_the_docs_build = os.environ.get('READTHEDOCS', None) == 'True' + +if read_the_docs_build: + subprocess.call('cd sphinx ; make clean', shell=True) + subprocess.call('cd sphinx/doxygen ; doxygen', shell=True) + +html_theme = 'sphinx_rtd_theme' + +breathe_projects = { "libbpf": "./sphinx/doxygen/build/xml/" } +breathe_default_project = "libbpf" +breathe_show_define_initializer = True +breathe_show_enumvalue_initializer = True diff --git a/docs/sphinx/Makefile b/docs/sphinx/Makefile new file mode 100644 index 0000000..5dc39c5 --- /dev/null +++ b/docs/sphinx/Makefile @@ -0,0 +1,9 @@ +SPHINXBUILD ?= sphinx-build +SOURCEDIR = ../src +BUILDDIR = build + +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" + +%: + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" diff --git a/docs/sphinx/doxygen/Doxyfile b/docs/sphinx/doxygen/Doxyfile new file mode 100644 index 0000000..502d335 --- /dev/null +++ b/docs/sphinx/doxygen/Doxyfile @@ -0,0 +1,277 @@ +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = "libbpf" +PROJECT_NUMBER = +PROJECT_BRIEF = +PROJECT_LOGO = +OUTPUT_DIRECTORY = ./build +CREATE_SUBDIRS = NO +ALLOW_UNICODE_NAMES = NO +OUTPUT_LANGUAGE = English +OUTPUT_TEXT_DIRECTION = None +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +JAVADOC_BANNER = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +PYTHON_DOCSTRING = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 4 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +OPTIMIZE_OUTPUT_SLICE = NO +EXTENSION_MAPPING = +MARKDOWN_SUPPORT = YES +TOC_INCLUDE_HEADINGS = 5 +AUTOLINK_SUPPORT = YES +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +GROUP_NESTED_COMPOUNDS = NO +SUBGROUPING = YES +INLINE_GROUPED_CLASSES = NO +INLINE_SIMPLE_STRUCTS = NO +TYPEDEF_HIDES_STRUCT = NO +LOOKUP_CACHE_SIZE = 0 +NUM_PROC_THREADS = 1 +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_PRIV_VIRTUAL = NO +EXTRACT_PACKAGE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +RESOLVE_UNNAMED_PARAMS = YES +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +HIDE_COMPOUND_REFERENCE= NO +SHOW_INCLUDE_FILES = YES +SHOW_GROUPED_MEMB_INC = NO +FORCE_LOCAL_INCLUDES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_MEMBERS_CTORS_1ST = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +STRICT_PROTO_MATCHING = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +CITE_BIB_FILES = +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_AS_ERROR = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +INPUT = ../../src +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.c \ + *.h +RECURSIVE = NO +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = ___* +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +FILTER_SOURCE_PATTERNS = +USE_MDFILE_AS_MAINPAGE = YES +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +SOURCE_TOOLTIPS = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +ALPHABETICAL_INDEX = YES +IGNORE_PREFIX = +GENERATE_HTML = NO +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_EXTRA_STYLESHEET = +HTML_EXTRA_FILES = +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 80 +HTML_TIMESTAMP = NO +HTML_DYNAMIC_MENUS = YES +HTML_DYNAMIC_SECTIONS = NO +HTML_INDEX_NUM_ENTRIES = 100 +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +DOCSET_PUBLISHER_ID = org.doxygen.Publisher +DOCSET_PUBLISHER_NAME = Publisher +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = org.doxygen.Project +QHP_VIRTUAL_FOLDER = doc +QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = +QHG_LOCATION = +GENERATE_ECLIPSEHELP = NO +ECLIPSE_DOC_ID = org.doxygen.Project +DISABLE_INDEX = NO +GENERATE_TREEVIEW = NO +ENUM_VALUES_PER_LINE = 4 +TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO +HTML_FORMULA_FORMAT = png +FORMULA_FONTSIZE = 10 +FORMULA_TRANSPARENT = YES +FORMULA_MACROFILE = +USE_MATHJAX = NO +MATHJAX_FORMAT = HTML-CSS +MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@2 +MATHJAX_EXTENSIONS = +MATHJAX_CODEFILE = +SEARCHENGINE = YES +SERVER_BASED_SEARCH = NO +EXTERNAL_SEARCH = NO +SEARCHENGINE_URL = +SEARCHDATA_FILE = searchdata.xml +EXTERNAL_SEARCH_ID = +EXTRA_SEARCH_MAPPINGS = +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = +MAKEINDEX_CMD_NAME = makeindex +LATEX_MAKEINDEX_CMD = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4 +EXTRA_PACKAGES = +LATEX_HEADER = +LATEX_FOOTER = +LATEX_EXTRA_STYLESHEET = +LATEX_EXTRA_FILES = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +LATEX_SOURCE_CODE = NO +LATEX_BIB_STYLE = plain +LATEX_TIMESTAMP = NO +LATEX_EMOJI_DIRECTORY = +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +RTF_SOURCE_CODE = NO +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_SUBDIR = +MAN_LINKS = NO +GENERATE_XML = YES +XML_OUTPUT = xml +XML_PROGRAMLISTING = YES +XML_NS_MEMB_FILE_SCOPE = NO +GENERATE_DOCBOOK = NO +DOCBOOK_OUTPUT = docbook +DOCBOOK_PROGRAMLISTING = NO +GENERATE_AUTOGEN_DEF = NO +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = YES +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = NO +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +EXTERNAL_PAGES = YES +CLASS_DIAGRAMS = YES +DIA_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +DOT_NUM_THREADS = 0 +DOT_FONTNAME = Helvetica +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +UML_LIMIT_NUM_FIELDS = 10 +DOT_UML_DETAILS = NO +DOT_WRAP_THRESHOLD = 17 +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +INTERACTIVE_SVG = NO +DOT_PATH = +DOTFILE_DIRS = +MSCFILE_DIRS = +DIAFILE_DIRS = +PLANTUML_JAR_PATH = +PLANTUML_CFG_FILE = +PLANTUML_INCLUDE_PATH = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES diff --git a/docs/sphinx/requirements.txt b/docs/sphinx/requirements.txt new file mode 100644 index 0000000..188f51e --- /dev/null +++ b/docs/sphinx/requirements.txt @@ -0,0 +1 @@ +breathe \ No newline at end of file diff --git a/scripts/sync-kernel.sh b/scripts/sync-kernel.sh index cd4c256..cf49f6d 100755 --- a/scripts/sync-kernel.sh +++ b/scripts/sync-kernel.sh @@ -47,6 +47,7 @@ PATH_MAP=( \ [tools/include/uapi/linux/netlink.h]=include/uapi/linux/netlink.h \ [tools/include/uapi/linux/pkt_cls.h]=include/uapi/linux/pkt_cls.h \ [tools/include/uapi/linux/pkt_sched.h]=include/uapi/linux/pkt_sched.h \ + [Documentation/bpf/libbpf]=src/docs \ ) LIBBPF_PATHS="${!PATH_MAP[@]} :^tools/lib/bpf/Makefile :^tools/lib/bpf/Build :^tools/lib/bpf/.gitignore :^tools/include/tools/libc_compat.h" From 4ab24e7d62f017f1ac97bdc3fbef40ad8da766bf Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Mon, 16 Aug 2021 21:19:06 -0700 Subject: [PATCH 10/28] docs: initial set of libbpf docs Add libbpf-related .rst files before they started being synced automatically. Signed-off-by: Andrii Nakryiko --- docs/libbpf.rst | 14 +++ docs/libbpf_build.rst | 37 +++++++ docs/libbpf_naming_convention.rst | 162 ++++++++++++++++++++++++++++++ 3 files changed, 213 insertions(+) create mode 100644 docs/libbpf.rst create mode 100644 docs/libbpf_build.rst create mode 100644 docs/libbpf_naming_convention.rst diff --git a/docs/libbpf.rst b/docs/libbpf.rst new file mode 100644 index 0000000..1b1e61d --- /dev/null +++ b/docs/libbpf.rst @@ -0,0 +1,14 @@ +.. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) + +libbpf +====== + +This is documentation for libbpf, a userspace library for loading and +interacting with bpf programs. + +All general BPF questions, including kernel functionality, libbpf APIs and +their application, should be sent to bpf@vger.kernel.org mailing list. +You can `subscribe `_ to the +mailing list search its `archive `_. +Please search the archive before asking new questions. It very well might +be that this was already addressed or answered before. diff --git a/docs/libbpf_build.rst b/docs/libbpf_build.rst new file mode 100644 index 0000000..8e8c23e --- /dev/null +++ b/docs/libbpf_build.rst @@ -0,0 +1,37 @@ +.. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) + +Building libbpf +=============== + +libelf and zlib are internal dependencies of libbpf and thus are required to link +against and must be installed on the system for applications to work. +pkg-config is used by default to find libelf, and the program called +can be overridden with PKG_CONFIG. + +If using pkg-config at build time is not desired, it can be disabled by +setting NO_PKG_CONFIG=1 when calling make. + +To build both static libbpf.a and shared libbpf.so: + +.. code-block:: bash + + $ cd src + $ make + +To build only static libbpf.a library in directory build/ and install them +together with libbpf headers in a staging directory root/: + +.. code-block:: bash + + $ cd src + $ mkdir build root + $ BUILD_STATIC_ONLY=y OBJDIR=build DESTDIR=root make install + +To build both static libbpf.a and shared libbpf.so against a custom libelf +dependency installed in /build/root/ and install them together with libbpf +headers in a build directory /build/root/: + +.. code-block:: bash + + $ cd src + $ PKG_CONFIG_PATH=/build/root/lib64/pkgconfig DESTDIR=/build/root make \ No newline at end of file diff --git a/docs/libbpf_naming_convention.rst b/docs/libbpf_naming_convention.rst new file mode 100644 index 0000000..3de1d51 --- /dev/null +++ b/docs/libbpf_naming_convention.rst @@ -0,0 +1,162 @@ +.. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) + +API naming convention +===================== + +libbpf API provides access to a few logically separated groups of +functions and types. Every group has its own naming convention +described here. It's recommended to follow these conventions whenever a +new function or type is added to keep libbpf API clean and consistent. + +All types and functions provided by libbpf API should have one of the +following prefixes: ``bpf_``, ``btf_``, ``libbpf_``, ``xsk_``, +``btf_dump_``, ``ring_buffer_``, ``perf_buffer_``. + +System call wrappers +-------------------- + +System call wrappers are simple wrappers for commands supported by +sys_bpf system call. These wrappers should go to ``bpf.h`` header file +and map one to one to corresponding commands. + +For example ``bpf_map_lookup_elem`` wraps ``BPF_MAP_LOOKUP_ELEM`` +command of sys_bpf, ``bpf_prog_attach`` wraps ``BPF_PROG_ATTACH``, etc. + +Objects +------- + +Another class of types and functions provided by libbpf API is "objects" +and functions to work with them. Objects are high-level abstractions +such as BPF program or BPF map. They're represented by corresponding +structures such as ``struct bpf_object``, ``struct bpf_program``, +``struct bpf_map``, etc. + +Structures are forward declared and access to their fields should be +provided via corresponding getters and setters rather than directly. + +These objects are associated with corresponding parts of ELF object that +contains compiled BPF programs. + +For example ``struct bpf_object`` represents ELF object itself created +from an ELF file or from a buffer, ``struct bpf_program`` represents a +program in ELF object and ``struct bpf_map`` is a map. + +Functions that work with an object have names built from object name, +double underscore and part that describes function purpose. + +For example ``bpf_object__open`` consists of the name of corresponding +object, ``bpf_object``, double underscore and ``open`` that defines the +purpose of the function to open ELF file and create ``bpf_object`` from +it. + +All objects and corresponding functions other than BTF related should go +to ``libbpf.h``. BTF types and functions should go to ``btf.h``. + +Auxiliary functions +------------------- + +Auxiliary functions and types that don't fit well in any of categories +described above should have ``libbpf_`` prefix, e.g. +``libbpf_get_error`` or ``libbpf_prog_type_by_name``. + +AF_XDP functions +------------------- + +AF_XDP functions should have an ``xsk_`` prefix, e.g. +``xsk_umem__get_data`` or ``xsk_umem__create``. The interface consists +of both low-level ring access functions and high-level configuration +functions. These can be mixed and matched. Note that these functions +are not reentrant for performance reasons. + +ABI +========== + +libbpf can be both linked statically or used as DSO. To avoid possible +conflicts with other libraries an application is linked with, all +non-static libbpf symbols should have one of the prefixes mentioned in +API documentation above. See API naming convention to choose the right +name for a new symbol. + +Symbol visibility +----------------- + +libbpf follow the model when all global symbols have visibility "hidden" +by default and to make a symbol visible it has to be explicitly +attributed with ``LIBBPF_API`` macro. For example: + +.. code-block:: c + + LIBBPF_API int bpf_prog_get_fd_by_id(__u32 id); + +This prevents from accidentally exporting a symbol, that is not supposed +to be a part of ABI what, in turn, improves both libbpf developer- and +user-experiences. + +ABI versionning +--------------- + +To make future ABI extensions possible libbpf ABI is versioned. +Versioning is implemented by ``libbpf.map`` version script that is +passed to linker. + +Version name is ``LIBBPF_`` prefix + three-component numeric version, +starting from ``0.0.1``. + +Every time ABI is being changed, e.g. because a new symbol is added or +semantic of existing symbol is changed, ABI version should be bumped. +This bump in ABI version is at most once per kernel development cycle. + +For example, if current state of ``libbpf.map`` is: + +.. code-block:: c + + LIBBPF_0.0.1 { + global: + bpf_func_a; + bpf_func_b; + local: + \*; + }; + +, and a new symbol ``bpf_func_c`` is being introduced, then +``libbpf.map`` should be changed like this: + +.. code-block:: c + + LIBBPF_0.0.1 { + global: + bpf_func_a; + bpf_func_b; + local: + \*; + }; + LIBBPF_0.0.2 { + global: + bpf_func_c; + } LIBBPF_0.0.1; + +, where new version ``LIBBPF_0.0.2`` depends on the previous +``LIBBPF_0.0.1``. + +Format of version script and ways to handle ABI changes, including +incompatible ones, described in details in [1]. + +Stand-alone build +------------------- + +Under https://github.com/libbpf/libbpf there is a (semi-)automated +mirror of the mainline's version of libbpf for a stand-alone build. + +However, all changes to libbpf's code base must be upstreamed through +the mainline kernel tree. + +License +------------------- + +libbpf is dual-licensed under LGPL 2.1 and BSD 2-Clause. + +Links +------------------- + +[1] https://www.akkadia.org/drepper/dsohowto.pdf + (Chapter 3. Maintaining APIs and ABIs). From 827963ffb3426653116df953bb52860fc636b086 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Mon, 16 Aug 2021 22:11:07 -0700 Subject: [PATCH 11/28] sync: fix up docs sync path mapping Kernel docs from Documentation/bpf/libbpf go straight to docs/ under libbpf. Also ignore libbpf-only parts of docs subdir. Signed-off-by: Andrii Nakryiko --- docs/api.rst | 2 +- scripts/sync-kernel.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/api.rst b/docs/api.rst index 56aa72f..781972d 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -3,7 +3,7 @@ .. _api: .. toctree:: Table of Contents - + LIBBPF API ================== diff --git a/scripts/sync-kernel.sh b/scripts/sync-kernel.sh index cf49f6d..ccf5a41 100755 --- a/scripts/sync-kernel.sh +++ b/scripts/sync-kernel.sh @@ -47,12 +47,12 @@ PATH_MAP=( \ [tools/include/uapi/linux/netlink.h]=include/uapi/linux/netlink.h \ [tools/include/uapi/linux/pkt_cls.h]=include/uapi/linux/pkt_cls.h \ [tools/include/uapi/linux/pkt_sched.h]=include/uapi/linux/pkt_sched.h \ - [Documentation/bpf/libbpf]=src/docs \ + [Documentation/bpf/libbpf]=docs \ ) LIBBPF_PATHS="${!PATH_MAP[@]} :^tools/lib/bpf/Makefile :^tools/lib/bpf/Build :^tools/lib/bpf/.gitignore :^tools/include/tools/libc_compat.h" LIBBPF_VIEW_PATHS="${PATH_MAP[@]}" -LIBBPF_VIEW_EXCLUDE_REGEX='^src/(Makefile|Build|test_libbpf\.c|bpf_helper_defs\.h|\.gitignore)$' +LIBBPF_VIEW_EXCLUDE_REGEX='^src/(Makefile|Build|test_libbpf\.c|bpf_helper_defs\.h|\.gitignore)$|^docs/(\.gitignore|api\.rst|conf\.py)$|^docs/sphinx/.*' LINUX_VIEW_EXCLUDE_REGEX='^include/tools/libc_compat.h$' LIBBPF_TREE_FILTER="mkdir -p __libbpf/include/uapi/linux __libbpf/include/tools && "$'\\\n' From 1a1e7a06126f84f074f1351e62dfe0b75ed84aa3 Mon Sep 17 00:00:00 2001 From: Hangbin Liu Date: Mon, 2 Aug 2021 11:02:19 +0800 Subject: [PATCH 12/28] bonding: add new option lacp_active Add an option lacp_active, which is similar with team's runner.active. This option specifies whether to send LACPDU frames periodically. If set on, the LACPDU frames are sent along with the configured lacp_rate setting. If set off, the LACPDU frames acts as "speak when spoken to". Note, the LACPDU state frames still will be sent when init or unbind port. v2: remove module parameter Signed-off-by: Hangbin Liu Signed-off-by: David S. Miller --- include/uapi/linux/if_link.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index d208b2a..eb15f31 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -653,6 +653,7 @@ enum { IFLA_BOND_AD_ACTOR_SYSTEM, IFLA_BOND_TLB_DYNAMIC_LB, IFLA_BOND_PEER_NOTIF_DELAY, + IFLA_BOND_AD_LACP_ACTIVE, __IFLA_BOND_MAX, }; From c3f7daaab5ffef25b4b9a297a0d82faf3abd428a Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 1 Aug 2021 18:50:37 -0700 Subject: [PATCH 13/28] libbpf, doc: Eliminate warnings in libbpf_naming_convention Use "code-block: none" instead of "c" for non-C-language code blocks. Removes these warnings: lnx-514-rc4/Documentation/bpf/libbpf/libbpf_naming_convention.rst:111: WARNING: Could not lex literal_block as "c". Highlighting skipped. lnx-514-rc4/Documentation/bpf/libbpf/libbpf_naming_convention.rst:124: WARNING: Could not lex literal_block as "c". Highlighting skipped. Fixes: f42cfb469f9b ("bpf: Add documentation for libbpf including API autogen") Signed-off-by: Randy Dunlap Signed-off-by: Daniel Borkmann Link: https://lore.kernel.org/bpf/20210802015037.787-1-rdunlap@infradead.org --- docs/libbpf_naming_convention.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/libbpf_naming_convention.rst b/docs/libbpf_naming_convention.rst index 3de1d51..6bf9c5a 100644 --- a/docs/libbpf_naming_convention.rst +++ b/docs/libbpf_naming_convention.rst @@ -108,7 +108,7 @@ This bump in ABI version is at most once per kernel development cycle. For example, if current state of ``libbpf.map`` is: -.. code-block:: c +.. code-block:: none LIBBPF_0.0.1 { global: @@ -121,7 +121,7 @@ For example, if current state of ``libbpf.map`` is: , and a new symbol ``bpf_func_c`` is being introduced, then ``libbpf.map`` should be changed like this: -.. code-block:: c +.. code-block:: none LIBBPF_0.0.1 { global: From 0e7520949e5a9e92c10d8aacd5e2e0e7bcd87108 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Wed, 11 Aug 2021 17:38:19 -0700 Subject: [PATCH 14/28] libbpf: Support weak typed ksyms. Currently weak typeless ksyms have default value zero, when they don't exist in the kernel. However, weak typed ksyms are rejected by libbpf if they can not be resolved. This means that if a bpf object contains the declaration of a nonexistent weak typed ksym, it will be rejected even if there is no program that references the symbol. Nonexistent weak typed ksyms can also default to zero just like typeless ones. This allows programs that access weak typed ksyms to be accepted by verifier, if the accesses are guarded. For example, extern const int bpf_link_fops3 __ksym __weak; /* then in BPF program */ if (&bpf_link_fops3) { /* use bpf_link_fops3 */ } If actual use of nonexistent typed ksym is not guarded properly, verifier would see that register is not PTR_TO_BTF_ID and wouldn't allow to use it for direct memory reads or passing it to BPF helpers. Signed-off-by: Hao Luo Signed-off-by: Andrii Nakryiko Link: https://lore.kernel.org/bpf/20210812003819.2439037-1-haoluo@google.com --- src/libbpf.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/libbpf.c b/src/libbpf.c index cb106e8..ff3c0ee 100644 --- a/src/libbpf.c +++ b/src/libbpf.c @@ -5277,11 +5277,11 @@ bpf_object__relocate_data(struct bpf_object *obj, struct bpf_program *prog) } insn[1].imm = ext->kcfg.data_off; } else /* EXT_KSYM */ { - if (ext->ksym.type_id) { /* typed ksyms */ + if (ext->ksym.type_id && ext->is_set) { /* typed ksyms */ insn[0].src_reg = BPF_PSEUDO_BTF_ID; insn[0].imm = ext->ksym.kernel_btf_id; insn[1].imm = ext->ksym.kernel_btf_obj_fd; - } else { /* typeless ksyms */ + } else { /* typeless ksyms or unresolved typed ksyms */ insn[0].imm = (__u32)ext->ksym.addr; insn[1].imm = ext->ksym.addr >> 32; } @@ -6608,11 +6608,8 @@ static int find_ksym_btf_id(struct bpf_object *obj, const char *ksym_name, break; } } - if (id <= 0) { - pr_warn("extern (%s ksym) '%s': failed to find BTF ID in kernel BTF(s).\n", - __btf_kind_str(kind), ksym_name); + if (id <= 0) return -ESRCH; - } *res_btf = btf; *res_btf_fd = btf_fd; @@ -6629,8 +6626,13 @@ static int bpf_object__resolve_ksym_var_btf_id(struct bpf_object *obj, struct btf *btf = NULL; id = find_ksym_btf_id(obj, ext->name, BTF_KIND_VAR, &btf, &btf_fd); - if (id < 0) + if (id == -ESRCH && ext->is_weak) { + return 0; + } else if (id < 0) { + pr_warn("extern (var ksym) '%s': not found in kernel BTF\n", + ext->name); return id; + } /* find local type_id */ local_type_id = ext->ksym.type_id; From 152882e17a6e9e4a7d3b94034c71d9a5be29209d Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Sun, 15 Aug 2021 00:05:57 -0700 Subject: [PATCH 15/28] bpf: Implement minimal BPF perf link Introduce a new type of BPF link - BPF perf link. This brings perf_event-based BPF program attachments (perf_event, tracepoints, kprobes, and uprobes) into the common BPF link infrastructure, allowing to list all active perf_event based attachments, auto-detaching BPF program from perf_event when link's FD is closed, get generic BPF link fdinfo/get_info functionality. BPF_LINK_CREATE command expects perf_event's FD as target_fd. No extra flags are currently supported. Force-detaching and atomic BPF program updates are not yet implemented, but with perf_event-based BPF links we now have common framework for this without the need to extend ioctl()-based perf_event interface. One interesting consideration is a new value for bpf_attach_type, which BPF_LINK_CREATE command expects. Generally, it's either 1-to-1 mapping from bpf_attach_type to bpf_prog_type, or many-to-1 mapping from a subset of bpf_attach_types to one bpf_prog_type (e.g., see BPF_PROG_TYPE_SK_SKB or BPF_PROG_TYPE_CGROUP_SOCK). In this case, though, we have three different program types (KPROBE, TRACEPOINT, PERF_EVENT) using the same perf_event-based mechanism, so it's many bpf_prog_types to one bpf_attach_type. I chose to define a single BPF_PERF_EVENT attach type for all of them and adjust link_create()'s logic for checking correspondence between attach type and program type. The alternative would be to define three new attach types (e.g., BPF_KPROBE, BPF_TRACEPOINT, and BPF_PERF_EVENT), but that seemed like unnecessary overkill and BPF_KPROBE will cause naming conflicts with BPF_KPROBE() macro, defined by libbpf. I chose to not do this to avoid unnecessary proliferation of bpf_attach_type enum values and not have to deal with naming conflicts. Signed-off-by: Andrii Nakryiko Signed-off-by: Daniel Borkmann Acked-by: Yonghong Song Acked-by: Peter Zijlstra (Intel) Link: https://lore.kernel.org/bpf/20210815070609.987780-5-andrii@kernel.org --- include/uapi/linux/bpf.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 2db6925..94fe832 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -993,6 +993,7 @@ enum bpf_attach_type { BPF_SK_SKB_VERDICT, BPF_SK_REUSEPORT_SELECT, BPF_SK_REUSEPORT_SELECT_OR_MIGRATE, + BPF_PERF_EVENT, __MAX_BPF_ATTACH_TYPE }; @@ -1006,6 +1007,7 @@ enum bpf_link_type { BPF_LINK_TYPE_ITER = 4, BPF_LINK_TYPE_NETNS = 5, BPF_LINK_TYPE_XDP = 6, + BPF_LINK_TYPE_PERF_EVENT = 7, MAX_BPF_LINK_TYPE, }; From 7b22fc4cdb4a67aba1be90e42db8b0ebd5b40a02 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Sun, 15 Aug 2021 00:05:58 -0700 Subject: [PATCH 16/28] bpf: Allow to specify user-provided bpf_cookie for BPF perf links Add ability for users to specify custom u64 value (bpf_cookie) when creating BPF link for perf_event-backed BPF programs (kprobe/uprobe, perf_event, tracepoints). This is useful for cases when the same BPF program is used for attaching and processing invocation of different tracepoints/kprobes/uprobes in a generic fashion, but such that each invocation is distinguished from each other (e.g., BPF program can look up additional information associated with a specific kernel function without having to rely on function IP lookups). This enables new use cases to be implemented simply and efficiently that previously were possible only through code generation (and thus multiple instances of almost identical BPF program) or compilation at runtime (BCC-style) on target hosts (even more expensive resource-wise). For uprobes it is not even possible in some cases to know function IP before hand (e.g., when attaching to shared library without PID filtering, in which case base load address is not known for a library). This is done by storing u64 bpf_cookie in struct bpf_prog_array_item, corresponding to each attached and run BPF program. Given cgroup BPF programs already use two 8-byte pointers for their needs and cgroup BPF programs don't have (yet?) support for bpf_cookie, reuse that space through union of cgroup_storage and new bpf_cookie field. Make it available to kprobe/tracepoint BPF programs through bpf_trace_run_ctx. This is set by BPF_PROG_RUN_ARRAY, used by kprobe/uprobe/tracepoint BPF program execution code, which luckily is now also split from BPF_PROG_RUN_ARRAY_CG. This run context will be utilized by a new BPF helper giving access to this user-provided cookie value from inside a BPF program. Generic perf_event BPF programs will access this value from perf_event itself through passed in BPF program context. Signed-off-by: Andrii Nakryiko Signed-off-by: Daniel Borkmann Acked-by: Yonghong Song Acked-by: Peter Zijlstra (Intel) Link: https://lore.kernel.org/bpf/20210815070609.987780-6-andrii@kernel.org --- include/uapi/linux/bpf.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 94fe832..63ee482 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -1448,6 +1448,13 @@ union bpf_attr { __aligned_u64 iter_info; /* extra bpf_iter_link_info */ __u32 iter_info_len; /* iter_info length */ }; + struct { + /* black box user-provided value passed through + * to BPF program at the execution time and + * accessible through bpf_get_attach_cookie() BPF helper + */ + __u64 bpf_cookie; + } perf_event; }; } link_create; From 40160ed4d4b2587458ab3e6e965bb48bee5912cf Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Sun, 15 Aug 2021 00:05:59 -0700 Subject: [PATCH 17/28] bpf: Add bpf_get_attach_cookie() BPF helper to access bpf_cookie value Add new BPF helper, bpf_get_attach_cookie(), which can be used by BPF programs to get access to a user-provided bpf_cookie value, specified during BPF program attachment (BPF link creation) time. Naming is hard, though. With the concept being named "BPF cookie", I've considered calling the helper: - bpf_get_cookie() -- seems too unspecific and easily mistaken with socket cookie; - bpf_get_bpf_cookie() -- too much tautology; - bpf_get_link_cookie() -- would be ok, but while we create a BPF link to attach BPF program to BPF hook, it's still an "attachment" and the bpf_cookie is associated with BPF program attachment to a hook, not a BPF link itself. Technically, we could support bpf_cookie with old-style cgroup programs.So I ultimately rejected it in favor of bpf_get_attach_cookie(). Currently all perf_event-backed BPF program types support bpf_get_attach_cookie() helper. Follow-up patches will add support for fentry/fexit programs as well. While at it, mark bpf_tracing_func_proto() as static to make it obvious that it's only used from within the kernel/trace/bpf_trace.c. Signed-off-by: Andrii Nakryiko Signed-off-by: Daniel Borkmann Acked-by: Yonghong Song Link: https://lore.kernel.org/bpf/20210815070609.987780-7-andrii@kernel.org --- include/uapi/linux/bpf.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 63ee482..c4f7892 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -4856,6 +4856,21 @@ union bpf_attr { * Get address of the traced function (for tracing and kprobe programs). * Return * Address of the traced function. + * + * u64 bpf_get_attach_cookie(void *ctx) + * Description + * Get bpf_cookie value provided (optionally) during the program + * attachment. It might be different for each individual + * attachment, even if BPF program itself is the same. + * Expects BPF program context *ctx* as a first argument. + * + * Supported for the following program types: + * - kprobe/uprobe; + * - tracepoint; + * - perf_event. + * Return + * Value specified by user at BPF link creation/attachment time + * or 0, if it was not specified. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -5032,6 +5047,7 @@ union bpf_attr { FN(timer_start), \ FN(timer_cancel), \ FN(get_func_ip), \ + FN(get_attach_cookie), \ /* */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper From 9923f25600c0904129a0a5441b8debcb4c842cd7 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Sun, 15 Aug 2021 00:06:01 -0700 Subject: [PATCH 18/28] libbpf: Remove unused bpf_link's destroy operation, but add dealloc bpf_link->destroy() isn't used by any code, so remove it. Instead, add ability to override deallocation procedure, with default doing plain free(link). This is necessary for cases when we want to "subclass" struct bpf_link to keep extra information, as is the case in the next patch adding struct bpf_link_perf. Signed-off-by: Andrii Nakryiko Signed-off-by: Daniel Borkmann Link: https://lore.kernel.org/bpf/20210815070609.987780-9-andrii@kernel.org --- src/libbpf.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/libbpf.c b/src/libbpf.c index ff3c0ee..d30e328 100644 --- a/src/libbpf.c +++ b/src/libbpf.c @@ -8810,7 +8810,7 @@ int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr, struct bpf_link { int (*detach)(struct bpf_link *link); - int (*destroy)(struct bpf_link *link); + void (*dealloc)(struct bpf_link *link); char *pin_path; /* NULL, if not pinned */ int fd; /* hook FD, -1 if not applicable */ bool disconnected; @@ -8849,11 +8849,12 @@ int bpf_link__destroy(struct bpf_link *link) if (!link->disconnected && link->detach) err = link->detach(link); - if (link->destroy) - link->destroy(link); if (link->pin_path) free(link->pin_path); - free(link); + if (link->dealloc) + link->dealloc(link); + else + free(link); return libbpf_err(err); } From d23679b4152210264e75b0f33e4d8550bf9acb9a Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Sun, 15 Aug 2021 00:06:02 -0700 Subject: [PATCH 19/28] libbpf: Use BPF perf link when supported by kernel Detect kernel support for BPF perf link and prefer it when attaching to perf_event, tracepoint, kprobe/uprobe. Underlying perf_event FD will be kept open until BPF link is destroyed, at which point both perf_event FD and BPF link FD will be closed. This preserves current behavior in which perf_event FD is open for the duration of bpf_link's lifetime and user is able to "disconnect" bpf_link from underlying FD (with bpf_link__disconnect()), so that bpf_link__destroy() doesn't close underlying perf_event FD.When BPF perf link is used, disconnect will keep both perf_event and bpf_link FDs open, so it will be up to (advanced) user to close them. This approach is demonstrated in bpf_cookie.c selftests, added in this patch set. Signed-off-by: Andrii Nakryiko Signed-off-by: Daniel Borkmann Link: https://lore.kernel.org/bpf/20210815070609.987780-10-andrii@kernel.org --- src/libbpf.c | 113 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 91 insertions(+), 22 deletions(-) diff --git a/src/libbpf.c b/src/libbpf.c index d30e328..5dc15f5 100644 --- a/src/libbpf.c +++ b/src/libbpf.c @@ -193,6 +193,8 @@ enum kern_feature_id { FEAT_MODULE_BTF, /* BTF_KIND_FLOAT support */ FEAT_BTF_FLOAT, + /* BPF perf link support */ + FEAT_PERF_LINK, __FEAT_CNT, }; @@ -4337,6 +4339,37 @@ static int probe_module_btf(void) return !err; } +static int probe_perf_link(void) +{ + struct bpf_load_program_attr attr; + struct bpf_insn insns[] = { + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }; + int prog_fd, link_fd, err; + + memset(&attr, 0, sizeof(attr)); + attr.prog_type = BPF_PROG_TYPE_TRACEPOINT; + attr.insns = insns; + attr.insns_cnt = ARRAY_SIZE(insns); + attr.license = "GPL"; + prog_fd = bpf_load_program_xattr(&attr, NULL, 0); + if (prog_fd < 0) + return -errno; + + /* use invalid perf_event FD to get EBADF, if link is supported; + * otherwise EINVAL should be returned + */ + link_fd = bpf_link_create(prog_fd, -1, BPF_PERF_EVENT, NULL); + err = -errno; /* close() can clobber errno */ + + if (link_fd >= 0) + close(link_fd); + close(prog_fd); + + return link_fd < 0 && err == -EBADF; +} + enum kern_feature_result { FEAT_UNKNOWN = 0, FEAT_SUPPORTED = 1, @@ -4387,6 +4420,9 @@ static struct kern_feature_desc { [FEAT_BTF_FLOAT] = { "BTF_KIND_FLOAT support", probe_kern_btf_float, }, + [FEAT_PERF_LINK] = { + "BPF perf link support", probe_perf_link, + }, }; static bool kernel_supports(const struct bpf_object *obj, enum kern_feature_id feat_id) @@ -8951,23 +8987,38 @@ int bpf_link__unpin(struct bpf_link *link) return 0; } -static int bpf_link__detach_perf_event(struct bpf_link *link) -{ - int err; +struct bpf_link_perf { + struct bpf_link link; + int perf_event_fd; +}; - err = ioctl(link->fd, PERF_EVENT_IOC_DISABLE, 0); - if (err) +static int bpf_link_perf_detach(struct bpf_link *link) +{ + struct bpf_link_perf *perf_link = container_of(link, struct bpf_link_perf, link); + int err = 0; + + if (ioctl(perf_link->perf_event_fd, PERF_EVENT_IOC_DISABLE, 0) < 0) err = -errno; + if (perf_link->perf_event_fd != link->fd) + close(perf_link->perf_event_fd); close(link->fd); + return libbpf_err(err); } +static void bpf_link_perf_dealloc(struct bpf_link *link) +{ + struct bpf_link_perf *perf_link = container_of(link, struct bpf_link_perf, link); + + free(perf_link); +} + struct bpf_link *bpf_program__attach_perf_event(struct bpf_program *prog, int pfd) { char errmsg[STRERR_BUFSIZE]; - struct bpf_link *link; - int prog_fd, err; + struct bpf_link_perf *link; + int prog_fd, link_fd = -1, err; if (pfd < 0) { pr_warn("prog '%s': invalid perf event FD %d\n", @@ -8984,27 +9035,45 @@ struct bpf_link *bpf_program__attach_perf_event(struct bpf_program *prog, int pf link = calloc(1, sizeof(*link)); if (!link) return libbpf_err_ptr(-ENOMEM); - link->detach = &bpf_link__detach_perf_event; - link->fd = pfd; + link->link.detach = &bpf_link_perf_detach; + link->link.dealloc = &bpf_link_perf_dealloc; + link->perf_event_fd = pfd; - if (ioctl(pfd, PERF_EVENT_IOC_SET_BPF, prog_fd) < 0) { - err = -errno; - free(link); - pr_warn("prog '%s': failed to attach to pfd %d: %s\n", - prog->name, pfd, libbpf_strerror_r(err, errmsg, sizeof(errmsg))); - if (err == -EPROTO) - pr_warn("prog '%s': try add PERF_SAMPLE_CALLCHAIN to or remove exclude_callchain_[kernel|user] from pfd %d\n", - prog->name, pfd); - return libbpf_err_ptr(err); + if (kernel_supports(prog->obj, FEAT_PERF_LINK)) { + link_fd = bpf_link_create(prog_fd, pfd, BPF_PERF_EVENT, NULL); + if (link_fd < 0) { + err = -errno; + pr_warn("prog '%s': failed to create BPF link for perf_event FD %d: %d (%s)\n", + prog->name, pfd, + err, libbpf_strerror_r(err, errmsg, sizeof(errmsg))); + goto err_out; + } + link->link.fd = link_fd; + } else { + if (ioctl(pfd, PERF_EVENT_IOC_SET_BPF, prog_fd) < 0) { + err = -errno; + pr_warn("prog '%s': failed to attach to perf_event FD %d: %s\n", + prog->name, pfd, libbpf_strerror_r(err, errmsg, sizeof(errmsg))); + if (err == -EPROTO) + pr_warn("prog '%s': try add PERF_SAMPLE_CALLCHAIN to or remove exclude_callchain_[kernel|user] from pfd %d\n", + prog->name, pfd); + goto err_out; + } + link->link.fd = pfd; } if (ioctl(pfd, PERF_EVENT_IOC_ENABLE, 0) < 0) { err = -errno; - free(link); - pr_warn("prog '%s': failed to enable pfd %d: %s\n", + pr_warn("prog '%s': failed to enable perf_event FD %d: %s\n", prog->name, pfd, libbpf_strerror_r(err, errmsg, sizeof(errmsg))); - return libbpf_err_ptr(err); + goto err_out; } - return link; + + return &link->link; +err_out: + if (link_fd >= 0) + close(link_fd); + free(link); + return libbpf_err_ptr(err); } /* From a3f8c5a3063314b746f67ee746c052f57a23e84f Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Sun, 15 Aug 2021 00:06:03 -0700 Subject: [PATCH 20/28] libbpf: Add bpf_cookie support to bpf_link_create() API Add ability to specify bpf_cookie value when creating BPF perf link with bpf_link_create() low-level API. Given BPF_LINK_CREATE command is growing and keeps getting new fields that are specific to the type of BPF_LINK, extend libbpf side of bpf_link_create() API and corresponding OPTS struct to accomodate such changes. Add extra checks to prevent using incompatible/unexpected combinations of fields. Signed-off-by: Andrii Nakryiko Signed-off-by: Daniel Borkmann Link: https://lore.kernel.org/bpf/20210815070609.987780-11-andrii@kernel.org --- src/bpf.c | 32 +++++++++++++++++++++++++------- src/bpf.h | 8 +++++++- src/libbpf_internal.h | 32 ++++++++++++++++++++++---------- 3 files changed, 54 insertions(+), 18 deletions(-) diff --git a/src/bpf.c b/src/bpf.c index 86dcac4..2401fad 100644 --- a/src/bpf.c +++ b/src/bpf.c @@ -684,8 +684,13 @@ int bpf_link_create(int prog_fd, int target_fd, iter_info_len = OPTS_GET(opts, iter_info_len, 0); target_btf_id = OPTS_GET(opts, target_btf_id, 0); - if (iter_info_len && target_btf_id) - return libbpf_err(-EINVAL); + /* validate we don't have unexpected combinations of non-zero fields */ + if (iter_info_len || target_btf_id) { + if (iter_info_len && target_btf_id) + return libbpf_err(-EINVAL); + if (!OPTS_ZEROED(opts, target_btf_id)) + return libbpf_err(-EINVAL); + } memset(&attr, 0, sizeof(attr)); attr.link_create.prog_fd = prog_fd; @@ -693,14 +698,27 @@ int bpf_link_create(int prog_fd, int target_fd, attr.link_create.attach_type = attach_type; attr.link_create.flags = OPTS_GET(opts, flags, 0); - if (iter_info_len) { - attr.link_create.iter_info = - ptr_to_u64(OPTS_GET(opts, iter_info, (void *)0)); - attr.link_create.iter_info_len = iter_info_len; - } else if (target_btf_id) { + if (target_btf_id) { attr.link_create.target_btf_id = target_btf_id; + goto proceed; } + switch (attach_type) { + case BPF_TRACE_ITER: + attr.link_create.iter_info = ptr_to_u64(OPTS_GET(opts, iter_info, (void *)0)); + attr.link_create.iter_info_len = iter_info_len; + break; + case BPF_PERF_EVENT: + attr.link_create.perf_event.bpf_cookie = OPTS_GET(opts, perf_event.bpf_cookie, 0); + if (!OPTS_ZEROED(opts, perf_event)) + return libbpf_err(-EINVAL); + break; + default: + if (!OPTS_ZEROED(opts, flags)) + return libbpf_err(-EINVAL); + break; + } +proceed: fd = sys_bpf(BPF_LINK_CREATE, &attr, sizeof(attr)); return libbpf_err_errno(fd); } diff --git a/src/bpf.h b/src/bpf.h index 4f758f8..6fffb3c 100644 --- a/src/bpf.h +++ b/src/bpf.h @@ -177,8 +177,14 @@ struct bpf_link_create_opts { union bpf_iter_link_info *iter_info; __u32 iter_info_len; __u32 target_btf_id; + union { + struct { + __u64 bpf_cookie; + } perf_event; + }; + size_t :0; }; -#define bpf_link_create_opts__last_field target_btf_id +#define bpf_link_create_opts__last_field perf_event LIBBPF_API int bpf_link_create(int prog_fd, int target_fd, enum bpf_attach_type attach_type, diff --git a/src/libbpf_internal.h b/src/libbpf_internal.h index f7b691d..533b021 100644 --- a/src/libbpf_internal.h +++ b/src/libbpf_internal.h @@ -196,6 +196,17 @@ void *libbpf_add_mem(void **data, size_t *cap_cnt, size_t elem_sz, size_t cur_cnt, size_t max_cnt, size_t add_cnt); int libbpf_ensure_mem(void **data, size_t *cap_cnt, size_t elem_sz, size_t need_cnt); +static inline bool libbpf_is_mem_zeroed(const char *p, ssize_t len) +{ + while (len > 0) { + if (*p) + return false; + p++; + len--; + } + return true; +} + static inline bool libbpf_validate_opts(const char *opts, size_t opts_sz, size_t user_sz, const char *type_name) @@ -204,16 +215,9 @@ static inline bool libbpf_validate_opts(const char *opts, pr_warn("%s size (%zu) is too small\n", type_name, user_sz); return false; } - if (user_sz > opts_sz) { - size_t i; - - for (i = opts_sz; i < user_sz; i++) { - if (opts[i]) { - pr_warn("%s has non-zero extra bytes\n", - type_name); - return false; - } - } + if (!libbpf_is_mem_zeroed(opts + opts_sz, (ssize_t)user_sz - opts_sz)) { + pr_warn("%s has non-zero extra bytes\n", type_name); + return false; } return true; } @@ -233,6 +237,14 @@ static inline bool libbpf_validate_opts(const char *opts, (opts)->field = value; \ } while (0) +#define OPTS_ZEROED(opts, last_nonzero_field) \ +({ \ + ssize_t __off = offsetofend(typeof(*(opts)), last_nonzero_field); \ + !(opts) || libbpf_is_mem_zeroed((const void *)opts + __off, \ + (opts)->sz - __off); \ +}) + + int parse_cpu_mask_str(const char *s, bool **mask, int *mask_sz); int parse_cpu_mask_file(const char *fcpu, bool **mask, int *mask_sz); int libbpf__load_raw_btf(const char *raw_types, size_t types_len, From 91259bc676ae64bb376cff666055d09640773737 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Sun, 15 Aug 2021 00:06:04 -0700 Subject: [PATCH 21/28] libbpf: Add bpf_cookie to perf_event, kprobe, uprobe, and tp attach APIs Wire through bpf_cookie for all attach APIs that use perf_event_open under the hood: - for kprobes, extend existing bpf_kprobe_opts with bpf_cookie field; - for perf_event, uprobe, and tracepoint APIs, add their _opts variants and pass bpf_cookie through opts. For kernel that don't support BPF_LINK_CREATE for perf_events, and thus bpf_cookie is not supported either, return error and log warning for user. Signed-off-by: Andrii Nakryiko Signed-off-by: Daniel Borkmann Link: https://lore.kernel.org/bpf/20210815070609.987780-12-andrii@kernel.org --- src/libbpf.c | 78 +++++++++++++++++++++++++++++++++++++++++--------- src/libbpf.h | 71 +++++++++++++++++++++++++++++++++++++-------- src/libbpf.map | 3 ++ 3 files changed, 127 insertions(+), 25 deletions(-) diff --git a/src/libbpf.c b/src/libbpf.c index 5dc15f5..62ce878 100644 --- a/src/libbpf.c +++ b/src/libbpf.c @@ -9014,12 +9014,16 @@ static void bpf_link_perf_dealloc(struct bpf_link *link) free(perf_link); } -struct bpf_link *bpf_program__attach_perf_event(struct bpf_program *prog, int pfd) +struct bpf_link *bpf_program__attach_perf_event_opts(struct bpf_program *prog, int pfd, + const struct bpf_perf_event_opts *opts) { char errmsg[STRERR_BUFSIZE]; struct bpf_link_perf *link; int prog_fd, link_fd = -1, err; + if (!OPTS_VALID(opts, bpf_perf_event_opts)) + return libbpf_err_ptr(-EINVAL); + if (pfd < 0) { pr_warn("prog '%s': invalid perf event FD %d\n", prog->name, pfd); @@ -9040,7 +9044,10 @@ struct bpf_link *bpf_program__attach_perf_event(struct bpf_program *prog, int pf link->perf_event_fd = pfd; if (kernel_supports(prog->obj, FEAT_PERF_LINK)) { - link_fd = bpf_link_create(prog_fd, pfd, BPF_PERF_EVENT, NULL); + DECLARE_LIBBPF_OPTS(bpf_link_create_opts, link_opts, + .perf_event.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0)); + + link_fd = bpf_link_create(prog_fd, pfd, BPF_PERF_EVENT, &link_opts); if (link_fd < 0) { err = -errno; pr_warn("prog '%s': failed to create BPF link for perf_event FD %d: %d (%s)\n", @@ -9050,6 +9057,12 @@ struct bpf_link *bpf_program__attach_perf_event(struct bpf_program *prog, int pf } link->link.fd = link_fd; } else { + if (OPTS_GET(opts, bpf_cookie, 0)) { + pr_warn("prog '%s': user context value is not supported\n", prog->name); + err = -EOPNOTSUPP; + goto err_out; + } + if (ioctl(pfd, PERF_EVENT_IOC_SET_BPF, prog_fd) < 0) { err = -errno; pr_warn("prog '%s': failed to attach to perf_event FD %d: %s\n", @@ -9076,6 +9089,11 @@ err_out: return libbpf_err_ptr(err); } +struct bpf_link *bpf_program__attach_perf_event(struct bpf_program *prog, int pfd) +{ + return bpf_program__attach_perf_event_opts(prog, pfd, NULL); +} + /* * this function is expected to parse integer in the range of [0, 2^31-1] from * given file using scanf format string fmt. If actual parsed value is @@ -9184,8 +9202,9 @@ static int perf_event_open_probe(bool uprobe, bool retprobe, const char *name, struct bpf_link * bpf_program__attach_kprobe_opts(struct bpf_program *prog, const char *func_name, - struct bpf_kprobe_opts *opts) + const struct bpf_kprobe_opts *opts) { + DECLARE_LIBBPF_OPTS(bpf_perf_event_opts, pe_opts); char errmsg[STRERR_BUFSIZE]; struct bpf_link *link; unsigned long offset; @@ -9197,6 +9216,7 @@ bpf_program__attach_kprobe_opts(struct bpf_program *prog, retprobe = OPTS_GET(opts, retprobe, false); offset = OPTS_GET(opts, offset, 0); + pe_opts.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0); pfd = perf_event_open_probe(false /* uprobe */, retprobe, func_name, offset, -1 /* pid */); @@ -9206,7 +9226,7 @@ bpf_program__attach_kprobe_opts(struct bpf_program *prog, libbpf_strerror_r(pfd, errmsg, sizeof(errmsg))); return libbpf_err_ptr(pfd); } - link = bpf_program__attach_perf_event(prog, pfd); + link = bpf_program__attach_perf_event_opts(prog, pfd, &pe_opts); err = libbpf_get_error(link); if (err) { close(pfd); @@ -9261,14 +9281,22 @@ static struct bpf_link *attach_kprobe(const struct bpf_sec_def *sec, return link; } -struct bpf_link *bpf_program__attach_uprobe(struct bpf_program *prog, - bool retprobe, pid_t pid, - const char *binary_path, - size_t func_offset) +LIBBPF_API struct bpf_link * +bpf_program__attach_uprobe_opts(struct bpf_program *prog, pid_t pid, + const char *binary_path, size_t func_offset, + const struct bpf_uprobe_opts *opts) { + DECLARE_LIBBPF_OPTS(bpf_perf_event_opts, pe_opts); char errmsg[STRERR_BUFSIZE]; struct bpf_link *link; int pfd, err; + bool retprobe; + + if (!OPTS_VALID(opts, bpf_uprobe_opts)) + return libbpf_err_ptr(-EINVAL); + + retprobe = OPTS_GET(opts, retprobe, false); + pe_opts.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0); pfd = perf_event_open_probe(true /* uprobe */, retprobe, binary_path, func_offset, pid); @@ -9279,7 +9307,7 @@ struct bpf_link *bpf_program__attach_uprobe(struct bpf_program *prog, libbpf_strerror_r(pfd, errmsg, sizeof(errmsg))); return libbpf_err_ptr(pfd); } - link = bpf_program__attach_perf_event(prog, pfd); + link = bpf_program__attach_perf_event_opts(prog, pfd, &pe_opts); err = libbpf_get_error(link); if (err) { close(pfd); @@ -9292,6 +9320,16 @@ struct bpf_link *bpf_program__attach_uprobe(struct bpf_program *prog, return link; } +struct bpf_link *bpf_program__attach_uprobe(struct bpf_program *prog, + bool retprobe, pid_t pid, + const char *binary_path, + size_t func_offset) +{ + DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, opts, .retprobe = retprobe); + + return bpf_program__attach_uprobe_opts(prog, pid, binary_path, func_offset, &opts); +} + static int determine_tracepoint_id(const char *tp_category, const char *tp_name) { @@ -9342,14 +9380,21 @@ static int perf_event_open_tracepoint(const char *tp_category, return pfd; } -struct bpf_link *bpf_program__attach_tracepoint(struct bpf_program *prog, - const char *tp_category, - const char *tp_name) +struct bpf_link *bpf_program__attach_tracepoint_opts(struct bpf_program *prog, + const char *tp_category, + const char *tp_name, + const struct bpf_tracepoint_opts *opts) { + DECLARE_LIBBPF_OPTS(bpf_perf_event_opts, pe_opts); char errmsg[STRERR_BUFSIZE]; struct bpf_link *link; int pfd, err; + if (!OPTS_VALID(opts, bpf_tracepoint_opts)) + return libbpf_err_ptr(-EINVAL); + + pe_opts.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0); + pfd = perf_event_open_tracepoint(tp_category, tp_name); if (pfd < 0) { pr_warn("prog '%s': failed to create tracepoint '%s/%s' perf event: %s\n", @@ -9357,7 +9402,7 @@ struct bpf_link *bpf_program__attach_tracepoint(struct bpf_program *prog, libbpf_strerror_r(pfd, errmsg, sizeof(errmsg))); return libbpf_err_ptr(pfd); } - link = bpf_program__attach_perf_event(prog, pfd); + link = bpf_program__attach_perf_event_opts(prog, pfd, &pe_opts); err = libbpf_get_error(link); if (err) { close(pfd); @@ -9369,6 +9414,13 @@ struct bpf_link *bpf_program__attach_tracepoint(struct bpf_program *prog, return link; } +struct bpf_link *bpf_program__attach_tracepoint(struct bpf_program *prog, + const char *tp_category, + const char *tp_name) +{ + return bpf_program__attach_tracepoint_opts(prog, tp_category, tp_name, NULL); +} + static struct bpf_link *attach_tp(const struct bpf_sec_def *sec, struct bpf_program *prog) { diff --git a/src/libbpf.h b/src/libbpf.h index 1271d99..1f4a672 100644 --- a/src/libbpf.h +++ b/src/libbpf.h @@ -104,17 +104,6 @@ struct bpf_object_open_opts { }; #define bpf_object_open_opts__last_field btf_custom_path -struct bpf_kprobe_opts { - /* size of this struct, for forward/backward compatiblity */ - size_t sz; - /* function's offset to install kprobe to */ - unsigned long offset; - /* kprobe is return probe */ - bool retprobe; - size_t :0; -}; -#define bpf_kprobe_opts__last_field retprobe - LIBBPF_API struct bpf_object *bpf_object__open(const char *path); LIBBPF_API struct bpf_object * bpf_object__open_file(const char *path, const struct bpf_object_open_opts *opts); @@ -255,24 +244,82 @@ LIBBPF_API int bpf_link__destroy(struct bpf_link *link); LIBBPF_API struct bpf_link * bpf_program__attach(struct bpf_program *prog); + +struct bpf_perf_event_opts { + /* size of this struct, for forward/backward compatiblity */ + size_t sz; + /* custom user-provided value fetchable through bpf_get_attach_cookie() */ + __u64 bpf_cookie; +}; +#define bpf_perf_event_opts__last_field bpf_cookie + LIBBPF_API struct bpf_link * bpf_program__attach_perf_event(struct bpf_program *prog, int pfd); + +LIBBPF_API struct bpf_link * +bpf_program__attach_perf_event_opts(struct bpf_program *prog, int pfd, + const struct bpf_perf_event_opts *opts); + +struct bpf_kprobe_opts { + /* size of this struct, for forward/backward compatiblity */ + size_t sz; + /* custom user-provided value fetchable through bpf_get_attach_cookie() */ + __u64 bpf_cookie; + /* function's offset to install kprobe to */ + unsigned long offset; + /* kprobe is return probe */ + bool retprobe; + size_t :0; +}; +#define bpf_kprobe_opts__last_field retprobe + LIBBPF_API struct bpf_link * bpf_program__attach_kprobe(struct bpf_program *prog, bool retprobe, const char *func_name); LIBBPF_API struct bpf_link * bpf_program__attach_kprobe_opts(struct bpf_program *prog, const char *func_name, - struct bpf_kprobe_opts *opts); + const struct bpf_kprobe_opts *opts); + +struct bpf_uprobe_opts { + /* size of this struct, for forward/backward compatiblity */ + size_t sz; + /* custom user-provided value fetchable through bpf_get_attach_cookie() */ + __u64 bpf_cookie; + /* uprobe is return probe, invoked at function return time */ + bool retprobe; + size_t :0; +}; +#define bpf_uprobe_opts__last_field retprobe + LIBBPF_API struct bpf_link * bpf_program__attach_uprobe(struct bpf_program *prog, bool retprobe, pid_t pid, const char *binary_path, size_t func_offset); +LIBBPF_API struct bpf_link * +bpf_program__attach_uprobe_opts(struct bpf_program *prog, pid_t pid, + const char *binary_path, size_t func_offset, + const struct bpf_uprobe_opts *opts); + +struct bpf_tracepoint_opts { + /* size of this struct, for forward/backward compatiblity */ + size_t sz; + /* custom user-provided value fetchable through bpf_get_attach_cookie() */ + __u64 bpf_cookie; +}; +#define bpf_tracepoint_opts__last_field bpf_cookie + LIBBPF_API struct bpf_link * bpf_program__attach_tracepoint(struct bpf_program *prog, const char *tp_category, const char *tp_name); LIBBPF_API struct bpf_link * +bpf_program__attach_tracepoint_opts(struct bpf_program *prog, + const char *tp_category, + const char *tp_name, + const struct bpf_tracepoint_opts *opts); + +LIBBPF_API struct bpf_link * bpf_program__attach_raw_tracepoint(struct bpf_program *prog, const char *tp_name); LIBBPF_API struct bpf_link * diff --git a/src/libbpf.map b/src/libbpf.map index 58e0fb2..bbc53bb 100644 --- a/src/libbpf.map +++ b/src/libbpf.map @@ -374,6 +374,9 @@ LIBBPF_0.5.0 { bpf_map__pin_path; bpf_map_lookup_and_delete_elem_flags; bpf_program__attach_kprobe_opts; + bpf_program__attach_perf_event_opts; + bpf_program__attach_tracepoint_opts; + bpf_program__attach_uprobe_opts; bpf_object__gen_loader; btf__load_from_kernel_by_id; btf__load_from_kernel_by_id_split; From 6d67d5314399822be224da81858c786526435c63 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Sun, 15 Aug 2021 00:06:08 -0700 Subject: [PATCH 22/28] libbpf: Add uprobe ref counter offset support for USDT semaphores When attaching to uprobes through perf subsystem, it's possible to specify offset of a so-called USDT semaphore, which is just a reference counted u16, used by kernel to keep track of how many tracers are attached to a given location. Support for this feature was added in [0], so just wire this through uprobe_opts. This is important to enable implementing USDT attachment and tracing through libbpf's bpf_program__attach_uprobe_opts() API. [0] a6ca88b241d5 ("trace_uprobe: support reference counter in fd-based uprobe") Signed-off-by: Andrii Nakryiko Signed-off-by: Daniel Borkmann Link: https://lore.kernel.org/bpf/20210815070609.987780-16-andrii@kernel.org --- src/libbpf.c | 17 +++++++++++++---- src/libbpf.h | 4 ++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/libbpf.c b/src/libbpf.c index 62ce878..88d8825 100644 --- a/src/libbpf.c +++ b/src/libbpf.c @@ -9152,13 +9152,19 @@ static int determine_uprobe_retprobe_bit(void) return parse_uint_from_file(file, "config:%d\n"); } +#define PERF_UPROBE_REF_CTR_OFFSET_BITS 32 +#define PERF_UPROBE_REF_CTR_OFFSET_SHIFT 32 + static int perf_event_open_probe(bool uprobe, bool retprobe, const char *name, - uint64_t offset, int pid) + uint64_t offset, int pid, size_t ref_ctr_off) { struct perf_event_attr attr = {}; char errmsg[STRERR_BUFSIZE]; int type, pfd, err; + if (ref_ctr_off >= (1ULL << PERF_UPROBE_REF_CTR_OFFSET_BITS)) + return -EINVAL; + type = uprobe ? determine_uprobe_perf_type() : determine_kprobe_perf_type(); if (type < 0) { @@ -9181,6 +9187,7 @@ static int perf_event_open_probe(bool uprobe, bool retprobe, const char *name, } attr.size = sizeof(attr); attr.type = type; + attr.config |= (__u64)ref_ctr_off << PERF_UPROBE_REF_CTR_OFFSET_SHIFT; attr.config1 = ptr_to_u64(name); /* kprobe_func or uprobe_path */ attr.config2 = offset; /* kprobe_addr or probe_offset */ @@ -9219,7 +9226,7 @@ bpf_program__attach_kprobe_opts(struct bpf_program *prog, pe_opts.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0); pfd = perf_event_open_probe(false /* uprobe */, retprobe, func_name, - offset, -1 /* pid */); + offset, -1 /* pid */, 0 /* ref_ctr_off */); if (pfd < 0) { pr_warn("prog '%s': failed to create %s '%s' perf event: %s\n", prog->name, retprobe ? "kretprobe" : "kprobe", func_name, @@ -9289,6 +9296,7 @@ bpf_program__attach_uprobe_opts(struct bpf_program *prog, pid_t pid, DECLARE_LIBBPF_OPTS(bpf_perf_event_opts, pe_opts); char errmsg[STRERR_BUFSIZE]; struct bpf_link *link; + size_t ref_ctr_off; int pfd, err; bool retprobe; @@ -9296,10 +9304,11 @@ bpf_program__attach_uprobe_opts(struct bpf_program *prog, pid_t pid, return libbpf_err_ptr(-EINVAL); retprobe = OPTS_GET(opts, retprobe, false); + ref_ctr_off = OPTS_GET(opts, ref_ctr_offset, 0); pe_opts.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0); - pfd = perf_event_open_probe(true /* uprobe */, retprobe, - binary_path, func_offset, pid); + pfd = perf_event_open_probe(true /* uprobe */, retprobe, binary_path, + func_offset, pid, ref_ctr_off); if (pfd < 0) { pr_warn("prog '%s': failed to create %s '%s:0x%zx' perf event: %s\n", prog->name, retprobe ? "uretprobe" : "uprobe", diff --git a/src/libbpf.h b/src/libbpf.h index 1f4a672..f177d89 100644 --- a/src/libbpf.h +++ b/src/libbpf.h @@ -284,6 +284,10 @@ bpf_program__attach_kprobe_opts(struct bpf_program *prog, struct bpf_uprobe_opts { /* size of this struct, for forward/backward compatiblity */ size_t sz; + /* offset of kernel reference counted USDT semaphore, added in + * a6ca88b241d5 ("trace_uprobe: support reference counter in fd-based uprobe") + */ + size_t ref_ctr_offset; /* custom user-provided value fetchable through bpf_get_attach_cookie() */ __u64 bpf_cookie; /* uprobe is return probe, invoked at function return time */ From a69c52bb11158bcdff89c1b034111e61eb737c9d Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Mon, 16 Aug 2021 22:41:57 -0700 Subject: [PATCH 23/28] sync: auto-generate latest BPF helpers Latest changes to BPF helper definitions. --- src/bpf_helper_defs.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/bpf_helper_defs.h b/src/bpf_helper_defs.h index 238f7f7..3e44468 100644 --- a/src/bpf_helper_defs.h +++ b/src/bpf_helper_defs.h @@ -4014,4 +4014,23 @@ static long (*bpf_timer_cancel)(struct bpf_timer *timer) = (void *) 172; */ static __u64 (*bpf_get_func_ip)(void *ctx) = (void *) 173; +/* + * bpf_get_attach_cookie + * + * Get bpf_cookie value provided (optionally) during the program + * attachment. It might be different for each individual + * attachment, even if BPF program itself is the same. + * Expects BPF program context *ctx* as a first argument. + * + * Supported for the following program types: + * - kprobe/uprobe; + * - tracepoint; + * - perf_event. + * + * Returns + * Value specified by user at BPF link creation/attachment time + * or 0, if it was not specified. + */ +static __u64 (*bpf_get_attach_cookie)(void *ctx) = (void *) 174; + From 7c6d34a2c94b972bf1ed8f68e03fe1135d7efe38 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Mon, 16 Aug 2021 22:41:57 -0700 Subject: [PATCH 24/28] sync: latest libbpf changes from kernel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Syncing latest libbpf commits from kernel repository. Baseline bpf-next commit: 372642ea83ff1c71a5d567a704c912359eb59776 Checkpoint bpf-next commit: 3c3bd542ffbb2ac09631313ede46ae66660ae550 Baseline bpf commit: 7c4a22339e7ce7b6ed473a8e682da622c3a774ee Checkpoint bpf commit: 3776f3517ed94d40ff0e3851d7ce2ce17b63099f Andrii Nakryiko (8): bpf: Implement minimal BPF perf link bpf: Allow to specify user-provided bpf_cookie for BPF perf links bpf: Add bpf_get_attach_cookie() BPF helper to access bpf_cookie value libbpf: Remove unused bpf_link's destroy operation, but add dealloc libbpf: Use BPF perf link when supported by kernel libbpf: Add bpf_cookie support to bpf_link_create() API libbpf: Add bpf_cookie to perf_event, kprobe, uprobe, and tp attach APIs libbpf: Add uprobe ref counter offset support for USDT semaphores Hangbin Liu (1): bonding: add new option lacp_active Hao Luo (1): libbpf: Support weak typed ksyms. Randy Dunlap (1): libbpf, doc: Eliminate warnings in libbpf_naming_convention Robin Gögge (1): libbpf: Fix probe for BPF_PROG_TYPE_CGROUP_SOCKOPT grantseltzer (1): bpf: Reconfigure libbpf docs to remove unversioned API docs/libbpf_api.rst | 27 ---- docs/libbpf_naming_convention.rst | 4 +- include/uapi/linux/bpf.h | 25 ++++ include/uapi/linux/if_link.h | 1 + src/bpf.c | 32 ++++- src/bpf.h | 8 +- src/libbpf.c | 229 +++++++++++++++++++++++------- src/libbpf.h | 75 ++++++++-- src/libbpf.map | 3 + src/libbpf_internal.h | 32 +++-- src/libbpf_probes.c | 4 +- 11 files changed, 332 insertions(+), 108 deletions(-) delete mode 100644 docs/libbpf_api.rst -- 2.30.2 --- BPF-CHECKPOINT-COMMIT | 2 +- CHECKPOINT-COMMIT | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/BPF-CHECKPOINT-COMMIT b/BPF-CHECKPOINT-COMMIT index 93b676d..e49628c 100644 --- a/BPF-CHECKPOINT-COMMIT +++ b/BPF-CHECKPOINT-COMMIT @@ -1 +1 @@ -7c4a22339e7ce7b6ed473a8e682da622c3a774ee +3776f3517ed94d40ff0e3851d7ce2ce17b63099f diff --git a/CHECKPOINT-COMMIT b/CHECKPOINT-COMMIT index 74ab33c..dcc3aa1 100644 --- a/CHECKPOINT-COMMIT +++ b/CHECKPOINT-COMMIT @@ -1 +1 @@ -372642ea83ff1c71a5d567a704c912359eb59776 +3c3bd542ffbb2ac09631313ede46ae66660ae550 From a3c0cc19d4b93cb0b7088c5604b0cec1c6863fde Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Tue, 17 Aug 2021 00:34:45 -0700 Subject: [PATCH 25/28] ci: blacklist new selftests on 5.5 Blacklist bpf_cookie, perf_link, and xdp_bonding selftests on 5.5 kernel. Signed-off-by: Andrii Nakryiko --- travis-ci/vmtest/configs/blacklist/BLACKLIST-5.5.0 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/travis-ci/vmtest/configs/blacklist/BLACKLIST-5.5.0 b/travis-ci/vmtest/configs/blacklist/BLACKLIST-5.5.0 index 0b774ea..cdd3dc3 100644 --- a/travis-ci/vmtest/configs/blacklist/BLACKLIST-5.5.0 +++ b/travis-ci/vmtest/configs/blacklist/BLACKLIST-5.5.0 @@ -3,6 +3,7 @@ align # verifier output format changed atomics # new atomic operations (v5.12+) atomic_bounds # new atomic operations (v5.12+) bind_perm # changed semantics of return values (v5.12+) +bpf_cookie # 5.15+ bpf_iter # bpf_iter support is missing bpf_obj_id # bpf_link support missing for GET_OBJ_INFO, GET_FD_BY_ID, etc bpf_tcp_ca # STRUCT_OPS is missing @@ -47,6 +48,7 @@ netcnt ns_current_pid_tgid # bpf_get_ns_current_pid_tgid() helper is missing pe_preserve_elems # v5.10+ perf_branches # bpf_read_branch_records() helper is missing +perf_link # v5.15+ pkt_access # 32-bit pointer arith in test_pkt_access probe_read_user_str # kernel bug with garbage bytes at the end prog_run_xattr # 32-bit pointer arith in test_pkt_access @@ -97,6 +99,7 @@ varlen # verifier bug fixed in later kernels vmlinux # hrtimer_nanosleep() signature changed incompatibly xdp_adjust_tail # new XDP functionality added in 5.8 xdp_attach # IFLA_XDP_EXPECTED_FD support is missing +xdp_bonding # v5.15+ xdp_bpf2bpf # freplace is missing xdp_context_test_run # v5.15+ xdp_cpumap_attach # v5.9+ From 7d9cc837ef9726e054cd97310ef6b79198875448 Mon Sep 17 00:00:00 2001 From: grantseltzer Date: Wed, 18 Aug 2021 11:19:17 -0400 Subject: [PATCH 26/28] Fix path to Doxygen source code input Signed-off-by: Grant Seltzer --- docs/sphinx/doxygen/Doxyfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sphinx/doxygen/Doxyfile b/docs/sphinx/doxygen/Doxyfile index 502d335..b04c115 100644 --- a/docs/sphinx/doxygen/Doxyfile +++ b/docs/sphinx/doxygen/Doxyfile @@ -93,7 +93,7 @@ WARN_NO_PARAMDOC = NO WARN_AS_ERROR = NO WARN_FORMAT = "$file:$line: $text" WARN_LOGFILE = -INPUT = ../../src +INPUT = ../../../src INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.c \ *.h From d0c398be4f08645b4f2b5d99f7531c9000841250 Mon Sep 17 00:00:00 2001 From: Grant Seltzer Date: Wed, 18 Aug 2021 11:13:13 -0400 Subject: [PATCH 27/28] libbpf: Rename libbpf documentation index file This patch renames a documentation libbpf.rst to index.rst. In order for readthedocs.org to pick this file up and properly build the documentation site. It also changes the title type of the ABI subsection in the naming convention doc. This is so that readthedocs.org doesn't treat this section as a separate document. Signed-off-by: Grant Seltzer Signed-off-by: Andrii Nakryiko Link: https://lore.kernel.org/bpf/20210818151313.49992-1-grantseltzer@gmail.com --- docs/{libbpf.rst => index.rst} | 8 ++++++++ docs/libbpf_naming_convention.rst | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) rename docs/{libbpf.rst => index.rst} (75%) diff --git a/docs/libbpf.rst b/docs/index.rst similarity index 75% rename from docs/libbpf.rst rename to docs/index.rst index 1b1e61d..4f8adfc 100644 --- a/docs/libbpf.rst +++ b/docs/index.rst @@ -3,6 +3,14 @@ libbpf ====== +For API documentation see the `versioned API documentation site `_. + +.. toctree:: + :maxdepth: 1 + + libbpf_naming_convention + libbpf_build + This is documentation for libbpf, a userspace library for loading and interacting with bpf programs. diff --git a/docs/libbpf_naming_convention.rst b/docs/libbpf_naming_convention.rst index 6bf9c5a..9c68d50 100644 --- a/docs/libbpf_naming_convention.rst +++ b/docs/libbpf_naming_convention.rst @@ -69,7 +69,7 @@ functions. These can be mixed and matched. Note that these functions are not reentrant for performance reasons. ABI -========== +--- libbpf can be both linked statically or used as DSO. To avoid possible conflicts with other libraries an application is linked with, all From 8bdc267e7b853ca08ed762b21fecc0e019ddc332 Mon Sep 17 00:00:00 2001 From: grantseltzer Date: Wed, 18 Aug 2021 16:34:33 -0400 Subject: [PATCH 28/28] sync: latest libbpf changes from kernel Syncing latest libbpf commits from kernel repository. Baseline bpf-next commit: 3c3bd542ffbb2ac09631313ede46ae66660ae550 Checkpoint bpf-next commit: d20b41115ad53293201cc07ee429a38740cb056b Baseline bpf commit: 3776f3517ed94d40ff0e3851d7ce2ce17b63099f Checkpoint bpf commit: 3776f3517ed94d40ff0e3851d7ce2ce17b63099f Grant Seltzer (1): libbpf: Rename libbpf documentation index file docs/{libbpf.rst => index.rst} | 8 ++++++++ docs/libbpf_naming_convention.rst | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) rename docs/{libbpf.rst => index.rst} (75%) -- 2.31.1 --- CHECKPOINT-COMMIT | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHECKPOINT-COMMIT b/CHECKPOINT-COMMIT index dcc3aa1..79178c1 100644 --- a/CHECKPOINT-COMMIT +++ b/CHECKPOINT-COMMIT @@ -1 +1 @@ -3c3bd542ffbb2ac09631313ede46ae66660ae550 +d20b41115ad53293201cc07ee429a38740cb056b