Skip to content

bpf: bpf link iterator #357

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .github/actions/vmtest/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: 'vmtest'
description: 'Build + run vmtest'
inputs:
arch:
description: 'what arch to test'
required: true
default: 'x86_64'
runs:
using: "composite"
steps:
# 1. Setup environment
- name: Setup build environment
uses: libbpf/ci/setup-build-env@master
# 2. Build
- name: Build kernel image
shell: bash
run: ${GITHUB_ACTION_PATH}/build.sh ${{ inputs.arch }}
- name: Build selftests
shell: bash
run: ${GITHUB_ACTION_PATH}/build_selftests.sh
env:
VMLINUX_BTF: ${{ github.workspace }}/vmlinux
# 3. Test
- name: Prepare rootfs
uses: libbpf/ci/prepare-rootfs@master
with:
project-name: 'libbpf'
arch: ${{ inputs.arch }}
kernel-root: '.'
- name: Run selftests
uses: libbpf/ci/run-qemu@master
with:
arch: ${{ inputs.arch}}
img: '/tmp/root.img'
vmlinuz: '${{ github.workspace }}/vmlinuz'
17 changes: 17 additions & 0 deletions .github/actions/vmtest/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

set -euo pipefail

ARCH="$1"

THISDIR="$(cd $(dirname $0) && pwd)"

source "${THISDIR}"/helpers.sh

travis_fold start build_kernel "Building kernel"

cp ${GITHUB_WORKSPACE}/travis-ci/vmtest/configs/config-latest.${ARCH} .config

make -j $((4*$(nproc))) olddefconfig all > /dev/null

travis_fold end build_kernel
42 changes: 42 additions & 0 deletions .github/actions/vmtest/build_selftests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/bin/bash

set -euo pipefail

THISDIR="$(cd $(dirname $0) && pwd)"

source "${THISDIR}"/helpers.sh

travis_fold start prepare_selftests "Building selftests"

LLVM_VER=15
LIBBPF_PATH="${REPO_ROOT}"

PREPARE_SELFTESTS_SCRIPT=${THISDIR}/prepare_selftests-${KERNEL}.sh
if [ -f "${PREPARE_SELFTESTS_SCRIPT}" ]; then
(cd "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" && ${PREPARE_SELFTESTS_SCRIPT})
fi

if [[ "${KERNEL}" = 'LATEST' ]]; then
VMLINUX_H=
else
VMLINUX_H=${THISDIR}/vmlinux.h
fi

cd ${REPO_ROOT}/${REPO_PATH}
make \
CLANG=clang-${LLVM_VER} \
LLC=llc-${LLVM_VER} \
LLVM_STRIP=llvm-strip-${LLVM_VER} \
VMLINUX_BTF="${VMLINUX_BTF}" \
VMLINUX_H="${VMLINUX_H}" \
-C "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" \
-j $((4*$(nproc))) > /dev/null
cd -
mkdir "${LIBBPF_PATH}"/selftests
cp -R "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" \
"${LIBBPF_PATH}"/selftests
cd "${LIBBPF_PATH}"
rm selftests/bpf/.gitignore
git add selftests

travis_fold end prepare_selftests
44 changes: 44 additions & 0 deletions .github/actions/vmtest/helpers.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# $1 - start or end
# $2 - fold identifier, no spaces
# $3 - fold section description
travis_fold() {
local YELLOW='\033[1;33m'
local NOCOLOR='\033[0m'
if [ -z ${GITHUB_WORKFLOW+x} ]; then
echo travis_fold:$1:$2
if [ ! -z "${3:-}" ]; then
echo -e "${YELLOW}$3${NOCOLOR}"
fi
echo
else
if [ $1 = "start" ]; then
line="::group::$2"
if [ ! -z "${3:-}" ]; then
line="$line - ${YELLOW}$3${NOCOLOR}"
fi
else
line="::endgroup::"
fi
echo -e "$line"
fi
}

__print() {
local TITLE=""
if [[ -n $2 ]]; then
TITLE=" title=$2"
fi
echo "::$1${TITLE}::$3"
}

# $1 - title
# $2 - message
print_error() {
__print error $1 $2
}

# $1 - title
# $2 - message
print_notice() {
__print notice $1 $2
}
50 changes: 50 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: bpf-ci

on:
pull_request:

concurrency:
group: ci-test-${{ github.head_ref }}
cancel-in-progress: true

jobs:
VM_Test:
runs-on: ${{ matrix.runs_on }}
name: Kernel ${{ matrix.kernel }} on ${{ matrix.runs_on }} + selftests
timeout-minutes: 100
strategy:
fail-fast: false
matrix:
include:
- kernel: 'LATEST'
runs_on: ubuntu-latest
arch: 'x86_64'
- kernel: 'LATEST'
runs_on: z15
arch: 's390x'
env:
AUTHOR_EMAIL: "$(git log -1 --pretty=\"%aE\")"
KERNEL: LATEST
REPO_ROOT: ${{ github.workspace }}
REPO_PATH: ""
steps:
- uses: actions/checkout@v2
- if: ${{ github.repository != 'kernel-patches/bpf' && github.repository != 'kernel-patches/bpf-rc' }}
name: Download bpf-next tree
uses: libbpf/ci/get-linux-source@master
with:
dest: '.kernel'
- if: ${{ github.repository != 'kernel-patches/bpf' && github.repository != 'kernel-patches/bpf-rc' }}
name: Move linux source in place
shell: bash
run: |
rm -rf .kernel/.git
cp -rf .kernel/. .
rm -rf .kernel
- uses: libbpf/ci/patch-kernel@master
with:
patches-root: '${{ github.workspace }}/travis-ci/diffs'
repo-root: '${{ github.workspace }}'
- uses: ./.github/actions/vmtest
with:
arch: ${{ matrix.arch }}
18 changes: 0 additions & 18 deletions README
Original file line number Diff line number Diff line change
@@ -1,18 +0,0 @@
Linux kernel
============

There are several guides for kernel developers and users. These guides can
be rendered in a number of formats, like HTML and PDF. Please read
Documentation/admin-guide/README.rst first.

In order to build the documentation, use ``make htmldocs`` or
``make pdfdocs``. The formatted documentation can also be read online at:

https://www.kernel.org/doc/html/latest/

There are various text files in the Documentation/ subdirectory,
several of them using the Restructured Text markup notation.

Please read the Documentation/process/changes.rst file, as it contains the
requirements for building and running the kernel, and information about
the problems which may result by upgrading your kernel.
1 change: 1 addition & 0 deletions include/linux/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -1489,6 +1489,7 @@ void bpf_link_put(struct bpf_link *link);
int bpf_link_new_fd(struct bpf_link *link);
struct file *bpf_link_new_file(struct bpf_link *link, int *reserved_fd);
struct bpf_link *bpf_link_get_from_fd(u32 ufd);
struct bpf_link *bpf_link_get_curr_or_next(u32 *id);

int bpf_obj_pin_user(u32 ufd, const char __user *pathname);
int bpf_obj_get_user(const char __user *pathname, int flags);
Expand Down
2 changes: 1 addition & 1 deletion kernel/bpf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ cflags-nogcse-$(CONFIG_X86)$(CONFIG_CC_IS_GCC) := -fno-gcse
endif
CFLAGS_core.o += $(call cc-disable-warning, override-init) $(cflags-nogcse-yy)

obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o bpf_iter.o map_iter.o task_iter.o prog_iter.o
obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o bpf_iter.o map_iter.o task_iter.o prog_iter.o link_iter.o
obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o bpf_lru_list.o lpm_trie.o map_in_map.o bloom_filter.o
obj-$(CONFIG_BPF_SYSCALL) += local_storage.o queue_stack_maps.o ringbuf.o
obj-$(CONFIG_BPF_SYSCALL) += bpf_local_storage.o bpf_task_storage.o
Expand Down
107 changes: 107 additions & 0 deletions kernel/bpf/link_iter.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2020 Facebook */
#include <linux/bpf.h>
#include <linux/fs.h>
#include <linux/filter.h>
#include <linux/kernel.h>
#include <linux/btf_ids.h>

struct bpf_iter_seq_link_info {
u32 link_id;
};

static void *bpf_link_seq_start(struct seq_file *seq, loff_t *pos)
{
struct bpf_iter_seq_link_info *info = seq->private;
struct bpf_link *link;

link = bpf_link_get_curr_or_next(&info->link_id);
if (!link)
return NULL;

if (*pos == 0)
++*pos;
return link;
}

static void *bpf_link_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct bpf_iter_seq_link_info *info = seq->private;

++*pos;
++info->link_id;
bpf_link_put((struct bpf_link *)v);
return bpf_link_get_curr_or_next(&info->link_id);
}

struct bpf_iter__bpf_link {
__bpf_md_ptr(struct bpf_iter_meta *, meta);
__bpf_md_ptr(struct bpf_link *, link);
};

DEFINE_BPF_ITER_FUNC(bpf_link, struct bpf_iter_meta *meta, struct bpf_link *link)

static int __bpf_link_seq_show(struct seq_file *seq, void *v, bool in_stop)
{
struct bpf_iter__bpf_link ctx;
struct bpf_iter_meta meta;
struct bpf_prog *prog;
int ret = 0;

ctx.meta = &meta;
ctx.link = v;
meta.seq = seq;
prog = bpf_iter_get_info(&meta, in_stop);
if (prog)
ret = bpf_iter_run_prog(prog, &ctx);

return ret;
}

static int bpf_link_seq_show(struct seq_file *seq, void *v)
{
return __bpf_link_seq_show(seq, v, false);
}

static void bpf_link_seq_stop(struct seq_file *seq, void *v)
{
if (!v)
(void)__bpf_link_seq_show(seq, v, true);
else
bpf_link_put((struct bpf_link *)v);
}

static const struct seq_operations bpf_link_seq_ops = {
.start = bpf_link_seq_start,
.next = bpf_link_seq_next,
.stop = bpf_link_seq_stop,
.show = bpf_link_seq_show,
};

BTF_ID_LIST(btf_bpf_link_id)
BTF_ID(struct, bpf_link)

static const struct bpf_iter_seq_info bpf_link_seq_info = {
.seq_ops = &bpf_link_seq_ops,
.init_seq_private = NULL,
.fini_seq_private = NULL,
.seq_priv_size = sizeof(struct bpf_iter_seq_link_info),
};

static struct bpf_iter_reg bpf_link_reg_info = {
.target = "bpf_link",
.ctx_arg_info_size = 1,
.ctx_arg_info = {
{ offsetof(struct bpf_iter__bpf_link, link),
PTR_TO_BTF_ID_OR_NULL },
},
.seq_info = &bpf_link_seq_info,
};

static int __init bpf_link_iter_init(void)
{
bpf_link_reg_info.ctx_arg_info[0].btf_id = *btf_bpf_link_id;
return bpf_iter_reg_target(&bpf_link_reg_info);
}

late_initcall(bpf_link_iter_init);
19 changes: 19 additions & 0 deletions kernel/bpf/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -4454,6 +4454,25 @@ struct bpf_link *bpf_link_by_id(u32 id)
return link;
}

struct bpf_link *bpf_link_get_curr_or_next(u32 *id)
{
struct bpf_link *link;

spin_lock_bh(&link_idr_lock);
again:
link = idr_get_next(&link_idr, id);
if (link) {
link = bpf_link_inc_not_zero(link);
if (IS_ERR(link)) {
(*id)++;
goto again;
}
}
spin_unlock_bh(&link_idr_lock);

return link;
}

#define BPF_LINK_GET_FD_BY_ID_LAST_FIELD link_id

static int bpf_link_get_fd_by_id(const union bpf_attr *attr)
Expand Down
15 changes: 15 additions & 0 deletions tools/testing/selftests/bpf/prog_tests/bpf_iter.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "bpf_iter_bpf_sk_storage_map.skel.h"
#include "bpf_iter_test_kern5.skel.h"
#include "bpf_iter_test_kern6.skel.h"
#include "bpf_iter_bpf_link.skel.h"

static int duration;

Expand Down Expand Up @@ -1172,6 +1173,20 @@ static void test_buf_neg_offset(void)
bpf_iter_test_kern6__destroy(skel);
}

static void test_link_iter(void)
{
struct bpf_iter_bpf_link *skel;

skel = bpf_iter_bpf_link__open_and_load();
if (CHECK(skel, "bpf_iter_bpf_link__open_and_load",
"skeleton open_and_load unexpected success\n"))
return;

do_dummy_read(skel->progs.dump_bpf_link);

bpf_iter_bpf_link__destroy(skel);
}

#define CMP_BUFFER_SIZE 1024
static char task_vma_output[CMP_BUFFER_SIZE];
static char proc_maps_output[CMP_BUFFER_SIZE];
Expand Down
Loading