Compare commits

..

3 Commits

Author SHA1 Message Date
Vladimir Kobal
673424c561 Add fallback to an old attaching method 2020-07-30 13:38:27 +03:00
Vladimir Kobal
d2feaff998 Skip probing for loading 2020-07-30 13:37:26 +03:00
Vladimir Kobal
0d4b75d30e Skip kernel version check 2020-07-30 13:35:35 +03:00
92 changed files with 5182 additions and 111590 deletions

View File

@@ -1,16 +0,0 @@
name: 'debian'
description: 'Build'
inputs:
target:
description: 'Run target'
required: true
runs:
using: "composite"
steps:
- run: |
source /tmp/ci_setup
bash -x $CI_ROOT/managers/debian.sh SETUP
bash -x $CI_ROOT/managers/debian.sh ${{ inputs.target }}
bash -x $CI_ROOT/managers/debian.sh CLEANUP
shell: bash

View File

@@ -1,23 +0,0 @@
name: 'setup'
description: 'setup env, create /tmp/ci_setup'
runs:
using: "composite"
steps:
- id: variables
run: |
export REPO_ROOT=$GITHUB_WORKSPACE
export CI_ROOT=$REPO_ROOT/travis-ci
# this is somewhat ugly, but that is the easiest way to share this code with
# arch specific docker
echo 'echo ::group::Env setup' > /tmp/ci_setup
echo export DEBIAN_FRONTEND=noninteractive >> /tmp/ci_setup
echo sudo apt-get update >> /tmp/ci_setup
echo sudo apt-get install -y aptitude qemu-kvm zstd binutils-dev elfutils libcap-dev libelf-dev libdw-dev >> /tmp/ci_setup
echo export PROJECT_NAME='libbpf' >> /tmp/ci_setup
echo export AUTHOR_EMAIL="$(git log -1 --pretty=\"%aE\")" >> /tmp/ci_setup
echo export REPO_ROOT=$GITHUB_WORKSPACE >> /tmp/ci_setup
echo export CI_ROOT=$REPO_ROOT/travis-ci >> /tmp/ci_setup
echo export VMTEST_ROOT=$CI_ROOT/vmtest >> /tmp/ci_setup
echo 'echo ::endgroup::' >> /tmp/ci_setup
shell: bash

View File

@@ -1,35 +0,0 @@
name: 'vmtest'
description: 'Build + run vmtest'
inputs:
kernel:
description: 'kernel version or LATEST'
required: true
default: 'LATEST'
kernel-rev:
description: 'CHECKPOINT or rev/tag/branch'
required: true
default: 'CHECKPOINT'
kernel-origin:
description: 'kernel repo'
required: true
default: 'https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git'
pahole:
description: 'pahole rev/tag/branch'
required: true
default: 'master'
pahole-origin:
description: 'pahole repo'
required: true
default: 'https://git.kernel.org/pub/scm/devel/pahole/pahole.git'
runs:
using: "composite"
steps:
- run: |
source /tmp/ci_setup
export KERNEL=${{ inputs.kernel }}
export KERNEL_BRANCH=${{ inputs.kernel-rev }}
export KERNEL_ORIGIN=${{ inputs.kernel-origin }}
export PAHOLE_BRANCH=${{ inputs.pahole }}
export PAHOLE_ORIGIN=${{ inputs.pahole-origin }}
$CI_ROOT/vmtest/run_vmtest.sh
shell: bash

View File

@@ -1,30 +0,0 @@
name: libbpf-ci-coverity
on:
schedule:
- cron: '0 18 * * *'
jobs:
coverity:
runs-on: ubuntu-latest
name: Coverity
steps:
- uses: actions/checkout@v2
- uses: ./.github/actions/setup
- name: Run coverity
run: |
echo ::group::Setup CI env
source /tmp/ci_setup
export COVERITY_SCAN_NOTIFICATION_EMAIL="${AUTHOR_EMAIL}"
export COVERITY_SCAN_BRANCH_PATTERN=${GITHUB_REF##refs/*/}
export TRAVIS_BRANCH=${COVERITY_SCAN_BRANCH_PATTERN}
echo ::endgroup::
scripts/coverity.sh
env:
COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
COVERITY_SCAN_PROJECT_NAME: libbpf
COVERITY_SCAN_BUILD_COMMAND_PREPEND: 'cd src/'
COVERITY_SCAN_BUILD_COMMAND: 'make'
- name: SCM log
run: cat /home/runner/work/libbpf/libbpf/src/cov-int/scm_log.txt

View File

@@ -1,36 +0,0 @@
name: ondemand
on:
workflow_dispatch:
inputs:
kernel-origin:
description: 'git repo for linux kernel'
default: 'https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git'
required: true
kernel-rev:
description: 'rev/tag/branch for linux kernel'
default: "master"
required: true
pahole-origin:
description: 'git repo for pahole'
default: 'https://git.kernel.org/pub/scm/devel/pahole/pahole.git'
required: true
pahole-rev:
description: 'ref/tag/branch for pahole'
default: "master"
required: true
jobs:
vmtest:
runs-on: ubuntu-latest
name: vmtest with customized pahole/Kernel
steps:
- uses: actions/checkout@v2
- uses: ./.github/actions/setup
- uses: ./.github/actions/vmtest
with:
kernel: 'LATEST'
kernel-rev: ${{ github.event.inputs.kernel-rev }}
kernel-origin: ${{ github.event.inputs.kernel-origin }}
pahole: ${{ github.event.inputs.pahole-rev }}
pahole-origin: ${{ github.event.inputs.pahole-origin }}

View File

@@ -1,20 +0,0 @@
name: pahole-staging
on:
schedule:
- cron: '0 18 * * *'
jobs:
vmtest:
runs-on: ubuntu-latest
name: Kernel LATEST + staging pahole
env:
STAGING: tmp.master
steps:
- uses: actions/checkout@v2
- uses: ./.github/actions/setup
- uses: ./.github/actions/vmtest
with:
kernel: LATEST
pahole: $STAGING

View File

@@ -1,100 +0,0 @@
name: libbpf-ci
on:
pull_request:
push:
schedule:
- cron: '0 18 * * *'
concurrency:
group: ci-test-${{ github.head_ref }}
cancel-in-progress: true
jobs:
vmtest:
runs-on: ubuntu-latest
name: Kernel ${{ matrix.kernel }} + selftests
strategy:
fail-fast: false
matrix:
include:
- kernel: 'LATEST'
- kernel: '5.5.0'
- kernel: '4.9.0'
steps:
- uses: actions/checkout@v2
name: Checkout
- uses: ./.github/actions/setup
name: Setup
- uses: ./.github/actions/vmtest
name: vmtest
with:
kernel: ${{ matrix.kernel }}
debian:
runs-on: ubuntu-latest
name: Debian Build (${{ matrix.name }})
strategy:
fail-fast: false
matrix:
include:
- name: default
target: RUN
- name: ASan+UBSan
target: RUN_ASAN
- name: clang
target: RUN_CLANG
- name: clang ASan+UBSan
target: RUN_CLANG_ASAN
- name: gcc-10
target: RUN_GCC10
- name: gcc-10 ASan+UBSan
target: RUN_GCC10_ASAN
steps:
- uses: actions/checkout@v2
name: Checkout
- uses: ./.github/actions/setup
name: Setup
- uses: ./.github/actions/debian
name: Build
with:
target: ${{ matrix.target }}
ubuntu:
runs-on: ubuntu-latest
name: Ubuntu Focal Build (${{ matrix.arch }})
strategy:
fail-fast: false
matrix:
include:
- arch: aarch64
- arch: ppc64le
- arch: s390x
- arch: x86
steps:
- uses: actions/checkout@v2
name: Checkout
- uses: ./.github/actions/setup
name: Pre-Setup
- run: source /tmp/ci_setup && sudo -E $CI_ROOT/managers/ubuntu.sh
if: matrix.arch == 'x86'
name: Setup
- uses: uraimo/run-on-arch-action@v2.0.5
name: Build in docker
if: matrix.arch != 'x86'
with:
distro:
ubuntu20.04
arch:
${{ matrix.arch }}
setup:
cp /tmp/ci_setup $GITHUB_WORKSPACE
dockerRunArgs: |
--volume "${GITHUB_WORKSPACE}:${GITHUB_WORKSPACE}"
shell: /bin/bash
install: |
export DEBIAN_FRONTEND=noninteractive
export TZ="America/Los_Angeles"
apt-get update -y
apt-get install -y tzdata build-essential sudo
run: source ${GITHUB_WORKSPACE}/ci_setup && $CI_ROOT/managers/ubuntu.sh

View File

@@ -1,17 +0,0 @@
# .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

View File

@@ -1,6 +1,6 @@
sudo: required sudo: required
language: bash language: bash
dist: focal dist: bionic
services: services:
- docker - docker
@@ -35,23 +35,8 @@ stages:
jobs: jobs:
include: include:
- stage: Builds & Tests - stage: Build & Test
name: Kernel 5.5.0 + selftests name: Debian Build
language: bash
env: KERNEL=5.5.0
script: $CI_ROOT/vmtest/run_vmtest.sh || travis_terminate 1
- name: Kernel LATEST + selftests
language: bash
env: KERNEL=LATEST
script: $CI_ROOT/vmtest/run_vmtest.sh || travis_terminate 1
- name: Kernel 4.9.0 + selftests
language: bash
env: KERNEL=4.9.0
script: $CI_ROOT/vmtest/run_vmtest.sh || travis_terminate 1
- name: Debian Build
language: bash language: bash
install: $CI_ROOT/managers/debian.sh SETUP install: $CI_ROOT/managers/debian.sh SETUP
script: $CI_ROOT/managers/debian.sh RUN || travis_terminate 1 script: $CI_ROOT/managers/debian.sh RUN || travis_terminate 1
@@ -75,37 +60,47 @@ jobs:
script: $CI_ROOT/managers/debian.sh RUN_CLANG_ASAN || travis_terminate 1 script: $CI_ROOT/managers/debian.sh RUN_CLANG_ASAN || travis_terminate 1
after_script: $CI_ROOT/managers/debian.sh CLEANUP after_script: $CI_ROOT/managers/debian.sh CLEANUP
- name: Debian Build (gcc-10) - name: Debian Build (gcc-8)
language: bash language: bash
install: $CI_ROOT/managers/debian.sh SETUP install: $CI_ROOT/managers/debian.sh SETUP
script: $CI_ROOT/managers/debian.sh RUN_GCC10 || travis_terminate 1 script: $CI_ROOT/managers/debian.sh RUN_GCC8 || travis_terminate 1
after_script: $CI_ROOT/managers/debian.sh CLEANUP after_script: $CI_ROOT/managers/debian.sh CLEANUP
- name: Debian Build (gcc-10 ASan+UBSan) - name: Debian Build (gcc-8 ASan+UBSan)
language: bash language: bash
install: $CI_ROOT/managers/debian.sh SETUP install: $CI_ROOT/managers/debian.sh SETUP
script: $CI_ROOT/managers/debian.sh RUN_GCC10_ASAN || travis_terminate 1 script: $CI_ROOT/managers/debian.sh RUN_GCC8_ASAN || travis_terminate 1
after_script: $CI_ROOT/managers/debian.sh CLEANUP after_script: $CI_ROOT/managers/debian.sh CLEANUP
- name: Ubuntu Focal Build - name: Ubuntu Bionic Build
language: bash language: bash
script: sudo $CI_ROOT/managers/ubuntu.sh || travis_terminate 1 script: sudo $CI_ROOT/managers/ubuntu.sh || travis_terminate 1
- name: Ubuntu Focal Build (arm) - name: Ubuntu Bionic Build (arm)
arch: arm64 arch: arm64
language: bash language: bash
script: sudo $CI_ROOT/managers/ubuntu.sh || travis_terminate 1 script: sudo $CI_ROOT/managers/ubuntu.sh || travis_terminate 1
- name: Ubuntu Focal Build (s390x) - name: Ubuntu Bionic Build (s390x)
arch: s390x arch: s390x
language: bash language: bash
script: sudo $CI_ROOT/managers/ubuntu.sh || travis_terminate 1 script: sudo $CI_ROOT/managers/ubuntu.sh || travis_terminate 1
- name: Ubuntu Focal Build (ppc64le) - name: Ubuntu Bionic Build (ppc64le)
arch: ppc64le arch: ppc64le
language: bash language: bash
script: sudo $CI_ROOT/managers/ubuntu.sh || travis_terminate 1 script: sudo $CI_ROOT/managers/ubuntu.sh || travis_terminate 1
- name: Kernel 5.5.0 + selftests
language: bash
env: KERNEL=5.5.0
script: $CI_ROOT/vmtest/run_vmtest.sh || travis_terminate 1
- name: Kernel LATEST + selftests
language: bash
env: KERNEL=LATEST
script: $CI_ROOT/vmtest/run_vmtest.sh || travis_terminate 1
- stage: Coverity - stage: Coverity
language: bash language: bash
env: env:
@@ -120,11 +115,9 @@ jobs:
- COVERITY_SCAN_BUILD_COMMAND_PREPEND="cd src/" - COVERITY_SCAN_BUILD_COMMAND_PREPEND="cd src/"
- COVERITY_SCAN_BUILD_COMMAND="make" - COVERITY_SCAN_BUILD_COMMAND="make"
install: install:
- sudo echo 'deb-src http://archive.ubuntu.com/ubuntu/ focal main restricted universe multiverse' >>/etc/apt/sources.list - sudo echo 'deb-src http://archive.ubuntu.com/ubuntu/ bionic main restricted universe multiverse' >>/etc/apt/sources.list
- sudo apt-get update - sudo apt-get update
- sudo apt-get -y build-dep libelf-dev - sudo apt-get -y build-dep libelf-dev
- sudo apt-get install -y libelf-dev pkg-config - sudo apt-get install -y libelf-dev pkg-config
script: script:
- scripts/coverity.sh || travis_terminate 1 - scripts/coverity.sh || travis_terminate 1
allow_failures:
- env: KERNEL=x.x.x

View File

@@ -1 +1 @@
8d6c414cd2fb74aa6812e9bfec6178f8246c4f3a 4e15507fea70c0c312d79610efa46b6853ccf8e0

View File

@@ -1 +1 @@
5319255b8df9271474bc9027cabf82253934f28d 69119673bd50b176ded34032fadd41530fb5af21

View File

@@ -1,38 +1,23 @@
This is a mirror of [bpf-next Linux source
tree](https://kernel.googlesource.com/pub/scm/linux/kernel/git/bpf/bpf-next)'s This is a mirror of [bpf-next linux tree](https://kernel.googlesource.com/pub/scm/linux/kernel/git/bpf/bpf-next)'s
`tools/lib/bpf` directory plus its supporting header files. `tools/lib/bpf` directory plus its supporting header files.
All the gory details of syncing can be found in `scripts/sync-kernel.sh` The following files will by sync'ed with bpf-next repo:
script. - `src/` <-> `bpf-next/tools/lib/bpf/`
- `include/uapi/linux/bpf_common.h` <-> `bpf-next/tools/include/uapi/linux/bpf_common.h`
- `include/uapi/linux/bpf.h` <-> `bpf-next/tools/include/uapi/linux/bpf.h`
- `include/uapi/linux/btf.h` <-> `bpf-next/tools/include/uapi/linux/btf.h`
- `include/uapi/linux/if_link.h` <-> `bpf-next/tools/include/uapi/linux/if_link.h`
- `include/uapi/linux/if_xdp.h` <-> `bpf-next/tools/include/uapi/linux/if_xdp.h`
- `include/uapi/linux/netlink.h` <-> `bpf-next/tools/include/uapi/linux/netlink.h`
- `include/tools/libc_compat.h` <-> `bpf-next/tools/include/tools/libc_compat.h`
Some header files in this repo (`include/linux/*.h`) are reduced versions of Other header files at this repo (`include/linux/*.h`) are reduced versions of
their counterpart files at their counterpart files at bpf-next's `tools/include/linux/*.h` to make compilation
[bpf-next](https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/)'s successful.
`tools/include/linux/*.h` to make compilation successful.
BPF/libbpf usage and questions
==============================
Please check out [libbpf-bootstrap](https://github.com/libbpf/libbpf-bootstrap)
and [the companion blog post](https://nakryiko.com/posts/libbpf-bootstrap/) for
the examples of building BPF applications with libbpf.
[libbpf-tools](https://github.com/iovisor/bcc/tree/master/libbpf-tools) are also
a good source of the real-world libbpf-based tracing tools.
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 it [here](http://vger.kernel.org/vger-lists.html#bpf) and search
its archive [here](https://lore.kernel.org/bpf/). Please search the archive
before asking new questions. It very well might be that this was already
addressed or answered before.
bpf@vger.kernel.org is monitored by many more people and they will happily try
to help you with whatever issue you have. This repository's PRs and issues
should be opened only for dealing with issues pertaining to specific way this
libbpf mirror repo is set up and organized.
Build Build
[![Github Actions Builds & Tests](https://github.com/libbpf/libbpf/actions/workflows/test.yml/badge.svg)](https://github.com/libbpf/libbpf/actions/workflows/test.yml) [![Build Status](https://travis-ci.org/libbpf/libbpf.svg?branch=master)](https://travis-ci.org/libbpf/libbpf)
[![Total alerts](https://img.shields.io/lgtm/alerts/g/libbpf/libbpf.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/libbpf/libbpf/alerts/) [![Total alerts](https://img.shields.io/lgtm/alerts/g/libbpf/libbpf.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/libbpf/libbpf/alerts/)
[![Coverity](https://img.shields.io/coverity/scan/18195.svg)](https://scan.coverity.com/projects/libbpf) [![Coverity](https://img.shields.io/coverity/scan/18195.svg)](https://scan.coverity.com/projects/libbpf)
===== =====
@@ -40,9 +25,8 @@ libelf is an internal dependency of libbpf and thus it is required to link
against and must be installed on the system for applications to work. 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 pkg-config is used by default to find libelf, and the program called can be
overridden with `PKG_CONFIG`. overridden with `PKG_CONFIG`.
If using `pkg-config` at build time is not desired, it can be disabled by setting
If using `pkg-config` at build time is not desired, it can be disabled by `NO_PKG_CONFIG=1` when calling make.
setting `NO_PKG_CONFIG=1` when calling make.
To build both static libbpf.a and shared libbpf.so: To build both static libbpf.a and shared libbpf.so:
```bash ```bash
@@ -73,23 +57,18 @@ Distributions
Distributions packaging libbpf from this mirror: Distributions packaging libbpf from this mirror:
- [Fedora](https://src.fedoraproject.org/rpms/libbpf) - [Fedora](https://src.fedoraproject.org/rpms/libbpf)
- [Gentoo](https://packages.gentoo.org/packages/dev-libs/libbpf) - [Gentoo](https://packages.gentoo.org/packages/dev-libs/libbpf)
- [Debian](https://packages.debian.org/source/sid/libbpf) - [Debian](https://packages.debian.org/sid/libbpf-dev)
- [Arch](https://www.archlinux.org/packages/extra/x86_64/libbpf/)
- [Ubuntu](https://packages.ubuntu.com/source/groovy/libbpf)
- [Alpine](https://pkgs.alpinelinux.org/packages?name=libbpf)
Benefits of packaging from the mirror over packaging from kernel sources: Benefits of packaging from the mirror over packaging from kernel sources:
- Consistent versioning across distributions. - Consistent versioning across distributions.
- No ties to any specific kernel, transparent handling of older kernels. - No ties to any specific kernel, transparent handling of older kernels.
Libbpf is designed to be kernel-agnostic and work across multitude of Libbpf is designed to be kernel-agnostic and work across multitude of kernel
kernel versions. It has built-in mechanisms to gracefully handle older versions. It has built-in mechanisms to gracefully handle older kernels,
kernels, that are missing some of the features, by working around or that are missing some of the features, by working around or gracefully
gracefully degrading functionality. Thus libbpf is not tied to a specific degrading functionality. Thus libbpf is not tied to a specific kernel
kernel version and can/should be packaged and versioned independently. version and can/should be packaged and versioned independently.
- Continuous integration testing via - Continuous integration testing via [TravisCI](https://travis-ci.org/libbpf/libbpf).
[TravisCI](https://travis-ci.org/libbpf/libbpf). - Static code analysis via [LGTM](https://lgtm.com/projects/g/libbpf/libbpf) and [Coverity](https://scan.coverity.com/projects/libbpf).
- Static code analysis via [LGTM](https://lgtm.com/projects/g/libbpf/libbpf)
and [Coverity](https://scan.coverity.com/projects/libbpf).
Package dependencies of libbpf, package names may vary across distros: Package dependencies of libbpf, package names may vary across distros:
- zlib - zlib
@@ -110,9 +89,6 @@ Some major Linux distributions come with kernel BTF already built in:
- RHEL 8.2+ - RHEL 8.2+
- OpenSUSE Tumbleweed (in the next release, as of 2020-06-04) - OpenSUSE Tumbleweed (in the next release, as of 2020-06-04)
- Arch Linux (from kernel 5.7.1.arch1-1) - Arch Linux (from kernel 5.7.1.arch1-1)
- Manjaro (from kernel 5.4 if compiled after 2021-06-18)
- Ubuntu 20.10
- Debian 11 (amd64/arm64)
If your kernel doesn't come with BTF built-in, you'll need to build custom If your kernel doesn't come with BTF built-in, you'll need to build custom
kernel. You'll need: kernel. You'll need:
@@ -132,16 +108,13 @@ distributions have Clang/LLVM 10+ packaged by default:
- Fedora 32+ - Fedora 32+
- Ubuntu 20.04+ - Ubuntu 20.04+
- Arch Linux - Arch Linux
- Ubuntu 20.10 (LLVM 11)
- Debian 11 (LLVM 11)
- Alpine 3.13+
Otherwise, please make sure to update it on your system. Otherwise, please make sure to update it on your system.
The following resources are useful to understand what BPF CO-RE is and how to The following resources are useful to understand what BPF CO-RE is and how to
use it: use it:
- [BPF Portability and CO-RE](https://nakryiko.com/posts/bpf-portability-and-co-re/) - [BPF Portability and CO-RE](https://facebookmicrosites.github.io/bpf/blog/2020/02/19/bpf-portability-and-co-re.html)
- [HOWTO: BCC to libbpf conversion](https://nakryiko.com/posts/bcc-to-libbpf-howto-guide/) - [HOWTO: BCC to libbpf conversion](https://facebookmicrosites.github.io/bpf/blog/2020/02/20/bcc-to-libbpf-howto-guide.html)
- [libbpf-tools in BCC repo](https://github.com/iovisor/bcc/tree/master/libbpf-tools) - [libbpf-tools in BCC repo](https://github.com/iovisor/bcc/tree/master/libbpf-tools)
contain lots of real-world tools converted from BCC to BPF CO-RE. Consider contain lots of real-world tools converted from BCC to BPF CO-RE. Consider
converting some more to both contribute to the BPF community and gain some converting some more to both contribute to the BPF community and gain some

2
docs/.gitignore vendored
View File

@@ -1,2 +0,0 @@
sphinx/build
sphinx/doxygen/build

View File

@@ -1,51 +0,0 @@
.. 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 enum
bpf.h
-----
.. doxygenfile:: bpf.h
:project: libbpf
:sections: func define public-type enum
btf.h
-----
.. doxygenfile:: btf.h
:project: libbpf
:sections: func define public-type enum
xsk.h
-----
.. doxygenfile:: xsk.h
:project: libbpf
:sections: func define public-type enum
bpf_tracing.h
-------------
.. doxygenfile:: bpf_tracing.h
:project: libbpf
:sections: func define public-type enum
bpf_core_read.h
---------------
.. doxygenfile:: bpf_core_read.h
:project: libbpf
:sections: func define public-type enum
bpf_endian.h
------------
.. doxygenfile:: bpf_endian.h
:project: libbpf
:sections: func define public-type enum

View File

@@ -1,40 +0,0 @@
#!/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

View File

@@ -1,22 +0,0 @@
.. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
libbpf
======
For API documentation see the `versioned API documentation site <https://libbpf.readthedocs.io/en/latest/api.html>`_.
.. toctree::
:maxdepth: 1
libbpf_naming_convention
libbpf_build
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 <http://vger.kernel.org/vger-lists.html#bpf>`_ to the
mailing list search its `archive <https://lore.kernel.org/bpf/>`_.
Please search the archive before asking new questions. It very well might
be that this was already addressed or answered before.

View File

@@ -1,37 +0,0 @@
.. 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

View File

@@ -1,9 +0,0 @@
SPHINXBUILD ?= sphinx-build
SOURCEDIR = ../src
BUILDDIR = build
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)"
%:
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)"

View File

@@ -1,277 +0,0 @@
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

View File

@@ -1 +0,0 @@
breathe

View File

@@ -5,14 +5,6 @@
#include <linux/bpf.h> #include <linux/bpf.h>
#define BPF_RAW_INSN(CODE, DST, SRC, OFF, IMM) \
((struct bpf_insn) { \
.code = CODE, \
.dst_reg = DST, \
.src_reg = SRC, \
.off = OFF, \
.imm = IMM })
#define BPF_ALU64_IMM(OP, DST, IMM) \ #define BPF_ALU64_IMM(OP, DST, IMM) \
((struct bpf_insn) { \ ((struct bpf_insn) { \
.code = BPF_ALU64 | BPF_OP(OP) | BPF_K, \ .code = BPF_ALU64 | BPF_OP(OP) | BPF_K, \

View File

@@ -72,20 +72,11 @@ static inline void list_del(struct list_head *entry)
entry->prev = LIST_POISON2; entry->prev = LIST_POISON2;
} }
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
#define list_entry(ptr, type, member) \ #define list_entry(ptr, type, member) \
container_of(ptr, type, member) container_of(ptr, type, member)
#define list_first_entry(ptr, type, member) \ #define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member) list_entry((ptr)->next, type, member)
#define list_next_entry(pos, member) \ #define list_next_entry(pos, member) \
list_entry((pos)->member.next, typeof(*(pos)), member) list_entry((pos)->member.next, typeof(*(pos)), member)
#define list_for_each_entry(pos, head, member) \
for (pos = list_first_entry(head, typeof(*pos), member); \
&pos->member != (head); \
pos = list_next_entry(pos, member))
#endif #endif

View File

@@ -0,0 +1,20 @@
// SPDX-License-Identifier: (LGPL-2.0+ OR BSD-2-Clause)
/* Copyright (C) 2018 Netronome Systems, Inc. */
#ifndef __TOOLS_LIBC_COMPAT_H
#define __TOOLS_LIBC_COMPAT_H
#include <stdlib.h>
#include <linux/overflow.h>
#ifdef COMPAT_NEED_REALLOCARRAY
static inline void *reallocarray(void *ptr, size_t nmemb, size_t size)
{
size_t bytes;
if (unlikely(check_mul_overflow(nmemb, size, &bytes)))
return NULL;
return realloc(ptr, bytes);
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -43,7 +43,7 @@ struct btf_type {
* "size" tells the size of the type it is describing. * "size" tells the size of the type it is describing.
* *
* "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT, * "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT,
* FUNC, FUNC_PROTO, VAR and TAG. * FUNC, FUNC_PROTO and VAR.
* "type" is a type_id referring to another type. * "type" is a type_id referring to another type.
*/ */
union { union {
@@ -52,33 +52,28 @@ struct btf_type {
}; };
}; };
#define BTF_INFO_KIND(info) (((info) >> 24) & 0x1f) #define BTF_INFO_KIND(info) (((info) >> 24) & 0x0f)
#define BTF_INFO_VLEN(info) ((info) & 0xffff) #define BTF_INFO_VLEN(info) ((info) & 0xffff)
#define BTF_INFO_KFLAG(info) ((info) >> 31) #define BTF_INFO_KFLAG(info) ((info) >> 31)
enum { #define BTF_KIND_UNKN 0 /* Unknown */
BTF_KIND_UNKN = 0, /* Unknown */ #define BTF_KIND_INT 1 /* Integer */
BTF_KIND_INT = 1, /* Integer */ #define BTF_KIND_PTR 2 /* Pointer */
BTF_KIND_PTR = 2, /* Pointer */ #define BTF_KIND_ARRAY 3 /* Array */
BTF_KIND_ARRAY = 3, /* Array */ #define BTF_KIND_STRUCT 4 /* Struct */
BTF_KIND_STRUCT = 4, /* Struct */ #define BTF_KIND_UNION 5 /* Union */
BTF_KIND_UNION = 5, /* Union */ #define BTF_KIND_ENUM 6 /* Enumeration */
BTF_KIND_ENUM = 6, /* Enumeration */ #define BTF_KIND_FWD 7 /* Forward */
BTF_KIND_FWD = 7, /* Forward */ #define BTF_KIND_TYPEDEF 8 /* Typedef */
BTF_KIND_TYPEDEF = 8, /* Typedef */ #define BTF_KIND_VOLATILE 9 /* Volatile */
BTF_KIND_VOLATILE = 9, /* Volatile */ #define BTF_KIND_CONST 10 /* Const */
BTF_KIND_CONST = 10, /* Const */ #define BTF_KIND_RESTRICT 11 /* Restrict */
BTF_KIND_RESTRICT = 11, /* Restrict */ #define BTF_KIND_FUNC 12 /* Function */
BTF_KIND_FUNC = 12, /* Function */ #define BTF_KIND_FUNC_PROTO 13 /* Function Proto */
BTF_KIND_FUNC_PROTO = 13, /* Function Proto */ #define BTF_KIND_VAR 14 /* Variable */
BTF_KIND_VAR = 14, /* Variable */ #define BTF_KIND_DATASEC 15 /* Section */
BTF_KIND_DATASEC = 15, /* Section */ #define BTF_KIND_MAX BTF_KIND_DATASEC
BTF_KIND_FLOAT = 16, /* Floating point */ #define NR_BTF_KINDS (BTF_KIND_MAX + 1)
BTF_KIND_TAG = 17, /* Tag */
NR_BTF_KINDS,
BTF_KIND_MAX = NR_BTF_KINDS - 1,
};
/* For some specific BTF_KIND, "struct btf_type" is immediately /* For some specific BTF_KIND, "struct btf_type" is immediately
* followed by extra data. * followed by extra data.
@@ -174,15 +169,4 @@ struct btf_var_secinfo {
__u32 size; __u32 size;
}; };
/* BTF_KIND_TAG is followed by a single "struct btf_tag" to describe
* additional information related to the tag applied location.
* If component_idx == -1, the tag is applied to a struct, union,
* variable or function. Otherwise, it is applied to a struct/union
* member or a func argument, and component_idx indicates which member
* or argument (0 ... vlen-1).
*/
struct btf_tag {
__s32 component_idx;
};
#endif /* _UAPI__LINUX_BTF_H__ */ #endif /* _UAPI__LINUX_BTF_H__ */

View File

@@ -230,7 +230,6 @@ enum {
IFLA_INET6_ICMP6STATS, /* statistics (icmpv6) */ IFLA_INET6_ICMP6STATS, /* statistics (icmpv6) */
IFLA_INET6_TOKEN, /* device token */ IFLA_INET6_TOKEN, /* device token */
IFLA_INET6_ADDR_GEN_MODE, /* implicit address generator mode */ IFLA_INET6_ADDR_GEN_MODE, /* implicit address generator mode */
IFLA_INET6_RA_MTU, /* mtu carried in the RA message */
__IFLA_INET6_MAX __IFLA_INET6_MAX
}; };
@@ -345,7 +344,6 @@ enum {
IFLA_BRPORT_ISOLATED, IFLA_BRPORT_ISOLATED,
IFLA_BRPORT_BACKUP_PORT, IFLA_BRPORT_BACKUP_PORT,
IFLA_BRPORT_MRP_RING_OPEN, IFLA_BRPORT_MRP_RING_OPEN,
IFLA_BRPORT_MRP_IN_OPEN,
__IFLA_BRPORT_MAX __IFLA_BRPORT_MAX
}; };
#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
@@ -410,8 +408,6 @@ enum {
IFLA_MACVLAN_MACADDR, IFLA_MACVLAN_MACADDR,
IFLA_MACVLAN_MACADDR_DATA, IFLA_MACVLAN_MACADDR_DATA,
IFLA_MACVLAN_MACADDR_COUNT, IFLA_MACVLAN_MACADDR_COUNT,
IFLA_MACVLAN_BC_QUEUE_LEN,
IFLA_MACVLAN_BC_QUEUE_LEN_USED,
__IFLA_MACVLAN_MAX, __IFLA_MACVLAN_MAX,
}; };
@@ -654,7 +650,6 @@ enum {
IFLA_BOND_AD_ACTOR_SYSTEM, IFLA_BOND_AD_ACTOR_SYSTEM,
IFLA_BOND_TLB_DYNAMIC_LB, IFLA_BOND_TLB_DYNAMIC_LB,
IFLA_BOND_PEER_NOTIF_DELAY, IFLA_BOND_PEER_NOTIF_DELAY,
IFLA_BOND_AD_LACP_ACTIVE,
__IFLA_BOND_MAX, __IFLA_BOND_MAX,
}; };

View File

@@ -73,12 +73,9 @@ struct xdp_umem_reg {
}; };
struct xdp_statistics { struct xdp_statistics {
__u64 rx_dropped; /* Dropped for other reasons */ __u64 rx_dropped; /* Dropped for reasons other than invalid desc */
__u64 rx_invalid_descs; /* Dropped due to invalid descriptor */ __u64 rx_invalid_descs; /* Dropped due to invalid descriptor */
__u64 tx_invalid_descs; /* Dropped due to invalid descriptor */ __u64 tx_invalid_descs; /* Dropped due to invalid descriptor */
__u64 rx_ring_full; /* Dropped due to rx ring being full */
__u64 rx_fill_ring_empty_descs; /* Failed to retrieve item from fill ring */
__u64 tx_ring_empty_descs; /* Failed to retrieve item from tx ring */
}; };
struct xdp_options { struct xdp_options {

View File

@@ -1,612 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef __LINUX_PKT_CLS_H
#define __LINUX_PKT_CLS_H
#include <linux/types.h>
#include <linux/pkt_sched.h>
#define TC_COOKIE_MAX_SIZE 16
/* Action attributes */
enum {
TCA_ACT_UNSPEC,
TCA_ACT_KIND,
TCA_ACT_OPTIONS,
TCA_ACT_INDEX,
TCA_ACT_STATS,
TCA_ACT_PAD,
TCA_ACT_COOKIE,
__TCA_ACT_MAX
};
#define TCA_ACT_MAX __TCA_ACT_MAX
#define TCA_OLD_COMPAT (TCA_ACT_MAX+1)
#define TCA_ACT_MAX_PRIO 32
#define TCA_ACT_BIND 1
#define TCA_ACT_NOBIND 0
#define TCA_ACT_UNBIND 1
#define TCA_ACT_NOUNBIND 0
#define TCA_ACT_REPLACE 1
#define TCA_ACT_NOREPLACE 0
#define TC_ACT_UNSPEC (-1)
#define TC_ACT_OK 0
#define TC_ACT_RECLASSIFY 1
#define TC_ACT_SHOT 2
#define TC_ACT_PIPE 3
#define TC_ACT_STOLEN 4
#define TC_ACT_QUEUED 5
#define TC_ACT_REPEAT 6
#define TC_ACT_REDIRECT 7
#define TC_ACT_TRAP 8 /* For hw path, this means "trap to cpu"
* and don't further process the frame
* in hardware. For sw path, this is
* equivalent of TC_ACT_STOLEN - drop
* the skb and act like everything
* is alright.
*/
#define TC_ACT_VALUE_MAX TC_ACT_TRAP
/* There is a special kind of actions called "extended actions",
* which need a value parameter. These have a local opcode located in
* the highest nibble, starting from 1. The rest of the bits
* are used to carry the value. These two parts together make
* a combined opcode.
*/
#define __TC_ACT_EXT_SHIFT 28
#define __TC_ACT_EXT(local) ((local) << __TC_ACT_EXT_SHIFT)
#define TC_ACT_EXT_VAL_MASK ((1 << __TC_ACT_EXT_SHIFT) - 1)
#define TC_ACT_EXT_OPCODE(combined) ((combined) & (~TC_ACT_EXT_VAL_MASK))
#define TC_ACT_EXT_CMP(combined, opcode) (TC_ACT_EXT_OPCODE(combined) == opcode)
#define TC_ACT_JUMP __TC_ACT_EXT(1)
#define TC_ACT_GOTO_CHAIN __TC_ACT_EXT(2)
#define TC_ACT_EXT_OPCODE_MAX TC_ACT_GOTO_CHAIN
/* Action type identifiers*/
enum {
TCA_ID_UNSPEC=0,
TCA_ID_POLICE=1,
/* other actions go here */
__TCA_ID_MAX=255
};
#define TCA_ID_MAX __TCA_ID_MAX
struct tc_police {
__u32 index;
int action;
#define TC_POLICE_UNSPEC TC_ACT_UNSPEC
#define TC_POLICE_OK TC_ACT_OK
#define TC_POLICE_RECLASSIFY TC_ACT_RECLASSIFY
#define TC_POLICE_SHOT TC_ACT_SHOT
#define TC_POLICE_PIPE TC_ACT_PIPE
__u32 limit;
__u32 burst;
__u32 mtu;
struct tc_ratespec rate;
struct tc_ratespec peakrate;
int refcnt;
int bindcnt;
__u32 capab;
};
struct tcf_t {
__u64 install;
__u64 lastuse;
__u64 expires;
__u64 firstuse;
};
struct tc_cnt {
int refcnt;
int bindcnt;
};
#define tc_gen \
__u32 index; \
__u32 capab; \
int action; \
int refcnt; \
int bindcnt
enum {
TCA_POLICE_UNSPEC,
TCA_POLICE_TBF,
TCA_POLICE_RATE,
TCA_POLICE_PEAKRATE,
TCA_POLICE_AVRATE,
TCA_POLICE_RESULT,
TCA_POLICE_TM,
TCA_POLICE_PAD,
__TCA_POLICE_MAX
#define TCA_POLICE_RESULT TCA_POLICE_RESULT
};
#define TCA_POLICE_MAX (__TCA_POLICE_MAX - 1)
/* tca flags definitions */
#define TCA_CLS_FLAGS_SKIP_HW (1 << 0) /* don't offload filter to HW */
#define TCA_CLS_FLAGS_SKIP_SW (1 << 1) /* don't use filter in SW */
#define TCA_CLS_FLAGS_IN_HW (1 << 2) /* filter is offloaded to HW */
#define TCA_CLS_FLAGS_NOT_IN_HW (1 << 3) /* filter isn't offloaded to HW */
#define TCA_CLS_FLAGS_VERBOSE (1 << 4) /* verbose logging */
/* U32 filters */
#define TC_U32_HTID(h) ((h)&0xFFF00000)
#define TC_U32_USERHTID(h) (TC_U32_HTID(h)>>20)
#define TC_U32_HASH(h) (((h)>>12)&0xFF)
#define TC_U32_NODE(h) ((h)&0xFFF)
#define TC_U32_KEY(h) ((h)&0xFFFFF)
#define TC_U32_UNSPEC 0
#define TC_U32_ROOT (0xFFF00000)
enum {
TCA_U32_UNSPEC,
TCA_U32_CLASSID,
TCA_U32_HASH,
TCA_U32_LINK,
TCA_U32_DIVISOR,
TCA_U32_SEL,
TCA_U32_POLICE,
TCA_U32_ACT,
TCA_U32_INDEV,
TCA_U32_PCNT,
TCA_U32_MARK,
TCA_U32_FLAGS,
TCA_U32_PAD,
__TCA_U32_MAX
};
#define TCA_U32_MAX (__TCA_U32_MAX - 1)
struct tc_u32_key {
__be32 mask;
__be32 val;
int off;
int offmask;
};
struct tc_u32_sel {
unsigned char flags;
unsigned char offshift;
unsigned char nkeys;
__be16 offmask;
__u16 off;
short offoff;
short hoff;
__be32 hmask;
struct tc_u32_key keys[0];
};
struct tc_u32_mark {
__u32 val;
__u32 mask;
__u32 success;
};
struct tc_u32_pcnt {
__u64 rcnt;
__u64 rhit;
__u64 kcnts[0];
};
/* Flags */
#define TC_U32_TERMINAL 1
#define TC_U32_OFFSET 2
#define TC_U32_VAROFFSET 4
#define TC_U32_EAT 8
#define TC_U32_MAXDEPTH 8
/* RSVP filter */
enum {
TCA_RSVP_UNSPEC,
TCA_RSVP_CLASSID,
TCA_RSVP_DST,
TCA_RSVP_SRC,
TCA_RSVP_PINFO,
TCA_RSVP_POLICE,
TCA_RSVP_ACT,
__TCA_RSVP_MAX
};
#define TCA_RSVP_MAX (__TCA_RSVP_MAX - 1 )
struct tc_rsvp_gpi {
__u32 key;
__u32 mask;
int offset;
};
struct tc_rsvp_pinfo {
struct tc_rsvp_gpi dpi;
struct tc_rsvp_gpi spi;
__u8 protocol;
__u8 tunnelid;
__u8 tunnelhdr;
__u8 pad;
};
/* ROUTE filter */
enum {
TCA_ROUTE4_UNSPEC,
TCA_ROUTE4_CLASSID,
TCA_ROUTE4_TO,
TCA_ROUTE4_FROM,
TCA_ROUTE4_IIF,
TCA_ROUTE4_POLICE,
TCA_ROUTE4_ACT,
__TCA_ROUTE4_MAX
};
#define TCA_ROUTE4_MAX (__TCA_ROUTE4_MAX - 1)
/* FW filter */
enum {
TCA_FW_UNSPEC,
TCA_FW_CLASSID,
TCA_FW_POLICE,
TCA_FW_INDEV,
TCA_FW_ACT, /* used by CONFIG_NET_CLS_ACT */
TCA_FW_MASK,
__TCA_FW_MAX
};
#define TCA_FW_MAX (__TCA_FW_MAX - 1)
/* TC index filter */
enum {
TCA_TCINDEX_UNSPEC,
TCA_TCINDEX_HASH,
TCA_TCINDEX_MASK,
TCA_TCINDEX_SHIFT,
TCA_TCINDEX_FALL_THROUGH,
TCA_TCINDEX_CLASSID,
TCA_TCINDEX_POLICE,
TCA_TCINDEX_ACT,
__TCA_TCINDEX_MAX
};
#define TCA_TCINDEX_MAX (__TCA_TCINDEX_MAX - 1)
/* Flow filter */
enum {
FLOW_KEY_SRC,
FLOW_KEY_DST,
FLOW_KEY_PROTO,
FLOW_KEY_PROTO_SRC,
FLOW_KEY_PROTO_DST,
FLOW_KEY_IIF,
FLOW_KEY_PRIORITY,
FLOW_KEY_MARK,
FLOW_KEY_NFCT,
FLOW_KEY_NFCT_SRC,
FLOW_KEY_NFCT_DST,
FLOW_KEY_NFCT_PROTO_SRC,
FLOW_KEY_NFCT_PROTO_DST,
FLOW_KEY_RTCLASSID,
FLOW_KEY_SKUID,
FLOW_KEY_SKGID,
FLOW_KEY_VLAN_TAG,
FLOW_KEY_RXHASH,
__FLOW_KEY_MAX,
};
#define FLOW_KEY_MAX (__FLOW_KEY_MAX - 1)
enum {
FLOW_MODE_MAP,
FLOW_MODE_HASH,
};
enum {
TCA_FLOW_UNSPEC,
TCA_FLOW_KEYS,
TCA_FLOW_MODE,
TCA_FLOW_BASECLASS,
TCA_FLOW_RSHIFT,
TCA_FLOW_ADDEND,
TCA_FLOW_MASK,
TCA_FLOW_XOR,
TCA_FLOW_DIVISOR,
TCA_FLOW_ACT,
TCA_FLOW_POLICE,
TCA_FLOW_EMATCHES,
TCA_FLOW_PERTURB,
__TCA_FLOW_MAX
};
#define TCA_FLOW_MAX (__TCA_FLOW_MAX - 1)
/* Basic filter */
enum {
TCA_BASIC_UNSPEC,
TCA_BASIC_CLASSID,
TCA_BASIC_EMATCHES,
TCA_BASIC_ACT,
TCA_BASIC_POLICE,
__TCA_BASIC_MAX
};
#define TCA_BASIC_MAX (__TCA_BASIC_MAX - 1)
/* Cgroup classifier */
enum {
TCA_CGROUP_UNSPEC,
TCA_CGROUP_ACT,
TCA_CGROUP_POLICE,
TCA_CGROUP_EMATCHES,
__TCA_CGROUP_MAX,
};
#define TCA_CGROUP_MAX (__TCA_CGROUP_MAX - 1)
/* BPF classifier */
#define TCA_BPF_FLAG_ACT_DIRECT (1 << 0)
enum {
TCA_BPF_UNSPEC,
TCA_BPF_ACT,
TCA_BPF_POLICE,
TCA_BPF_CLASSID,
TCA_BPF_OPS_LEN,
TCA_BPF_OPS,
TCA_BPF_FD,
TCA_BPF_NAME,
TCA_BPF_FLAGS,
TCA_BPF_FLAGS_GEN,
TCA_BPF_TAG,
TCA_BPF_ID,
__TCA_BPF_MAX,
};
#define TCA_BPF_MAX (__TCA_BPF_MAX - 1)
/* Flower classifier */
enum {
TCA_FLOWER_UNSPEC,
TCA_FLOWER_CLASSID,
TCA_FLOWER_INDEV,
TCA_FLOWER_ACT,
TCA_FLOWER_KEY_ETH_DST, /* ETH_ALEN */
TCA_FLOWER_KEY_ETH_DST_MASK, /* ETH_ALEN */
TCA_FLOWER_KEY_ETH_SRC, /* ETH_ALEN */
TCA_FLOWER_KEY_ETH_SRC_MASK, /* ETH_ALEN */
TCA_FLOWER_KEY_ETH_TYPE, /* be16 */
TCA_FLOWER_KEY_IP_PROTO, /* u8 */
TCA_FLOWER_KEY_IPV4_SRC, /* be32 */
TCA_FLOWER_KEY_IPV4_SRC_MASK, /* be32 */
TCA_FLOWER_KEY_IPV4_DST, /* be32 */
TCA_FLOWER_KEY_IPV4_DST_MASK, /* be32 */
TCA_FLOWER_KEY_IPV6_SRC, /* struct in6_addr */
TCA_FLOWER_KEY_IPV6_SRC_MASK, /* struct in6_addr */
TCA_FLOWER_KEY_IPV6_DST, /* struct in6_addr */
TCA_FLOWER_KEY_IPV6_DST_MASK, /* struct in6_addr */
TCA_FLOWER_KEY_TCP_SRC, /* be16 */
TCA_FLOWER_KEY_TCP_DST, /* be16 */
TCA_FLOWER_KEY_UDP_SRC, /* be16 */
TCA_FLOWER_KEY_UDP_DST, /* be16 */
TCA_FLOWER_FLAGS,
TCA_FLOWER_KEY_VLAN_ID, /* be16 */
TCA_FLOWER_KEY_VLAN_PRIO, /* u8 */
TCA_FLOWER_KEY_VLAN_ETH_TYPE, /* be16 */
TCA_FLOWER_KEY_ENC_KEY_ID, /* be32 */
TCA_FLOWER_KEY_ENC_IPV4_SRC, /* be32 */
TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK,/* be32 */
TCA_FLOWER_KEY_ENC_IPV4_DST, /* be32 */
TCA_FLOWER_KEY_ENC_IPV4_DST_MASK,/* be32 */
TCA_FLOWER_KEY_ENC_IPV6_SRC, /* struct in6_addr */
TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK,/* struct in6_addr */
TCA_FLOWER_KEY_ENC_IPV6_DST, /* struct in6_addr */
TCA_FLOWER_KEY_ENC_IPV6_DST_MASK,/* struct in6_addr */
TCA_FLOWER_KEY_TCP_SRC_MASK, /* be16 */
TCA_FLOWER_KEY_TCP_DST_MASK, /* be16 */
TCA_FLOWER_KEY_UDP_SRC_MASK, /* be16 */
TCA_FLOWER_KEY_UDP_DST_MASK, /* be16 */
TCA_FLOWER_KEY_SCTP_SRC_MASK, /* be16 */
TCA_FLOWER_KEY_SCTP_DST_MASK, /* be16 */
TCA_FLOWER_KEY_SCTP_SRC, /* be16 */
TCA_FLOWER_KEY_SCTP_DST, /* be16 */
TCA_FLOWER_KEY_ENC_UDP_SRC_PORT, /* be16 */
TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK, /* be16 */
TCA_FLOWER_KEY_ENC_UDP_DST_PORT, /* be16 */
TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK, /* be16 */
TCA_FLOWER_KEY_FLAGS, /* be32 */
TCA_FLOWER_KEY_FLAGS_MASK, /* be32 */
TCA_FLOWER_KEY_ICMPV4_CODE, /* u8 */
TCA_FLOWER_KEY_ICMPV4_CODE_MASK,/* u8 */
TCA_FLOWER_KEY_ICMPV4_TYPE, /* u8 */
TCA_FLOWER_KEY_ICMPV4_TYPE_MASK,/* u8 */
TCA_FLOWER_KEY_ICMPV6_CODE, /* u8 */
TCA_FLOWER_KEY_ICMPV6_CODE_MASK,/* u8 */
TCA_FLOWER_KEY_ICMPV6_TYPE, /* u8 */
TCA_FLOWER_KEY_ICMPV6_TYPE_MASK,/* u8 */
TCA_FLOWER_KEY_ARP_SIP, /* be32 */
TCA_FLOWER_KEY_ARP_SIP_MASK, /* be32 */
TCA_FLOWER_KEY_ARP_TIP, /* be32 */
TCA_FLOWER_KEY_ARP_TIP_MASK, /* be32 */
TCA_FLOWER_KEY_ARP_OP, /* u8 */
TCA_FLOWER_KEY_ARP_OP_MASK, /* u8 */
TCA_FLOWER_KEY_ARP_SHA, /* ETH_ALEN */
TCA_FLOWER_KEY_ARP_SHA_MASK, /* ETH_ALEN */
TCA_FLOWER_KEY_ARP_THA, /* ETH_ALEN */
TCA_FLOWER_KEY_ARP_THA_MASK, /* ETH_ALEN */
TCA_FLOWER_KEY_MPLS_TTL, /* u8 - 8 bits */
TCA_FLOWER_KEY_MPLS_BOS, /* u8 - 1 bit */
TCA_FLOWER_KEY_MPLS_TC, /* u8 - 3 bits */
TCA_FLOWER_KEY_MPLS_LABEL, /* be32 - 20 bits */
TCA_FLOWER_KEY_TCP_FLAGS, /* be16 */
TCA_FLOWER_KEY_TCP_FLAGS_MASK, /* be16 */
TCA_FLOWER_KEY_IP_TOS, /* u8 */
TCA_FLOWER_KEY_IP_TOS_MASK, /* u8 */
TCA_FLOWER_KEY_IP_TTL, /* u8 */
TCA_FLOWER_KEY_IP_TTL_MASK, /* u8 */
TCA_FLOWER_KEY_CVLAN_ID, /* be16 */
TCA_FLOWER_KEY_CVLAN_PRIO, /* u8 */
TCA_FLOWER_KEY_CVLAN_ETH_TYPE, /* be16 */
TCA_FLOWER_KEY_ENC_IP_TOS, /* u8 */
TCA_FLOWER_KEY_ENC_IP_TOS_MASK, /* u8 */
TCA_FLOWER_KEY_ENC_IP_TTL, /* u8 */
TCA_FLOWER_KEY_ENC_IP_TTL_MASK, /* u8 */
TCA_FLOWER_KEY_ENC_OPTS,
TCA_FLOWER_KEY_ENC_OPTS_MASK,
TCA_FLOWER_IN_HW_COUNT,
__TCA_FLOWER_MAX,
};
#define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1)
enum {
TCA_FLOWER_KEY_ENC_OPTS_UNSPEC,
TCA_FLOWER_KEY_ENC_OPTS_GENEVE, /* Nested
* TCA_FLOWER_KEY_ENC_OPT_GENEVE_
* attributes
*/
__TCA_FLOWER_KEY_ENC_OPTS_MAX,
};
#define TCA_FLOWER_KEY_ENC_OPTS_MAX (__TCA_FLOWER_KEY_ENC_OPTS_MAX - 1)
enum {
TCA_FLOWER_KEY_ENC_OPT_GENEVE_UNSPEC,
TCA_FLOWER_KEY_ENC_OPT_GENEVE_CLASS, /* u16 */
TCA_FLOWER_KEY_ENC_OPT_GENEVE_TYPE, /* u8 */
TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA, /* 4 to 128 bytes */
__TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX,
};
#define TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX \
(__TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX - 1)
enum {
TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT = (1 << 0),
TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST = (1 << 1),
};
/* Match-all classifier */
enum {
TCA_MATCHALL_UNSPEC,
TCA_MATCHALL_CLASSID,
TCA_MATCHALL_ACT,
TCA_MATCHALL_FLAGS,
__TCA_MATCHALL_MAX,
};
#define TCA_MATCHALL_MAX (__TCA_MATCHALL_MAX - 1)
/* Extended Matches */
struct tcf_ematch_tree_hdr {
__u16 nmatches;
__u16 progid;
};
enum {
TCA_EMATCH_TREE_UNSPEC,
TCA_EMATCH_TREE_HDR,
TCA_EMATCH_TREE_LIST,
__TCA_EMATCH_TREE_MAX
};
#define TCA_EMATCH_TREE_MAX (__TCA_EMATCH_TREE_MAX - 1)
struct tcf_ematch_hdr {
__u16 matchid;
__u16 kind;
__u16 flags;
__u16 pad; /* currently unused */
};
/* 0 1
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
* +-----------------------+-+-+---+
* | Unused |S|I| R |
* +-----------------------+-+-+---+
*
* R(2) ::= relation to next ematch
* where: 0 0 END (last ematch)
* 0 1 AND
* 1 0 OR
* 1 1 Unused (invalid)
* I(1) ::= invert result
* S(1) ::= simple payload
*/
#define TCF_EM_REL_END 0
#define TCF_EM_REL_AND (1<<0)
#define TCF_EM_REL_OR (1<<1)
#define TCF_EM_INVERT (1<<2)
#define TCF_EM_SIMPLE (1<<3)
#define TCF_EM_REL_MASK 3
#define TCF_EM_REL_VALID(v) (((v) & TCF_EM_REL_MASK) != TCF_EM_REL_MASK)
enum {
TCF_LAYER_LINK,
TCF_LAYER_NETWORK,
TCF_LAYER_TRANSPORT,
__TCF_LAYER_MAX
};
#define TCF_LAYER_MAX (__TCF_LAYER_MAX - 1)
/* Ematch type assignments
* 1..32767 Reserved for ematches inside kernel tree
* 32768..65535 Free to use, not reliable
*/
#define TCF_EM_CONTAINER 0
#define TCF_EM_CMP 1
#define TCF_EM_NBYTE 2
#define TCF_EM_U32 3
#define TCF_EM_META 4
#define TCF_EM_TEXT 5
#define TCF_EM_VLAN 6
#define TCF_EM_CANID 7
#define TCF_EM_IPSET 8
#define TCF_EM_IPT 9
#define TCF_EM_MAX 9
enum {
TCF_EM_PROG_TC
};
enum {
TCF_EM_OPND_EQ,
TCF_EM_OPND_GT,
TCF_EM_OPND_LT
};
#endif

File diff suppressed because it is too large Load Diff

18
scripts/check-reallocarray.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/sh
tfile=$(mktemp /tmp/test_reallocarray_XXXXXXXX.c)
ofile=${tfile%.c}.o
cat > $tfile <<EOL
#define _GNU_SOURCE
#include <stdlib.h>
int main(void)
{
return !!reallocarray(NULL, 1, 1);
}
EOL
gcc $tfile -o $ofile >/dev/null 2>&1
if [ $? -ne 0 ]; then echo "FAIL"; fi
/bin/rm -f $tfile $ofile

View File

@@ -6,6 +6,7 @@ usage () {
echo "Set BPF_NEXT_BASELINE to override bpf-next tree commit, otherwise read from <libbpf-repo>/CHECKPOINT-COMMIT." echo "Set BPF_NEXT_BASELINE to override bpf-next tree commit, otherwise read from <libbpf-repo>/CHECKPOINT-COMMIT."
echo "Set BPF_BASELINE to override bpf tree commit, otherwise read from <libbpf-repo>/BPF-CHECKPOINT-COMMIT." echo "Set BPF_BASELINE to override bpf tree commit, otherwise read from <libbpf-repo>/BPF-CHECKPOINT-COMMIT."
echo "Set MANUAL_MODE to 1 to manually control every cherry-picked commits." echo "Set MANUAL_MODE to 1 to manually control every cherry-picked commits."
echo "Set IGNORE_CONSISTENCY to 1 to ignore failed contents consistency check."
exit 1 exit 1
} }
@@ -45,15 +46,12 @@ PATH_MAP=( \
[tools/include/uapi/linux/if_link.h]=include/uapi/linux/if_link.h \ [tools/include/uapi/linux/if_link.h]=include/uapi/linux/if_link.h \
[tools/include/uapi/linux/if_xdp.h]=include/uapi/linux/if_xdp.h \ [tools/include/uapi/linux/if_xdp.h]=include/uapi/linux/if_xdp.h \
[tools/include/uapi/linux/netlink.h]=include/uapi/linux/netlink.h \ [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/tools/libc_compat.h]=include/tools/libc_compat.h \
[tools/include/uapi/linux/pkt_sched.h]=include/uapi/linux/pkt_sched.h \
[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_PATHS="${!PATH_MAP[@]} :^tools/lib/bpf/Makefile :^tools/lib/bpf/Build :^tools/lib/bpf/.gitignore"
LIBBPF_VIEW_PATHS="${PATH_MAP[@]}" LIBBPF_VIEW_PATHS="${PATH_MAP[@]}"
LIBBPF_VIEW_EXCLUDE_REGEX='^src/(Makefile|Build|test_libbpf\.c|bpf_helper_defs\.h|\.gitignore)$|^docs/(\.gitignore|api\.rst|conf\.py)$|^docs/sphinx/.*' LIBBPF_VIEW_EXCLUDE_REGEX='^src/(Makefile|Build|test_libbpf\.c|bpf_helper_defs\.h|\.gitignore)$'
LINUX_VIEW_EXCLUDE_REGEX='^include/tools/libc_compat.h$'
LIBBPF_TREE_FILTER="mkdir -p __libbpf/include/uapi/linux __libbpf/include/tools && "$'\\\n' LIBBPF_TREE_FILTER="mkdir -p __libbpf/include/uapi/linux __libbpf/include/tools && "$'\\\n'
for p in "${!PATH_MAP[@]}"; do for p in "${!PATH_MAP[@]}"; do
@@ -139,7 +137,6 @@ cherry_pick_commits()
echo "Warning! Cherry-picking '${desc} failed, checking if it's non-libbpf files causing problems..." echo "Warning! Cherry-picking '${desc} failed, checking if it's non-libbpf files causing problems..."
libbpf_conflict_cnt=$(git diff --name-only --diff-filter=U -- ${LIBBPF_PATHS[@]} | wc -l) libbpf_conflict_cnt=$(git diff --name-only --diff-filter=U -- ${LIBBPF_PATHS[@]} | wc -l)
conflict_cnt=$(git diff --name-only | wc -l) conflict_cnt=$(git diff --name-only | wc -l)
prompt_resolution=1
if ((${libbpf_conflict_cnt} == 0)); then if ((${libbpf_conflict_cnt} == 0)); then
echo "Looks like only non-libbpf files have conflicts, ignoring..." echo "Looks like only non-libbpf files have conflicts, ignoring..."
@@ -155,37 +152,15 @@ cherry_pick_commits()
echo "Error! That still failed! Please resolve manually." echo "Error! That still failed! Please resolve manually."
else else
echo "Success! All cherry-pick conflicts were resolved for '${desc}'!" echo "Success! All cherry-pick conflicts were resolved for '${desc}'!"
prompt_resolution=0 continue
fi fi
fi fi
if ((${prompt_resolution} == 1)); then read -p "Error! Cherry-picking '${desc}' failed, please fix manually and press <return> to proceed..."
read -p "Error! Cherry-picking '${desc}' failed, please fix manually and press <return> to proceed..."
fi
fi fi
# Append signature of just cherry-picked commit to avoid
# potentially cherry-picking the same commit twice later when
# processing bpf tree commits. At this point we don't know yet
# the final commit sha in libbpf repo, so we record Linux SHA
# instead as LINUX_<sha>.
echo LINUX_$(git log --pretty='%h' -n1) "${signature}" >> ${TMP_DIR}/libbpf_commits.txt
done done
} }
cleanup()
{
echo "Cleaning up..."
rm -r ${TMP_DIR}
cd_to ${LINUX_REPO}
git checkout ${TIP_SYM_REF}
git branch -D ${BASELINE_TAG} ${TIP_TAG} ${BPF_BASELINE_TAG} ${BPF_TIP_TAG} \
${SQUASH_BASE_TAG} ${SQUASH_TIP_TAG} ${VIEW_TAG} || true
cd_to .
echo "DONE."
}
cd_to ${LIBBPF_REPO} cd_to ${LIBBPF_REPO}
GITHUB_ABS_DIR=$(pwd) GITHUB_ABS_DIR=$(pwd)
echo "Dumping existing libbpf commit signatures..." echo "Dumping existing libbpf commit signatures..."
@@ -251,7 +226,6 @@ FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch --prune-empty -f --subdirector
COMMIT_CNT=$(git rev-list --count ${SQUASH_BASE_TAG}..${SQUASH_TIP_TAG}) COMMIT_CNT=$(git rev-list --count ${SQUASH_BASE_TAG}..${SQUASH_TIP_TAG})
if ((${COMMIT_CNT} <= 0)); then if ((${COMMIT_CNT} <= 0)); then
echo "No new changes to apply, we are done!" echo "No new changes to apply, we are done!"
cleanup
exit 2 exit 2
fi fi
@@ -263,18 +237,18 @@ cd_to ${LIBBPF_REPO}
git checkout -b ${LIBBPF_SYNC_TAG} git checkout -b ${LIBBPF_SYNC_TAG}
for patch in $(ls -1 ${TMP_DIR}/patches | tail -n +2); do for patch in $(ls -1 ${TMP_DIR}/patches | tail -n +2); do
if ! git am --3way --committer-date-is-author-date "${TMP_DIR}/patches/${patch}"; then if ! git am --committer-date-is-author-date "${TMP_DIR}/patches/${patch}"; then
read -p "Applying ${TMP_DIR}/patches/${patch} failed, please resolve manually and press <return> to proceed..." read -p "Applying ${TMP_DIR}/patches/${patch} failed, please resolve manually and press <return> to proceed..."
fi fi
done done
# Generate bpf_helper_defs.h and commit, if anything changed # Generate bpf_helper_defs.h and commit, if anything changed
# restore Linux tip to use bpf_doc.py # restore Linux tip to use bpf_helpers_doc.py
cd_to ${LINUX_REPO} cd_to ${LINUX_REPO}
git checkout ${TIP_TAG} git checkout ${TIP_TAG}
# re-generate bpf_helper_defs.h # re-generate bpf_helper_defs.h
cd_to ${LIBBPF_REPO} cd_to ${LIBBPF_REPO}
"${LINUX_ABS_DIR}/scripts/bpf_doc.py" --header \ "${LINUX_ABS_DIR}/scripts/bpf_helpers_doc.py" --header \
--file include/uapi/linux/bpf.h > src/bpf_helper_defs.h --file include/uapi/linux/bpf.h > src/bpf_helper_defs.h
# if anything changed, commit it # if anything changed, commit it
helpers_changes=$(git status --porcelain src/bpf_helper_defs.h | wc -l) helpers_changes=$(git status --porcelain src/bpf_helper_defs.h | wc -l)
@@ -312,7 +286,7 @@ cd_to ${LINUX_REPO}
git checkout -b ${VIEW_TAG} ${TIP_COMMIT} git checkout -b ${VIEW_TAG} ${TIP_COMMIT}
FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch -f --tree-filter "${LIBBPF_TREE_FILTER}" ${VIEW_TAG}^..${VIEW_TAG} FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch -f --tree-filter "${LIBBPF_TREE_FILTER}" ${VIEW_TAG}^..${VIEW_TAG}
FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch -f --subdirectory-filter __libbpf ${VIEW_TAG}^..${VIEW_TAG} FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch -f --subdirectory-filter __libbpf ${VIEW_TAG}^..${VIEW_TAG}
git ls-files -- ${LIBBPF_VIEW_PATHS[@]} | grep -v -E "${LINUX_VIEW_EXCLUDE_REGEX}" > ${TMP_DIR}/linux-view.ls git ls-files -- ${LIBBPF_VIEW_PATHS[@]} > ${TMP_DIR}/linux-view.ls
cd_to ${LIBBPF_REPO} cd_to ${LIBBPF_REPO}
git ls-files -- ${LIBBPF_VIEW_PATHS[@]} | grep -v -E "${LIBBPF_VIEW_EXCLUDE_REGEX}" > ${TMP_DIR}/github-view.ls git ls-files -- ${LIBBPF_VIEW_PATHS[@]} | grep -v -E "${LIBBPF_VIEW_EXCLUDE_REGEX}" > ${TMP_DIR}/github-view.ls
@@ -330,17 +304,19 @@ done
if ((${CONSISTENT} == 1)); then if ((${CONSISTENT} == 1)); then
echo "Great! Content is identical!" echo "Great! Content is identical!"
else else
ignore_inconsistency=n echo "Unfortunately, there are consistency problems!"
echo "Unfortunately, there are some inconsistencies, please double check." if ((${IGNORE_CONSISTENCY-0} != 1)); then
read -p "Does everything look good? [y/N]: " ignore_inconsistency exit 4
case "${ignore_inconsistency}" in fi
"y" | "Y")
echo "Ok, proceeding..."
;;
*)
echo "Oops, exiting with error..."
exit 4
esac
fi fi
cleanup echo "Cleaning up..."
rm -r ${TMP_DIR}
cd_to ${LINUX_REPO}
git checkout ${TIP_SYM_REF}
git branch -D ${BASELINE_TAG} ${TIP_TAG} ${BPF_BASELINE_TAG} ${BPF_TIP_TAG} \
${SQUASH_BASE_TAG} ${SQUASH_TIP_TAG} ${VIEW_TAG}
cd_to .
echo "DONE."

View File

@@ -1,13 +1,5 @@
# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) # SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
ifeq ($(V),1)
Q =
msg =
else
Q = @
msg = @printf ' %-8s %s%s\n' "$(1)" "$(notdir $(2))" "$(if $(3), $(3))";
endif
LIBBPF_VERSION := $(shell \ LIBBPF_VERSION := $(shell \
grep -oE '^LIBBPF_([0-9.]+)' libbpf.map | \ grep -oE '^LIBBPF_([0-9.]+)' libbpf.map | \
sort -rV | head -n1 | cut -d'_' -f2) sort -rV | head -n1 | cut -d'_' -f2)
@@ -18,6 +10,11 @@ TOPDIR = ..
INCLUDES := -I. -I$(TOPDIR)/include -I$(TOPDIR)/include/uapi INCLUDES := -I. -I$(TOPDIR)/include -I$(TOPDIR)/include/uapi
ALL_CFLAGS := $(INCLUDES) ALL_CFLAGS := $(INCLUDES)
FEATURE_REALLOCARRAY := $(shell $(TOPDIR)/scripts/check-reallocarray.sh)
ifneq ($(FEATURE_REALLOCARRAY),)
ALL_CFLAGS += -DCOMPAT_NEED_REALLOCARRAY
endif
SHARED_CFLAGS += -fPIC -fvisibility=hidden -DSHARED SHARED_CFLAGS += -fPIC -fvisibility=hidden -DSHARED
CFLAGS ?= -g -O2 -Werror -Wall CFLAGS ?= -g -O2 -Werror -Wall
@@ -27,8 +24,8 @@ ifdef NO_PKG_CONFIG
ALL_LDFLAGS += -lelf -lz ALL_LDFLAGS += -lelf -lz
else else
PKG_CONFIG ?= pkg-config PKG_CONFIG ?= pkg-config
ALL_CFLAGS += $(shell $(PKG_CONFIG) --cflags libelf zlib) ALL_CFLAGS += $(shell $(PKG_CONFIG) --cflags libelf)
ALL_LDFLAGS += $(shell $(PKG_CONFIG) --libs libelf zlib) ALL_LDFLAGS += $(shell $(PKG_CONFIG) --libs libelf)
endif endif
OBJDIR ?= . OBJDIR ?= .
@@ -36,8 +33,7 @@ SHARED_OBJDIR := $(OBJDIR)/sharedobjs
STATIC_OBJDIR := $(OBJDIR)/staticobjs STATIC_OBJDIR := $(OBJDIR)/staticobjs
OBJS := bpf.o btf.o libbpf.o libbpf_errno.o netlink.o \ 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 \ 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
relo_core.o
SHARED_OBJS := $(addprefix $(SHARED_OBJDIR)/,$(OBJS)) SHARED_OBJS := $(addprefix $(SHARED_OBJDIR)/,$(OBJS))
STATIC_OBJS := $(addprefix $(STATIC_OBJDIR)/,$(OBJS)) STATIC_OBJS := $(addprefix $(STATIC_OBJDIR)/,$(OBJS))
@@ -49,9 +45,9 @@ ifndef BUILD_STATIC_ONLY
VERSION_SCRIPT := libbpf.map VERSION_SCRIPT := libbpf.map
endif endif
HEADERS := bpf.h libbpf.h btf.h libbpf_common.h libbpf_legacy.h xsk.h \ HEADERS := bpf.h libbpf.h btf.h xsk.h libbpf_util.h \
bpf_helpers.h bpf_helper_defs.h bpf_tracing.h \ bpf_helpers.h bpf_helper_defs.h bpf_tracing.h \
bpf_endian.h bpf_core_read.h skel_internal.h libbpf_version.h bpf_endian.h bpf_core_read.h libbpf_common.h
UAPI_HEADERS := $(addprefix $(TOPDIR)/include/uapi/linux/,\ UAPI_HEADERS := $(addprefix $(TOPDIR)/include/uapi/linux/,\
bpf.h bpf_common.h btf.h) bpf.h bpf_common.h btf.h)
@@ -61,19 +57,12 @@ INSTALL = install
DESTDIR ?= DESTDIR ?=
ifeq ($(filter-out %64 %64be %64eb %64le %64el s390x, $(shell uname -m)),) ifeq ($(shell uname -m),x86_64)
LIBSUBDIR := lib64 LIBSUBDIR := lib64
else else
LIBSUBDIR := lib LIBSUBDIR := lib
endif endif
# By default let the pc file itself use ${prefix} in includedir/libdir so that
# the prefix can be overridden at runtime (eg: --define-prefix)
ifndef LIBDIR
LIBDIR_PC := $$\{prefix\}/$(LIBSUBDIR)
else
LIBDIR_PC := $(LIBDIR)
endif
PREFIX ?= /usr PREFIX ?= /usr
LIBDIR ?= $(PREFIX)/$(LIBSUBDIR) LIBDIR ?= $(PREFIX)/$(LIBSUBDIR)
INCLUDEDIR ?= $(PREFIX)/include INCLUDEDIR ?= $(PREFIX)/include
@@ -84,54 +73,50 @@ TAGS_PROG := $(if $(shell which etags 2>/dev/null),etags,ctags)
all: $(STATIC_LIBS) $(SHARED_LIBS) $(PC_FILE) all: $(STATIC_LIBS) $(SHARED_LIBS) $(PC_FILE)
$(OBJDIR)/libbpf.a: $(STATIC_OBJS) $(OBJDIR)/libbpf.a: $(STATIC_OBJS)
$(call msg,AR,$@) $(AR) rcs $@ $^
$(Q)$(AR) rcs $@ $^
$(OBJDIR)/libbpf.so: $(OBJDIR)/libbpf.so.$(LIBBPF_MAJOR_VERSION) $(OBJDIR)/libbpf.so: $(OBJDIR)/libbpf.so.$(LIBBPF_MAJOR_VERSION)
$(Q)ln -sf $(^F) $@ ln -sf $(^F) $@
$(OBJDIR)/libbpf.so.$(LIBBPF_MAJOR_VERSION): $(OBJDIR)/libbpf.so.$(LIBBPF_VERSION) $(OBJDIR)/libbpf.so.$(LIBBPF_MAJOR_VERSION): $(OBJDIR)/libbpf.so.$(LIBBPF_VERSION)
$(Q)ln -sf $(^F) $@ ln -sf $(^F) $@
$(OBJDIR)/libbpf.so.$(LIBBPF_VERSION): $(SHARED_OBJS) $(OBJDIR)/libbpf.so.$(LIBBPF_VERSION): $(SHARED_OBJS)
$(call msg,CC,$@) $(CC) -shared -Wl,--version-script=$(VERSION_SCRIPT) \
$(Q)$(CC) -shared -Wl,--version-script=$(VERSION_SCRIPT) \ -Wl,-soname,libbpf.so.$(LIBBPF_MAJOR_VERSION) \
-Wl,-soname,libbpf.so.$(LIBBPF_MAJOR_VERSION) \ $^ $(ALL_LDFLAGS) -o $@
$^ $(ALL_LDFLAGS) -o $@
$(OBJDIR)/libbpf.pc: $(OBJDIR)/libbpf.pc:
$(Q)sed -e "s|@PREFIX@|$(PREFIX)|" \ sed -e "s|@PREFIX@|$(PREFIX)|" \
-e "s|@LIBDIR@|$(LIBDIR_PC)|" \ -e "s|@LIBDIR@|$(LIBDIR)|" \
-e "s|@VERSION@|$(LIBBPF_VERSION)|" \ -e "s|@VERSION@|$(LIBBPF_VERSION)|" \
< libbpf.pc.template > $@ < libbpf.pc.template > $@
$(STATIC_OBJDIR) $(SHARED_OBJDIR): $(STATIC_OBJDIR):
$(call msg,MKDIR,$@) mkdir -p $(STATIC_OBJDIR)
$(Q)mkdir -p $@
$(SHARED_OBJDIR):
mkdir -p $(SHARED_OBJDIR)
$(STATIC_OBJDIR)/%.o: %.c | $(STATIC_OBJDIR) $(STATIC_OBJDIR)/%.o: %.c | $(STATIC_OBJDIR)
$(call msg,CC,$@) $(CC) $(ALL_CFLAGS) $(CPPFLAGS) -c $< -o $@
$(Q)$(CC) $(ALL_CFLAGS) $(CPPFLAGS) -c $< -o $@
$(SHARED_OBJDIR)/%.o: %.c | $(SHARED_OBJDIR) $(SHARED_OBJDIR)/%.o: %.c | $(SHARED_OBJDIR)
$(call msg,CC,$@) $(CC) $(ALL_CFLAGS) $(SHARED_CFLAGS) $(CPPFLAGS) -c $< -o $@
$(Q)$(CC) $(ALL_CFLAGS) $(SHARED_CFLAGS) $(CPPFLAGS) -c $< -o $@
define do_install define do_install
$(call msg,INSTALL,$1) if [ ! -d '$(DESTDIR)$2' ]; then \
$(Q)if [ ! -d '$(DESTDIR)$2' ]; then \
$(INSTALL) -d -m 755 '$(DESTDIR)$2'; \ $(INSTALL) -d -m 755 '$(DESTDIR)$2'; \
fi; fi; \
$(Q)$(INSTALL) $(if $3,-m $3,) $1 '$(DESTDIR)$2' $(INSTALL) $1 $(if $3,-m $3,) '$(DESTDIR)$2'
endef endef
# Preserve symlinks at installation. # Preserve symlinks at installation.
define do_s_install define do_s_install
$(call msg,INSTALL,$1) if [ ! -d '$(DESTDIR)$2' ]; then \
$(Q)if [ ! -d '$(DESTDIR)$2' ]; then \
$(INSTALL) -d -m 755 '$(DESTDIR)$2'; \ $(INSTALL) -d -m 755 '$(DESTDIR)$2'; \
fi; fi; \
$(Q)cp -fR $1 '$(DESTDIR)$2' cp -fpR $1 '$(DESTDIR)$2'
endef endef
install: all install_headers install_pkgconfig install: all install_headers install_pkgconfig
@@ -149,16 +134,13 @@ install_pkgconfig: $(PC_FILE)
$(call do_install,$(PC_FILE),$(LIBDIR)/pkgconfig,644) $(call do_install,$(PC_FILE),$(LIBDIR)/pkgconfig,644)
clean: clean:
$(call msg,CLEAN) rm -rf *.o *.a *.so *.so.* *.pc $(SHARED_OBJDIR) $(STATIC_OBJDIR)
$(Q)rm -rf *.o *.a *.so *.so.* *.pc $(SHARED_OBJDIR) $(STATIC_OBJDIR)
.PHONY: cscope tags .PHONY: cscope tags
cscope: cscope:
$(call msg,CSCOPE) ls *.c *.h > cscope.files
$(Q)ls *.c *.h > cscope.files cscope -b -q -f cscope.out
$(Q)cscope -b -q -f cscope.out
tags: tags:
$(call msg,CTAGS) rm -f TAGS tags
$(Q)rm -f TAGS tags ls *.c *.h | xargs $(TAGS_PROG) -a
$(Q)ls *.c *.h | xargs $(TAGS_PROG) -a

View File

@@ -1,7 +1,7 @@
.. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) .. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
API naming convention libbpf API naming convention
===================== ============================
libbpf API provides access to a few logically separated groups of libbpf API provides access to a few logically separated groups of
functions and types. Every group has its own naming convention functions and types. Every group has its own naming convention
@@ -10,14 +10,14 @@ 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 All types and functions provided by libbpf API should have one of the
following prefixes: ``bpf_``, ``btf_``, ``libbpf_``, ``xsk_``, following prefixes: ``bpf_``, ``btf_``, ``libbpf_``, ``xsk_``,
``btf_dump_``, ``ring_buffer_``, ``perf_buffer_``. ``perf_buffer_``.
System call wrappers System call wrappers
-------------------- --------------------
System call wrappers are simple wrappers for commands supported by System call wrappers are simple wrappers for commands supported by
sys_bpf system call. These wrappers should go to ``bpf.h`` header file sys_bpf system call. These wrappers should go to ``bpf.h`` header file
and map one to one to corresponding commands. and map one-on-one to corresponding commands.
For example ``bpf_map_lookup_elem`` wraps ``BPF_MAP_LOOKUP_ELEM`` For example ``bpf_map_lookup_elem`` wraps ``BPF_MAP_LOOKUP_ELEM``
command of sys_bpf, ``bpf_prog_attach`` wraps ``BPF_PROG_ATTACH``, etc. command of sys_bpf, ``bpf_prog_attach`` wraps ``BPF_PROG_ATTACH``, etc.
@@ -49,6 +49,10 @@ object, ``bpf_object``, double underscore and ``open`` that defines the
purpose of the function to open ELF file and create ``bpf_object`` from purpose of the function to open ELF file and create ``bpf_object`` from
it. it.
Another example: ``bpf_program__load`` is named for corresponding
object, ``bpf_program``, that is separated from other part of the name
by double underscore.
All objects and corresponding functions other than BTF related should go All objects and corresponding functions other than BTF related should go
to ``libbpf.h``. BTF types and functions should go to ``btf.h``. to ``libbpf.h``. BTF types and functions should go to ``btf.h``.
@@ -68,8 +72,12 @@ of both low-level ring access functions and high-level configuration
functions. These can be mixed and matched. Note that these functions functions. These can be mixed and matched. Note that these functions
are not reentrant for performance reasons. are not reentrant for performance reasons.
ABI Please take a look at Documentation/networking/af_xdp.rst in the Linux
--- kernel source tree on how to use XDP sockets and for some common
mistakes in case you do not get any traffic up to user space.
libbpf ABI
==========
libbpf can be both linked statically or used as DSO. To avoid possible libbpf can be both linked statically or used as DSO. To avoid possible
conflicts with other libraries an application is linked with, all conflicts with other libraries an application is linked with, all
@@ -108,8 +116,7 @@ This bump in ABI version is at most once per kernel development cycle.
For example, if current state of ``libbpf.map`` is: For example, if current state of ``libbpf.map`` is:
.. code-block:: none .. code-block::
LIBBPF_0.0.1 { LIBBPF_0.0.1 {
global: global:
bpf_func_a; bpf_func_a;
@@ -121,8 +128,7 @@ For example, if current state of ``libbpf.map`` is:
, and a new symbol ``bpf_func_c`` is being introduced, then , and a new symbol ``bpf_func_c`` is being introduced, then
``libbpf.map`` should be changed like this: ``libbpf.map`` should be changed like this:
.. code-block:: none .. code-block::
LIBBPF_0.0.1 { LIBBPF_0.0.1 {
global: global:
bpf_func_a; bpf_func_a;
@@ -142,7 +148,7 @@ Format of version script and ways to handle ABI changes, including
incompatible ones, described in details in [1]. incompatible ones, described in details in [1].
Stand-alone build Stand-alone build
------------------- =================
Under https://github.com/libbpf/libbpf there is a (semi-)automated Under https://github.com/libbpf/libbpf there is a (semi-)automated
mirror of the mainline's version of libbpf for a stand-alone build. mirror of the mainline's version of libbpf for a stand-alone build.
@@ -150,53 +156,13 @@ 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 However, all changes to libbpf's code base must be upstreamed through
the mainline kernel tree. the mainline kernel tree.
API documentation convention
============================
The libbpf API is documented via comments above definitions in
header files. These comments can be rendered by doxygen and sphinx
for well organized html output. This section describes the
convention in which these comments should be formated.
Here is an example from btf.h:
.. code-block:: c
/**
* @brief **btf__new()** creates a new instance of a BTF object from the raw
* bytes of an ELF's BTF section
* @param data raw bytes
* @param size number of bytes passed in `data`
* @return new BTF object instance which has to be eventually freed with
* **btf__free()**
*
* On error, error-code-encoded-as-pointer is returned, not a NULL. To extract
* error code from such a pointer `libbpf_get_error()` should be used. If
* `libbpf_set_strict_mode(LIBBPF_STRICT_CLEAN_PTRS)` is enabled, NULL is
* returned on error instead. In both cases thread-local `errno` variable is
* always set to error code as well.
*/
The comment must start with a block comment of the form '/\*\*'.
The documentation always starts with a @brief directive. This line is a short
description about this API. It starts with the name of the API, denoted in bold
like so: **api_name**. Please include an open and close parenthesis if this is a
function. Follow with the short description of the API. A longer form description
can be added below the last directive, at the bottom of the comment.
Parameters are denoted with the @param directive, there should be one for each
parameter. If this is a function with a non-void return, use the @return directive
to document it.
License License
------------------- =======
libbpf is dual-licensed under LGPL 2.1 and BSD 2-Clause. libbpf is dual-licensed under LGPL 2.1 and BSD 2-Clause.
Links Links
------------------- =====
[1] https://www.akkadia.org/drepper/dsohowto.pdf [1] https://www.akkadia.org/drepper/dsohowto.pdf
(Chapter 3. Maintaining APIs and ABIs). (Chapter 3. Maintaining APIs and ABIs).

366
src/bpf.c
View File

@@ -32,6 +32,9 @@
#include "libbpf.h" #include "libbpf.h"
#include "libbpf_internal.h" #include "libbpf_internal.h"
/* make sure libbpf doesn't use kernel-only integer typedefs */
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
/* /*
* When building perf, unistd.h is overridden. __NR_bpf is * When building perf, unistd.h is overridden. __NR_bpf is
* required to be defined explicitly. * required to be defined explicitly.
@@ -67,12 +70,11 @@ static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
static inline int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size) static inline int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size)
{ {
int retries = 5;
int fd; int fd;
do { do {
fd = sys_bpf(BPF_PROG_LOAD, attr, size); fd = sys_bpf(BPF_PROG_LOAD, attr, size);
} while (fd < 0 && errno == EAGAIN && retries-- > 0); } while (fd < 0 && errno == EAGAIN);
return fd; return fd;
} }
@@ -80,7 +82,6 @@ static inline int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size)
int bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr) int bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr)
{ {
union bpf_attr attr; union bpf_attr attr;
int fd;
memset(&attr, '\0', sizeof(attr)); memset(&attr, '\0', sizeof(attr));
@@ -103,8 +104,7 @@ int bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr)
else else
attr.inner_map_fd = create_attr->inner_map_fd; attr.inner_map_fd = create_attr->inner_map_fd;
fd = sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
return libbpf_err_errno(fd);
} }
int bpf_create_map_node(enum bpf_map_type map_type, const char *name, int bpf_create_map_node(enum bpf_map_type map_type, const char *name,
@@ -162,7 +162,6 @@ int bpf_create_map_in_map_node(enum bpf_map_type map_type, const char *name,
__u32 map_flags, int node) __u32 map_flags, int node)
{ {
union bpf_attr attr; union bpf_attr attr;
int fd;
memset(&attr, '\0', sizeof(attr)); memset(&attr, '\0', sizeof(attr));
@@ -181,8 +180,7 @@ int bpf_create_map_in_map_node(enum bpf_map_type map_type, const char *name,
attr.numa_node = node; attr.numa_node = node;
} }
fd = sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
return libbpf_err_errno(fd);
} }
int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name, int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name,
@@ -219,56 +217,59 @@ alloc_zero_tailing_info(const void *orecord, __u32 cnt,
return info; return info;
} }
int libbpf__bpf_prog_load(const struct bpf_prog_load_params *load_attr) int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
char *log_buf, size_t log_buf_sz)
{ {
void *finfo = NULL, *linfo = NULL; void *finfo = NULL, *linfo = NULL;
union bpf_attr attr; union bpf_attr attr;
__u32 log_level;
int fd; int fd;
if (!load_attr->log_buf != !load_attr->log_buf_sz) if (!load_attr || !log_buf != !log_buf_sz)
return libbpf_err(-EINVAL); return -EINVAL;
if (load_attr->log_level > (4 | 2 | 1) || (load_attr->log_level && !load_attr->log_buf)) log_level = load_attr->log_level;
return libbpf_err(-EINVAL); if (log_level > (4 | 2 | 1) || (log_level && !log_buf))
return -EINVAL;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.prog_type = load_attr->prog_type; attr.prog_type = load_attr->prog_type;
attr.expected_attach_type = load_attr->expected_attach_type; attr.expected_attach_type = load_attr->expected_attach_type;
if (attr.prog_type == BPF_PROG_TYPE_STRUCT_OPS ||
if (load_attr->attach_prog_fd) attr.prog_type == BPF_PROG_TYPE_LSM) {
attr.attach_btf_id = load_attr->attach_btf_id;
} else if (attr.prog_type == BPF_PROG_TYPE_TRACING ||
attr.prog_type == BPF_PROG_TYPE_EXT) {
attr.attach_btf_id = load_attr->attach_btf_id;
attr.attach_prog_fd = load_attr->attach_prog_fd; attr.attach_prog_fd = load_attr->attach_prog_fd;
else } else {
attr.attach_btf_obj_fd = load_attr->attach_btf_obj_fd; attr.prog_ifindex = load_attr->prog_ifindex;
attr.attach_btf_id = load_attr->attach_btf_id; attr.kern_version = load_attr->kern_version;
}
attr.prog_ifindex = load_attr->prog_ifindex; attr.insn_cnt = (__u32)load_attr->insns_cnt;
attr.kern_version = load_attr->kern_version;
attr.insn_cnt = (__u32)load_attr->insn_cnt;
attr.insns = ptr_to_u64(load_attr->insns); attr.insns = ptr_to_u64(load_attr->insns);
attr.license = ptr_to_u64(load_attr->license); attr.license = ptr_to_u64(load_attr->license);
attr.log_level = load_attr->log_level; attr.log_level = log_level;
if (attr.log_level) { if (log_level) {
attr.log_buf = ptr_to_u64(load_attr->log_buf); attr.log_buf = ptr_to_u64(log_buf);
attr.log_size = load_attr->log_buf_sz; attr.log_size = log_buf_sz;
} else {
attr.log_buf = ptr_to_u64(NULL);
attr.log_size = 0;
} }
attr.prog_btf_fd = load_attr->prog_btf_fd; attr.prog_btf_fd = load_attr->prog_btf_fd;
attr.prog_flags = load_attr->prog_flags;
attr.func_info_rec_size = load_attr->func_info_rec_size; attr.func_info_rec_size = load_attr->func_info_rec_size;
attr.func_info_cnt = load_attr->func_info_cnt; attr.func_info_cnt = load_attr->func_info_cnt;
attr.func_info = ptr_to_u64(load_attr->func_info); attr.func_info = ptr_to_u64(load_attr->func_info);
attr.line_info_rec_size = load_attr->line_info_rec_size; attr.line_info_rec_size = load_attr->line_info_rec_size;
attr.line_info_cnt = load_attr->line_info_cnt; attr.line_info_cnt = load_attr->line_info_cnt;
attr.line_info = ptr_to_u64(load_attr->line_info); attr.line_info = ptr_to_u64(load_attr->line_info);
attr.fd_array = ptr_to_u64(load_attr->fd_array);
if (load_attr->name) if (load_attr->name)
memcpy(attr.prog_name, load_attr->name, memcpy(attr.prog_name, load_attr->name,
min(strlen(load_attr->name), (size_t)BPF_OBJ_NAME_LEN - 1)); min(strlen(load_attr->name), BPF_OBJ_NAME_LEN - 1));
attr.prog_flags = load_attr->prog_flags;
fd = sys_bpf_prog_load(&attr, sizeof(attr)); fd = sys_bpf_prog_load(&attr, sizeof(attr));
if (fd >= 0) if (fd >= 0)
@@ -286,10 +287,8 @@ int libbpf__bpf_prog_load(const struct bpf_prog_load_params *load_attr)
load_attr->func_info_cnt, load_attr->func_info_cnt,
load_attr->func_info_rec_size, load_attr->func_info_rec_size,
attr.func_info_rec_size); attr.func_info_rec_size);
if (!finfo) { if (!finfo)
errno = E2BIG;
goto done; goto done;
}
attr.func_info = ptr_to_u64(finfo); attr.func_info = ptr_to_u64(finfo);
attr.func_info_rec_size = load_attr->func_info_rec_size; attr.func_info_rec_size = load_attr->func_info_rec_size;
@@ -300,10 +299,8 @@ int libbpf__bpf_prog_load(const struct bpf_prog_load_params *load_attr)
load_attr->line_info_cnt, load_attr->line_info_cnt,
load_attr->line_info_rec_size, load_attr->line_info_rec_size,
attr.line_info_rec_size); attr.line_info_rec_size);
if (!linfo) { if (!linfo)
errno = E2BIG;
goto done; goto done;
}
attr.line_info = ptr_to_u64(linfo); attr.line_info = ptr_to_u64(linfo);
attr.line_info_rec_size = load_attr->line_info_rec_size; attr.line_info_rec_size = load_attr->line_info_rec_size;
@@ -312,68 +309,24 @@ int libbpf__bpf_prog_load(const struct bpf_prog_load_params *load_attr)
} }
fd = sys_bpf_prog_load(&attr, sizeof(attr)); fd = sys_bpf_prog_load(&attr, sizeof(attr));
if (fd >= 0) if (fd >= 0)
goto done; goto done;
} }
if (load_attr->log_level || !load_attr->log_buf) if (log_level || !log_buf)
goto done; goto done;
/* Try again with log */ /* Try again with log */
attr.log_buf = ptr_to_u64(load_attr->log_buf); attr.log_buf = ptr_to_u64(log_buf);
attr.log_size = load_attr->log_buf_sz; attr.log_size = log_buf_sz;
attr.log_level = 1; attr.log_level = 1;
load_attr->log_buf[0] = 0; log_buf[0] = 0;
fd = sys_bpf_prog_load(&attr, sizeof(attr)); fd = sys_bpf_prog_load(&attr, sizeof(attr));
done: done:
/* free() doesn't affect errno, so we don't need to restore it */
free(finfo); free(finfo);
free(linfo); free(linfo);
return libbpf_err_errno(fd); return fd;
}
int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
char *log_buf, size_t log_buf_sz)
{
struct bpf_prog_load_params p = {};
if (!load_attr || !log_buf != !log_buf_sz)
return libbpf_err(-EINVAL);
p.prog_type = load_attr->prog_type;
p.expected_attach_type = load_attr->expected_attach_type;
switch (p.prog_type) {
case BPF_PROG_TYPE_STRUCT_OPS:
case BPF_PROG_TYPE_LSM:
p.attach_btf_id = load_attr->attach_btf_id;
break;
case BPF_PROG_TYPE_TRACING:
case BPF_PROG_TYPE_EXT:
p.attach_btf_id = load_attr->attach_btf_id;
p.attach_prog_fd = load_attr->attach_prog_fd;
break;
default:
p.prog_ifindex = load_attr->prog_ifindex;
p.kern_version = load_attr->kern_version;
}
p.insn_cnt = load_attr->insns_cnt;
p.insns = load_attr->insns;
p.license = load_attr->license;
p.log_level = load_attr->log_level;
p.log_buf = log_buf;
p.log_buf_sz = log_buf_sz;
p.prog_btf_fd = load_attr->prog_btf_fd;
p.func_info_rec_size = load_attr->func_info_rec_size;
p.func_info_cnt = load_attr->func_info_cnt;
p.func_info = load_attr->func_info;
p.line_info_rec_size = load_attr->line_info_rec_size;
p.line_info_cnt = load_attr->line_info_cnt;
p.line_info = load_attr->line_info;
p.name = load_attr->name;
p.prog_flags = load_attr->prog_flags;
return libbpf__bpf_prog_load(&p);
} }
int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
@@ -401,7 +354,6 @@ int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
int log_level) int log_level)
{ {
union bpf_attr attr; union bpf_attr attr;
int fd;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.prog_type = type; attr.prog_type = type;
@@ -415,15 +367,13 @@ int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
attr.kern_version = kern_version; attr.kern_version = kern_version;
attr.prog_flags = prog_flags; attr.prog_flags = prog_flags;
fd = sys_bpf_prog_load(&attr, sizeof(attr)); return sys_bpf_prog_load(&attr, sizeof(attr));
return libbpf_err_errno(fd);
} }
int bpf_map_update_elem(int fd, const void *key, const void *value, int bpf_map_update_elem(int fd, const void *key, const void *value,
__u64 flags) __u64 flags)
{ {
union bpf_attr attr; union bpf_attr attr;
int ret;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.map_fd = fd; attr.map_fd = fd;
@@ -431,28 +381,24 @@ int bpf_map_update_elem(int fd, const void *key, const void *value,
attr.value = ptr_to_u64(value); attr.value = ptr_to_u64(value);
attr.flags = flags; attr.flags = flags;
ret = sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr)); return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
return libbpf_err_errno(ret);
} }
int bpf_map_lookup_elem(int fd, const void *key, void *value) int bpf_map_lookup_elem(int fd, const void *key, void *value)
{ {
union bpf_attr attr; union bpf_attr attr;
int ret;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.map_fd = fd; attr.map_fd = fd;
attr.key = ptr_to_u64(key); attr.key = ptr_to_u64(key);
attr.value = ptr_to_u64(value); attr.value = ptr_to_u64(value);
ret = sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr)); return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
return libbpf_err_errno(ret);
} }
int bpf_map_lookup_elem_flags(int fd, const void *key, void *value, __u64 flags) int bpf_map_lookup_elem_flags(int fd, const void *key, void *value, __u64 flags)
{ {
union bpf_attr attr; union bpf_attr attr;
int ret;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.map_fd = fd; attr.map_fd = fd;
@@ -460,74 +406,52 @@ int bpf_map_lookup_elem_flags(int fd, const void *key, void *value, __u64 flags)
attr.value = ptr_to_u64(value); attr.value = ptr_to_u64(value);
attr.flags = flags; attr.flags = flags;
ret = sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr)); return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
return libbpf_err_errno(ret);
} }
int bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value) int bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value)
{ {
union bpf_attr attr; union bpf_attr attr;
int ret;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.map_fd = fd; attr.map_fd = fd;
attr.key = ptr_to_u64(key); attr.key = ptr_to_u64(key);
attr.value = ptr_to_u64(value); attr.value = ptr_to_u64(value);
ret = sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, sizeof(attr));
return libbpf_err_errno(ret);
}
int bpf_map_lookup_and_delete_elem_flags(int fd, const void *key, void *value, __u64 flags)
{
union bpf_attr attr;
memset(&attr, 0, sizeof(attr));
attr.map_fd = fd;
attr.key = ptr_to_u64(key);
attr.value = ptr_to_u64(value);
attr.flags = flags;
return sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, sizeof(attr)); return sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, sizeof(attr));
} }
int bpf_map_delete_elem(int fd, const void *key) int bpf_map_delete_elem(int fd, const void *key)
{ {
union bpf_attr attr; union bpf_attr attr;
int ret;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.map_fd = fd; attr.map_fd = fd;
attr.key = ptr_to_u64(key); attr.key = ptr_to_u64(key);
ret = sys_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr)); return sys_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
return libbpf_err_errno(ret);
} }
int bpf_map_get_next_key(int fd, const void *key, void *next_key) int bpf_map_get_next_key(int fd, const void *key, void *next_key)
{ {
union bpf_attr attr; union bpf_attr attr;
int ret;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.map_fd = fd; attr.map_fd = fd;
attr.key = ptr_to_u64(key); attr.key = ptr_to_u64(key);
attr.next_key = ptr_to_u64(next_key); attr.next_key = ptr_to_u64(next_key);
ret = sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr)); return sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
return libbpf_err_errno(ret);
} }
int bpf_map_freeze(int fd) int bpf_map_freeze(int fd)
{ {
union bpf_attr attr; union bpf_attr attr;
int ret;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.map_fd = fd; attr.map_fd = fd;
ret = sys_bpf(BPF_MAP_FREEZE, &attr, sizeof(attr)); return sys_bpf(BPF_MAP_FREEZE, &attr, sizeof(attr));
return libbpf_err_errno(ret);
} }
static int bpf_map_batch_common(int cmd, int fd, void *in_batch, static int bpf_map_batch_common(int cmd, int fd, void *in_batch,
@@ -539,7 +463,7 @@ static int bpf_map_batch_common(int cmd, int fd, void *in_batch,
int ret; int ret;
if (!OPTS_VALID(opts, bpf_map_batch_opts)) if (!OPTS_VALID(opts, bpf_map_batch_opts))
return libbpf_err(-EINVAL); return -EINVAL;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.batch.map_fd = fd; attr.batch.map_fd = fd;
@@ -554,7 +478,7 @@ static int bpf_map_batch_common(int cmd, int fd, void *in_batch,
ret = sys_bpf(cmd, &attr, sizeof(attr)); ret = sys_bpf(cmd, &attr, sizeof(attr));
*count = attr.batch.count; *count = attr.batch.count;
return libbpf_err_errno(ret); return ret;
} }
int bpf_map_delete_batch(int fd, void *keys, __u32 *count, int bpf_map_delete_batch(int fd, void *keys, __u32 *count,
@@ -591,26 +515,22 @@ int bpf_map_update_batch(int fd, void *keys, void *values, __u32 *count,
int bpf_obj_pin(int fd, const char *pathname) int bpf_obj_pin(int fd, const char *pathname)
{ {
union bpf_attr attr; union bpf_attr attr;
int ret;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.pathname = ptr_to_u64((void *)pathname); attr.pathname = ptr_to_u64((void *)pathname);
attr.bpf_fd = fd; attr.bpf_fd = fd;
ret = sys_bpf(BPF_OBJ_PIN, &attr, sizeof(attr)); return sys_bpf(BPF_OBJ_PIN, &attr, sizeof(attr));
return libbpf_err_errno(ret);
} }
int bpf_obj_get(const char *pathname) int bpf_obj_get(const char *pathname)
{ {
union bpf_attr attr; union bpf_attr attr;
int fd;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.pathname = ptr_to_u64((void *)pathname); attr.pathname = ptr_to_u64((void *)pathname);
fd = sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr)); return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr));
return libbpf_err_errno(fd);
} }
int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type, int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type,
@@ -628,10 +548,9 @@ int bpf_prog_attach_xattr(int prog_fd, int target_fd,
const struct bpf_prog_attach_opts *opts) const struct bpf_prog_attach_opts *opts)
{ {
union bpf_attr attr; union bpf_attr attr;
int ret;
if (!OPTS_VALID(opts, bpf_prog_attach_opts)) if (!OPTS_VALID(opts, bpf_prog_attach_opts))
return libbpf_err(-EINVAL); return -EINVAL;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.target_fd = target_fd; attr.target_fd = target_fd;
@@ -640,110 +559,56 @@ int bpf_prog_attach_xattr(int prog_fd, int target_fd,
attr.attach_flags = OPTS_GET(opts, flags, 0); attr.attach_flags = OPTS_GET(opts, flags, 0);
attr.replace_bpf_fd = OPTS_GET(opts, replace_prog_fd, 0); attr.replace_bpf_fd = OPTS_GET(opts, replace_prog_fd, 0);
ret = sys_bpf(BPF_PROG_ATTACH, &attr, sizeof(attr)); return sys_bpf(BPF_PROG_ATTACH, &attr, sizeof(attr));
return libbpf_err_errno(ret);
} }
int bpf_prog_detach(int target_fd, enum bpf_attach_type type) int bpf_prog_detach(int target_fd, enum bpf_attach_type type)
{ {
union bpf_attr attr; union bpf_attr attr;
int ret;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.target_fd = target_fd; attr.target_fd = target_fd;
attr.attach_type = type; attr.attach_type = type;
ret = sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr)); return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
return libbpf_err_errno(ret);
} }
int bpf_prog_detach2(int prog_fd, int target_fd, enum bpf_attach_type type) int bpf_prog_detach2(int prog_fd, int target_fd, enum bpf_attach_type type)
{ {
union bpf_attr attr; union bpf_attr attr;
int ret;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.target_fd = target_fd; attr.target_fd = target_fd;
attr.attach_bpf_fd = prog_fd; attr.attach_bpf_fd = prog_fd;
attr.attach_type = type; attr.attach_type = type;
ret = sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr)); return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
return libbpf_err_errno(ret);
} }
int bpf_link_create(int prog_fd, int target_fd, int bpf_link_create(int prog_fd, int target_fd,
enum bpf_attach_type attach_type, enum bpf_attach_type attach_type,
const struct bpf_link_create_opts *opts) const struct bpf_link_create_opts *opts)
{ {
__u32 target_btf_id, iter_info_len;
union bpf_attr attr; union bpf_attr attr;
int fd;
if (!OPTS_VALID(opts, bpf_link_create_opts)) if (!OPTS_VALID(opts, bpf_link_create_opts))
return libbpf_err(-EINVAL); return -EINVAL;
iter_info_len = OPTS_GET(opts, iter_info_len, 0);
target_btf_id = OPTS_GET(opts, target_btf_id, 0);
/* 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)); memset(&attr, 0, sizeof(attr));
attr.link_create.prog_fd = prog_fd; attr.link_create.prog_fd = prog_fd;
attr.link_create.target_fd = target_fd; attr.link_create.target_fd = target_fd;
attr.link_create.attach_type = attach_type; attr.link_create.attach_type = attach_type;
attr.link_create.flags = OPTS_GET(opts, flags, 0);
if (target_btf_id) { return sys_bpf(BPF_LINK_CREATE, &attr, sizeof(attr));
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);
}
int bpf_link_detach(int link_fd)
{
union bpf_attr attr;
int ret;
memset(&attr, 0, sizeof(attr));
attr.link_detach.link_fd = link_fd;
ret = sys_bpf(BPF_LINK_DETACH, &attr, sizeof(attr));
return libbpf_err_errno(ret);
} }
int bpf_link_update(int link_fd, int new_prog_fd, int bpf_link_update(int link_fd, int new_prog_fd,
const struct bpf_link_update_opts *opts) const struct bpf_link_update_opts *opts)
{ {
union bpf_attr attr; union bpf_attr attr;
int ret;
if (!OPTS_VALID(opts, bpf_link_update_opts)) if (!OPTS_VALID(opts, bpf_link_update_opts))
return libbpf_err(-EINVAL); return -EINVAL;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.link_update.link_fd = link_fd; attr.link_update.link_fd = link_fd;
@@ -751,20 +616,17 @@ int bpf_link_update(int link_fd, int new_prog_fd,
attr.link_update.flags = OPTS_GET(opts, flags, 0); attr.link_update.flags = OPTS_GET(opts, flags, 0);
attr.link_update.old_prog_fd = OPTS_GET(opts, old_prog_fd, 0); attr.link_update.old_prog_fd = OPTS_GET(opts, old_prog_fd, 0);
ret = sys_bpf(BPF_LINK_UPDATE, &attr, sizeof(attr)); return sys_bpf(BPF_LINK_UPDATE, &attr, sizeof(attr));
return libbpf_err_errno(ret);
} }
int bpf_iter_create(int link_fd) int bpf_iter_create(int link_fd)
{ {
union bpf_attr attr; union bpf_attr attr;
int fd;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.iter_create.link_fd = link_fd; attr.iter_create.link_fd = link_fd;
fd = sys_bpf(BPF_ITER_CREATE, &attr, sizeof(attr)); return sys_bpf(BPF_ITER_CREATE, &attr, sizeof(attr));
return libbpf_err_errno(fd);
} }
int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags, int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
@@ -781,12 +643,10 @@ int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
attr.query.prog_ids = ptr_to_u64(prog_ids); attr.query.prog_ids = ptr_to_u64(prog_ids);
ret = sys_bpf(BPF_PROG_QUERY, &attr, sizeof(attr)); ret = sys_bpf(BPF_PROG_QUERY, &attr, sizeof(attr));
if (attach_flags) if (attach_flags)
*attach_flags = attr.query.attach_flags; *attach_flags = attr.query.attach_flags;
*prog_cnt = attr.query.prog_cnt; *prog_cnt = attr.query.prog_cnt;
return ret;
return libbpf_err_errno(ret);
} }
int bpf_prog_test_run(int prog_fd, int repeat, void *data, __u32 size, int bpf_prog_test_run(int prog_fd, int repeat, void *data, __u32 size,
@@ -804,15 +664,13 @@ int bpf_prog_test_run(int prog_fd, int repeat, void *data, __u32 size,
attr.test.repeat = repeat; attr.test.repeat = repeat;
ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr)); ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr));
if (size_out) if (size_out)
*size_out = attr.test.data_size_out; *size_out = attr.test.data_size_out;
if (retval) if (retval)
*retval = attr.test.retval; *retval = attr.test.retval;
if (duration) if (duration)
*duration = attr.test.duration; *duration = attr.test.duration;
return ret;
return libbpf_err_errno(ret);
} }
int bpf_prog_test_run_xattr(struct bpf_prog_test_run_attr *test_attr) int bpf_prog_test_run_xattr(struct bpf_prog_test_run_attr *test_attr)
@@ -821,7 +679,7 @@ int bpf_prog_test_run_xattr(struct bpf_prog_test_run_attr *test_attr)
int ret; int ret;
if (!test_attr->data_out && test_attr->data_size_out > 0) if (!test_attr->data_out && test_attr->data_size_out > 0)
return libbpf_err(-EINVAL); return -EINVAL;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.test.prog_fd = test_attr->prog_fd; attr.test.prog_fd = test_attr->prog_fd;
@@ -836,46 +694,11 @@ int bpf_prog_test_run_xattr(struct bpf_prog_test_run_attr *test_attr)
attr.test.repeat = test_attr->repeat; attr.test.repeat = test_attr->repeat;
ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr)); ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr));
test_attr->data_size_out = attr.test.data_size_out; test_attr->data_size_out = attr.test.data_size_out;
test_attr->ctx_size_out = attr.test.ctx_size_out; test_attr->ctx_size_out = attr.test.ctx_size_out;
test_attr->retval = attr.test.retval; test_attr->retval = attr.test.retval;
test_attr->duration = attr.test.duration; test_attr->duration = attr.test.duration;
return ret;
return libbpf_err_errno(ret);
}
int bpf_prog_test_run_opts(int prog_fd, struct bpf_test_run_opts *opts)
{
union bpf_attr attr;
int ret;
if (!OPTS_VALID(opts, bpf_test_run_opts))
return libbpf_err(-EINVAL);
memset(&attr, 0, sizeof(attr));
attr.test.prog_fd = prog_fd;
attr.test.cpu = OPTS_GET(opts, cpu, 0);
attr.test.flags = OPTS_GET(opts, flags, 0);
attr.test.repeat = OPTS_GET(opts, repeat, 0);
attr.test.duration = OPTS_GET(opts, duration, 0);
attr.test.ctx_size_in = OPTS_GET(opts, ctx_size_in, 0);
attr.test.ctx_size_out = OPTS_GET(opts, ctx_size_out, 0);
attr.test.data_size_in = OPTS_GET(opts, data_size_in, 0);
attr.test.data_size_out = OPTS_GET(opts, data_size_out, 0);
attr.test.ctx_in = ptr_to_u64(OPTS_GET(opts, ctx_in, NULL));
attr.test.ctx_out = ptr_to_u64(OPTS_GET(opts, ctx_out, NULL));
attr.test.data_in = ptr_to_u64(OPTS_GET(opts, data_in, NULL));
attr.test.data_out = ptr_to_u64(OPTS_GET(opts, data_out, NULL));
ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr));
OPTS_SET(opts, data_size_out, attr.test.data_size_out);
OPTS_SET(opts, ctx_size_out, attr.test.ctx_size_out);
OPTS_SET(opts, duration, attr.test.duration);
OPTS_SET(opts, retval, attr.test.retval);
return libbpf_err_errno(ret);
} }
static int bpf_obj_get_next_id(__u32 start_id, __u32 *next_id, int cmd) static int bpf_obj_get_next_id(__u32 start_id, __u32 *next_id, int cmd)
@@ -890,7 +713,7 @@ static int bpf_obj_get_next_id(__u32 start_id, __u32 *next_id, int cmd)
if (!err) if (!err)
*next_id = attr.next_id; *next_id = attr.next_id;
return libbpf_err_errno(err); return err;
} }
int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id) int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id)
@@ -916,49 +739,41 @@ int bpf_link_get_next_id(__u32 start_id, __u32 *next_id)
int bpf_prog_get_fd_by_id(__u32 id) int bpf_prog_get_fd_by_id(__u32 id)
{ {
union bpf_attr attr; union bpf_attr attr;
int fd;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.prog_id = id; attr.prog_id = id;
fd = sys_bpf(BPF_PROG_GET_FD_BY_ID, &attr, sizeof(attr)); return sys_bpf(BPF_PROG_GET_FD_BY_ID, &attr, sizeof(attr));
return libbpf_err_errno(fd);
} }
int bpf_map_get_fd_by_id(__u32 id) int bpf_map_get_fd_by_id(__u32 id)
{ {
union bpf_attr attr; union bpf_attr attr;
int fd;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.map_id = id; attr.map_id = id;
fd = sys_bpf(BPF_MAP_GET_FD_BY_ID, &attr, sizeof(attr)); return sys_bpf(BPF_MAP_GET_FD_BY_ID, &attr, sizeof(attr));
return libbpf_err_errno(fd);
} }
int bpf_btf_get_fd_by_id(__u32 id) int bpf_btf_get_fd_by_id(__u32 id)
{ {
union bpf_attr attr; union bpf_attr attr;
int fd;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.btf_id = id; attr.btf_id = id;
fd = sys_bpf(BPF_BTF_GET_FD_BY_ID, &attr, sizeof(attr)); return sys_bpf(BPF_BTF_GET_FD_BY_ID, &attr, sizeof(attr));
return libbpf_err_errno(fd);
} }
int bpf_link_get_fd_by_id(__u32 id) int bpf_link_get_fd_by_id(__u32 id)
{ {
union bpf_attr attr; union bpf_attr attr;
int fd;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.link_id = id; attr.link_id = id;
fd = sys_bpf(BPF_LINK_GET_FD_BY_ID, &attr, sizeof(attr)); return sys_bpf(BPF_LINK_GET_FD_BY_ID, &attr, sizeof(attr));
return libbpf_err_errno(fd);
} }
int bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len) int bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len)
@@ -972,27 +787,24 @@ int bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len)
attr.info.info = ptr_to_u64(info); attr.info.info = ptr_to_u64(info);
err = sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, sizeof(attr)); err = sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, sizeof(attr));
if (!err) if (!err)
*info_len = attr.info.info_len; *info_len = attr.info.info_len;
return libbpf_err_errno(err); return err;
} }
int bpf_raw_tracepoint_open(const char *name, int prog_fd) int bpf_raw_tracepoint_open(const char *name, int prog_fd)
{ {
union bpf_attr attr; union bpf_attr attr;
int fd;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.raw_tracepoint.name = ptr_to_u64(name); attr.raw_tracepoint.name = ptr_to_u64(name);
attr.raw_tracepoint.prog_fd = prog_fd; attr.raw_tracepoint.prog_fd = prog_fd;
fd = sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, sizeof(attr)); return sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, sizeof(attr));
return libbpf_err_errno(fd);
} }
int bpf_load_btf(const void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size, int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size,
bool do_log) bool do_log)
{ {
union bpf_attr attr = {}; union bpf_attr attr = {};
@@ -1009,13 +821,12 @@ retry:
} }
fd = sys_bpf(BPF_BTF_LOAD, &attr, sizeof(attr)); fd = sys_bpf(BPF_BTF_LOAD, &attr, sizeof(attr));
if (fd == -1 && !do_log && log_buf && log_buf_size) {
if (fd < 0 && !do_log && log_buf && log_buf_size) {
do_log = true; do_log = true;
goto retry; goto retry;
} }
return libbpf_err_errno(fd); return fd;
} }
int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len, int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len,
@@ -1032,42 +843,21 @@ int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len,
attr.task_fd_query.buf_len = *buf_len; attr.task_fd_query.buf_len = *buf_len;
err = sys_bpf(BPF_TASK_FD_QUERY, &attr, sizeof(attr)); err = sys_bpf(BPF_TASK_FD_QUERY, &attr, sizeof(attr));
*buf_len = attr.task_fd_query.buf_len; *buf_len = attr.task_fd_query.buf_len;
*prog_id = attr.task_fd_query.prog_id; *prog_id = attr.task_fd_query.prog_id;
*fd_type = attr.task_fd_query.fd_type; *fd_type = attr.task_fd_query.fd_type;
*probe_offset = attr.task_fd_query.probe_offset; *probe_offset = attr.task_fd_query.probe_offset;
*probe_addr = attr.task_fd_query.probe_addr; *probe_addr = attr.task_fd_query.probe_addr;
return libbpf_err_errno(err); return err;
} }
int bpf_enable_stats(enum bpf_stats_type type) int bpf_enable_stats(enum bpf_stats_type type)
{ {
union bpf_attr attr; union bpf_attr attr;
int fd;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
attr.enable_stats.type = type; attr.enable_stats.type = type;
fd = sys_bpf(BPF_ENABLE_STATS, &attr, sizeof(attr)); return sys_bpf(BPF_ENABLE_STATS, &attr, sizeof(attr));
return libbpf_err_errno(fd);
}
int bpf_prog_bind_map(int prog_fd, int map_fd,
const struct bpf_prog_bind_opts *opts)
{
union bpf_attr attr;
int ret;
if (!OPTS_VALID(opts, bpf_prog_bind_opts))
return libbpf_err(-EINVAL);
memset(&attr, 0, sizeof(attr));
attr.prog_bind_map.prog_fd = prog_fd;
attr.prog_bind_map.map_fd = map_fd;
attr.prog_bind_map.flags = OPTS_GET(opts, flags, 0);
ret = sys_bpf(BPF_PROG_BIND_MAP, &attr, sizeof(attr));
return libbpf_err_errno(ret);
} }

View File

@@ -124,8 +124,6 @@ LIBBPF_API int bpf_map_lookup_elem_flags(int fd, const void *key, void *value,
__u64 flags); __u64 flags);
LIBBPF_API int bpf_map_lookup_and_delete_elem(int fd, const void *key, LIBBPF_API int bpf_map_lookup_and_delete_elem(int fd, const void *key,
void *value); void *value);
LIBBPF_API int bpf_map_lookup_and_delete_elem_flags(int fd, const void *key,
void *value, __u64 flags);
LIBBPF_API int bpf_map_delete_elem(int fd, const void *key); LIBBPF_API int bpf_map_delete_elem(int fd, const void *key);
LIBBPF_API int bpf_map_get_next_key(int fd, const void *key, void *next_key); LIBBPF_API int bpf_map_get_next_key(int fd, const void *key, void *next_key);
LIBBPF_API int bpf_map_freeze(int fd); LIBBPF_API int bpf_map_freeze(int fd);
@@ -170,28 +168,15 @@ LIBBPF_API int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type);
LIBBPF_API int bpf_prog_detach2(int prog_fd, int attachable_fd, LIBBPF_API int bpf_prog_detach2(int prog_fd, int attachable_fd,
enum bpf_attach_type type); enum bpf_attach_type type);
union bpf_iter_link_info; /* defined in up-to-date linux/bpf.h */
struct bpf_link_create_opts { struct bpf_link_create_opts {
size_t sz; /* size of this struct for forward/backward compatibility */ size_t sz; /* size of this struct for forward/backward compatibility */
__u32 flags;
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 perf_event #define bpf_link_create_opts__last_field sz
LIBBPF_API int bpf_link_create(int prog_fd, int target_fd, LIBBPF_API int bpf_link_create(int prog_fd, int target_fd,
enum bpf_attach_type attach_type, enum bpf_attach_type attach_type,
const struct bpf_link_create_opts *opts); const struct bpf_link_create_opts *opts);
LIBBPF_API int bpf_link_detach(int link_fd);
struct bpf_link_update_opts { struct bpf_link_update_opts {
size_t sz; /* size of this struct for forward/backward compatibility */ size_t sz; /* size of this struct for forward/backward compatibility */
__u32 flags; /* extra flags */ __u32 flags; /* extra flags */
@@ -243,7 +228,7 @@ LIBBPF_API int bpf_prog_query(int target_fd, enum bpf_attach_type type,
__u32 query_flags, __u32 *attach_flags, __u32 query_flags, __u32 *attach_flags,
__u32 *prog_ids, __u32 *prog_cnt); __u32 *prog_ids, __u32 *prog_cnt);
LIBBPF_API int bpf_raw_tracepoint_open(const char *name, int prog_fd); LIBBPF_API int bpf_raw_tracepoint_open(const char *name, int prog_fd);
LIBBPF_API int bpf_load_btf(const void *btf, __u32 btf_size, char *log_buf, LIBBPF_API int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf,
__u32 log_buf_size, bool do_log); __u32 log_buf_size, bool do_log);
LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf,
__u32 *buf_len, __u32 *prog_id, __u32 *fd_type, __u32 *buf_len, __u32 *prog_id, __u32 *fd_type,
@@ -252,40 +237,6 @@ LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf,
enum bpf_stats_type; /* defined in up-to-date linux/bpf.h */ enum bpf_stats_type; /* defined in up-to-date linux/bpf.h */
LIBBPF_API int bpf_enable_stats(enum bpf_stats_type type); LIBBPF_API int bpf_enable_stats(enum bpf_stats_type type);
struct bpf_prog_bind_opts {
size_t sz; /* size of this struct for forward/backward compatibility */
__u32 flags;
};
#define bpf_prog_bind_opts__last_field flags
LIBBPF_API int bpf_prog_bind_map(int prog_fd, int map_fd,
const struct bpf_prog_bind_opts *opts);
struct bpf_test_run_opts {
size_t sz; /* size of this struct for forward/backward compatibility */
const void *data_in; /* optional */
void *data_out; /* optional */
__u32 data_size_in;
__u32 data_size_out; /* in: max length of data_out
* out: length of data_out
*/
const void *ctx_in; /* optional */
void *ctx_out; /* optional */
__u32 ctx_size_in;
__u32 ctx_size_out; /* in: max length of ctx_out
* out: length of cxt_out
*/
__u32 retval; /* out: return code of the BPF program */
int repeat;
__u32 duration; /* out: average per repetition in ns */
__u32 flags;
__u32 cpu;
};
#define bpf_test_run_opts__last_field cpu
LIBBPF_API int bpf_prog_test_run_opts(int prog_fd,
struct bpf_test_run_opts *opts);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif

View File

@@ -19,52 +19,32 @@ enum bpf_field_info_kind {
BPF_FIELD_RSHIFT_U64 = 5, BPF_FIELD_RSHIFT_U64 = 5,
}; };
/* second argument to __builtin_btf_type_id() built-in */
enum bpf_type_id_kind {
BPF_TYPE_ID_LOCAL = 0, /* BTF type ID in local program */
BPF_TYPE_ID_TARGET = 1, /* BTF type ID in target kernel */
};
/* second argument to __builtin_preserve_type_info() built-in */
enum bpf_type_info_kind {
BPF_TYPE_EXISTS = 0, /* type existence in target kernel */
BPF_TYPE_SIZE = 1, /* type size in target kernel */
};
/* second argument to __builtin_preserve_enum_value() built-in */
enum bpf_enum_value_kind {
BPF_ENUMVAL_EXISTS = 0, /* enum value existence in kernel */
BPF_ENUMVAL_VALUE = 1, /* enum value value relocation */
};
#define __CORE_RELO(src, field, info) \ #define __CORE_RELO(src, field, info) \
__builtin_preserve_field_info((src)->field, BPF_FIELD_##info) __builtin_preserve_field_info((src)->field, BPF_FIELD_##info)
#if __BYTE_ORDER == __LITTLE_ENDIAN #if __BYTE_ORDER == __LITTLE_ENDIAN
#define __CORE_BITFIELD_PROBE_READ(dst, src, fld) \ #define __CORE_BITFIELD_PROBE_READ(dst, src, fld) \
bpf_probe_read_kernel( \ bpf_probe_read((void *)dst, \
(void *)dst, \ __CORE_RELO(src, fld, BYTE_SIZE), \
__CORE_RELO(src, fld, BYTE_SIZE), \ (const void *)src + __CORE_RELO(src, fld, BYTE_OFFSET))
(const void *)src + __CORE_RELO(src, fld, BYTE_OFFSET))
#else #else
/* semantics of LSHIFT_64 assumes loading values into low-ordered bytes, so /* semantics of LSHIFT_64 assumes loading values into low-ordered bytes, so
* for big-endian we need to adjust destination pointer accordingly, based on * for big-endian we need to adjust destination pointer accordingly, based on
* field byte size * field byte size
*/ */
#define __CORE_BITFIELD_PROBE_READ(dst, src, fld) \ #define __CORE_BITFIELD_PROBE_READ(dst, src, fld) \
bpf_probe_read_kernel( \ bpf_probe_read((void *)dst + (8 - __CORE_RELO(src, fld, BYTE_SIZE)), \
(void *)dst + (8 - __CORE_RELO(src, fld, BYTE_SIZE)), \ __CORE_RELO(src, fld, BYTE_SIZE), \
__CORE_RELO(src, fld, BYTE_SIZE), \ (const void *)src + __CORE_RELO(src, fld, BYTE_OFFSET))
(const void *)src + __CORE_RELO(src, fld, BYTE_OFFSET))
#endif #endif
/* /*
* Extract bitfield, identified by s->field, and return its value as u64. * Extract bitfield, identified by s->field, and return its value as u64.
* All this is done in relocatable manner, so bitfield changes such as * All this is done in relocatable manner, so bitfield changes such as
* signedness, bit size, offset changes, this will be handled automatically. * signedness, bit size, offset changes, this will be handled automatically.
* This version of macro is using bpf_probe_read_kernel() to read underlying * This version of macro is using bpf_probe_read() to read underlying integer
* integer storage. Macro functions as an expression and its return type is * storage. Macro functions as an expression and its return type is
* bpf_probe_read_kernel()'s return value: 0, on success, <0 on error. * bpf_probe_read()'s return value: 0, on success, <0 on error.
*/ */
#define BPF_CORE_READ_BITFIELD_PROBED(s, field) ({ \ #define BPF_CORE_READ_BITFIELD_PROBED(s, field) ({ \
unsigned long long val = 0; \ unsigned long long val = 0; \
@@ -88,19 +68,11 @@ enum bpf_enum_value_kind {
const void *p = (const void *)s + __CORE_RELO(s, field, BYTE_OFFSET); \ const void *p = (const void *)s + __CORE_RELO(s, field, BYTE_OFFSET); \
unsigned long long val; \ unsigned long long val; \
\ \
/* This is a so-called barrier_var() operation that makes specified \
* variable "a black box" for optimizing compiler. \
* It forces compiler to perform BYTE_OFFSET relocation on p and use \
* its calculated value in the switch below, instead of applying \
* the same relocation 4 times for each individual memory load. \
*/ \
asm volatile("" : "=r"(p) : "0"(p)); \
\
switch (__CORE_RELO(s, field, BYTE_SIZE)) { \ switch (__CORE_RELO(s, field, BYTE_SIZE)) { \
case 1: val = *(const unsigned char *)p; break; \ case 1: val = *(const unsigned char *)p; \
case 2: val = *(const unsigned short *)p; break; \ case 2: val = *(const unsigned short *)p; \
case 4: val = *(const unsigned int *)p; break; \ case 4: val = *(const unsigned int *)p; \
case 8: val = *(const unsigned long long *)p; break; \ case 8: val = *(const unsigned long long *)p; \
} \ } \
val <<= __CORE_RELO(s, field, LSHIFT_U64); \ val <<= __CORE_RELO(s, field, LSHIFT_U64); \
if (__CORE_RELO(s, field, SIGNED)) \ if (__CORE_RELO(s, field, SIGNED)) \
@@ -120,75 +92,15 @@ enum bpf_enum_value_kind {
__builtin_preserve_field_info(field, BPF_FIELD_EXISTS) __builtin_preserve_field_info(field, BPF_FIELD_EXISTS)
/* /*
* Convenience macro to get the byte size of a field. Works for integers, * Convenience macro to get byte size of a field. Works for integers,
* struct/unions, pointers, arrays, and enums. * struct/unions, pointers, arrays, and enums.
*/ */
#define bpf_core_field_size(field) \ #define bpf_core_field_size(field) \
__builtin_preserve_field_info(field, BPF_FIELD_BYTE_SIZE) __builtin_preserve_field_info(field, BPF_FIELD_BYTE_SIZE)
/* /*
* Convenience macro to get BTF type ID of a specified type, using a local BTF * bpf_core_read() abstracts away bpf_probe_read() call and captures offset
* information. Return 32-bit unsigned integer with type ID from program's own * relocation for source address using __builtin_preserve_access_index()
* BTF. Always succeeds.
*/
#define bpf_core_type_id_local(type) \
__builtin_btf_type_id(*(typeof(type) *)0, BPF_TYPE_ID_LOCAL)
/*
* Convenience macro to get BTF type ID of a target kernel's type that matches
* specified local type.
* Returns:
* - valid 32-bit unsigned type ID in kernel BTF;
* - 0, if no matching type was found in a target kernel BTF.
*/
#define bpf_core_type_id_kernel(type) \
__builtin_btf_type_id(*(typeof(type) *)0, BPF_TYPE_ID_TARGET)
/*
* Convenience macro to check that provided named type
* (struct/union/enum/typedef) exists in a target kernel.
* Returns:
* 1, if such type is present in target kernel's BTF;
* 0, if no matching type is found.
*/
#define bpf_core_type_exists(type) \
__builtin_preserve_type_info(*(typeof(type) *)0, BPF_TYPE_EXISTS)
/*
* Convenience macro to get the byte size of a provided named type
* (struct/union/enum/typedef) in a target kernel.
* Returns:
* >= 0 size (in bytes), if type is present in target kernel's BTF;
* 0, if no matching type is found.
*/
#define bpf_core_type_size(type) \
__builtin_preserve_type_info(*(typeof(type) *)0, BPF_TYPE_SIZE)
/*
* Convenience macro to check that provided enumerator value is defined in
* a target kernel.
* Returns:
* 1, if specified enum type and its enumerator value are present in target
* kernel's BTF;
* 0, if no matching enum and/or enum value within that enum is found.
*/
#define bpf_core_enum_value_exists(enum_type, enum_value) \
__builtin_preserve_enum_value(*(typeof(enum_type) *)enum_value, BPF_ENUMVAL_EXISTS)
/*
* Convenience macro to get the integer value of an enumerator value in
* a target kernel.
* Returns:
* 64-bit value, if specified enum type and its enumerator value are
* present in target kernel's BTF;
* 0, if no matching enum and/or enum value within that enum is found.
*/
#define bpf_core_enum_value(enum_type, enum_value) \
__builtin_preserve_enum_value(*(typeof(enum_type) *)enum_value, BPF_ENUMVAL_VALUE)
/*
* bpf_core_read() abstracts away bpf_probe_read_kernel() call and captures
* offset relocation for source address using __builtin_preserve_access_index()
* built-in, provided by Clang. * built-in, provided by Clang.
* *
* __builtin_preserve_access_index() takes as an argument an expression of * __builtin_preserve_access_index() takes as an argument an expression of
@@ -203,22 +115,17 @@ enum bpf_enum_value_kind {
* (local) BTF, used to record relocation. * (local) BTF, used to record relocation.
*/ */
#define bpf_core_read(dst, sz, src) \ #define bpf_core_read(dst, sz, src) \
bpf_probe_read_kernel(dst, sz, (const void *)__builtin_preserve_access_index(src)) bpf_probe_read(dst, sz, \
(const void *)__builtin_preserve_access_index(src))
/* NOTE: see comments for BPF_CORE_READ_USER() about the proper types use. */
#define bpf_core_read_user(dst, sz, src) \
bpf_probe_read_user(dst, sz, (const void *)__builtin_preserve_access_index(src))
/* /*
* bpf_core_read_str() is a thin wrapper around bpf_probe_read_str() * bpf_core_read_str() is a thin wrapper around bpf_probe_read_str()
* additionally emitting BPF CO-RE field relocation for specified source * additionally emitting BPF CO-RE field relocation for specified source
* argument. * argument.
*/ */
#define bpf_core_read_str(dst, sz, src) \ #define bpf_core_read_str(dst, sz, src) \
bpf_probe_read_kernel_str(dst, sz, (const void *)__builtin_preserve_access_index(src)) bpf_probe_read_str(dst, sz, \
(const void *)__builtin_preserve_access_index(src))
/* NOTE: see comments for BPF_CORE_READ_USER() about the proper types use. */
#define bpf_core_read_user_str(dst, sz, src) \
bpf_probe_read_user_str(dst, sz, (const void *)__builtin_preserve_access_index(src))
#define ___concat(a, b) a ## b #define ___concat(a, b) a ## b
#define ___apply(fn, n) ___concat(fn, n) #define ___apply(fn, n) ___concat(fn, n)
@@ -277,29 +184,30 @@ enum bpf_enum_value_kind {
read_fn((void *)(dst), sizeof(*(dst)), &((src_type)(src))->accessor) read_fn((void *)(dst), sizeof(*(dst)), &((src_type)(src))->accessor)
/* "recursively" read a sequence of inner pointers using local __t var */ /* "recursively" read a sequence of inner pointers using local __t var */
#define ___rd_first(fn, src, a) ___read(fn, &__t, ___type(src), src, a); #define ___rd_first(src, a) ___read(bpf_core_read, &__t, ___type(src), src, a);
#define ___rd_last(fn, ...) \ #define ___rd_last(...) \
___read(fn, &__t, ___type(___nolast(__VA_ARGS__)), __t, ___last(__VA_ARGS__)); ___read(bpf_core_read, &__t, \
#define ___rd_p1(fn, ...) const void *__t; ___rd_first(fn, __VA_ARGS__) ___type(___nolast(__VA_ARGS__)), __t, ___last(__VA_ARGS__));
#define ___rd_p2(fn, ...) ___rd_p1(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__) #define ___rd_p1(...) const void *__t; ___rd_first(__VA_ARGS__)
#define ___rd_p3(fn, ...) ___rd_p2(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__) #define ___rd_p2(...) ___rd_p1(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__)
#define ___rd_p4(fn, ...) ___rd_p3(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__) #define ___rd_p3(...) ___rd_p2(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__)
#define ___rd_p5(fn, ...) ___rd_p4(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__) #define ___rd_p4(...) ___rd_p3(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__)
#define ___rd_p6(fn, ...) ___rd_p5(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__) #define ___rd_p5(...) ___rd_p4(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__)
#define ___rd_p7(fn, ...) ___rd_p6(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__) #define ___rd_p6(...) ___rd_p5(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__)
#define ___rd_p8(fn, ...) ___rd_p7(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__) #define ___rd_p7(...) ___rd_p6(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__)
#define ___rd_p9(fn, ...) ___rd_p8(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__) #define ___rd_p8(...) ___rd_p7(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__)
#define ___read_ptrs(fn, src, ...) \ #define ___rd_p9(...) ___rd_p8(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__)
___apply(___rd_p, ___narg(__VA_ARGS__))(fn, src, __VA_ARGS__) #define ___read_ptrs(src, ...) \
___apply(___rd_p, ___narg(__VA_ARGS__))(src, __VA_ARGS__)
#define ___core_read0(fn, fn_ptr, dst, src, a) \ #define ___core_read0(fn, dst, src, a) \
___read(fn, dst, ___type(src), src, a); ___read(fn, dst, ___type(src), src, a);
#define ___core_readN(fn, fn_ptr, dst, src, ...) \ #define ___core_readN(fn, dst, src, ...) \
___read_ptrs(fn_ptr, src, ___nolast(__VA_ARGS__)) \ ___read_ptrs(src, ___nolast(__VA_ARGS__)) \
___read(fn, dst, ___type(src, ___nolast(__VA_ARGS__)), __t, \ ___read(fn, dst, ___type(src, ___nolast(__VA_ARGS__)), __t, \
___last(__VA_ARGS__)); ___last(__VA_ARGS__));
#define ___core_read(fn, fn_ptr, dst, src, a, ...) \ #define ___core_read(fn, dst, src, a, ...) \
___apply(___core_read, ___empty(__VA_ARGS__))(fn, fn_ptr, dst, \ ___apply(___core_read, ___empty(__VA_ARGS__))(fn, dst, \
src, a, ##__VA_ARGS__) src, a, ##__VA_ARGS__)
/* /*
@@ -307,73 +215,20 @@ enum bpf_enum_value_kind {
* BPF_CORE_READ(), in which final field is read into user-provided storage. * BPF_CORE_READ(), in which final field is read into user-provided storage.
* See BPF_CORE_READ() below for more details on general usage. * See BPF_CORE_READ() below for more details on general usage.
*/ */
#define BPF_CORE_READ_INTO(dst, src, a, ...) ({ \ #define BPF_CORE_READ_INTO(dst, src, a, ...) \
___core_read(bpf_core_read, bpf_core_read, \ ({ \
dst, (src), a, ##__VA_ARGS__) \ ___core_read(bpf_core_read, dst, src, a, ##__VA_ARGS__) \
}) })
/*
* Variant of BPF_CORE_READ_INTO() for reading from user-space memory.
*
* NOTE: see comments for BPF_CORE_READ_USER() about the proper types use.
*/
#define BPF_CORE_READ_USER_INTO(dst, src, a, ...) ({ \
___core_read(bpf_core_read_user, bpf_core_read_user, \
dst, (src), a, ##__VA_ARGS__) \
})
/* Non-CO-RE variant of BPF_CORE_READ_INTO() */
#define BPF_PROBE_READ_INTO(dst, src, a, ...) ({ \
___core_read(bpf_probe_read, bpf_probe_read, \
dst, (src), a, ##__VA_ARGS__) \
})
/* Non-CO-RE variant of BPF_CORE_READ_USER_INTO().
*
* As no CO-RE relocations are emitted, source types can be arbitrary and are
* not restricted to kernel types only.
*/
#define BPF_PROBE_READ_USER_INTO(dst, src, a, ...) ({ \
___core_read(bpf_probe_read_user, bpf_probe_read_user, \
dst, (src), a, ##__VA_ARGS__) \
})
/* /*
* BPF_CORE_READ_STR_INTO() does same "pointer chasing" as * BPF_CORE_READ_STR_INTO() does same "pointer chasing" as
* BPF_CORE_READ() for intermediate pointers, but then executes (and returns * BPF_CORE_READ() for intermediate pointers, but then executes (and returns
* corresponding error code) bpf_core_read_str() for final string read. * corresponding error code) bpf_core_read_str() for final string read.
*/ */
#define BPF_CORE_READ_STR_INTO(dst, src, a, ...) ({ \ #define BPF_CORE_READ_STR_INTO(dst, src, a, ...) \
___core_read(bpf_core_read_str, bpf_core_read, \ ({ \
dst, (src), a, ##__VA_ARGS__) \ ___core_read(bpf_core_read_str, dst, src, a, ##__VA_ARGS__) \
}) })
/*
* Variant of BPF_CORE_READ_STR_INTO() for reading from user-space memory.
*
* NOTE: see comments for BPF_CORE_READ_USER() about the proper types use.
*/
#define BPF_CORE_READ_USER_STR_INTO(dst, src, a, ...) ({ \
___core_read(bpf_core_read_user_str, bpf_core_read_user, \
dst, (src), a, ##__VA_ARGS__) \
})
/* Non-CO-RE variant of BPF_CORE_READ_STR_INTO() */
#define BPF_PROBE_READ_STR_INTO(dst, src, a, ...) ({ \
___core_read(bpf_probe_read_str, bpf_probe_read, \
dst, (src), a, ##__VA_ARGS__) \
})
/*
* Non-CO-RE variant of BPF_CORE_READ_USER_STR_INTO().
*
* As no CO-RE relocations are emitted, source types can be arbitrary and are
* not restricted to kernel types only.
*/
#define BPF_PROBE_READ_USER_STR_INTO(dst, src, a, ...) ({ \
___core_read(bpf_probe_read_user_str, bpf_probe_read_user, \
dst, (src), a, ##__VA_ARGS__) \
})
/* /*
* BPF_CORE_READ() is used to simplify BPF CO-RE relocatable read, especially * BPF_CORE_READ() is used to simplify BPF CO-RE relocatable read, especially
@@ -384,61 +239,25 @@ enum bpf_enum_value_kind {
* int x = BPF_CORE_READ(s, a.b.c, d.e, f, g); * int x = BPF_CORE_READ(s, a.b.c, d.e, f, g);
* *
* BPF_CORE_READ will decompose above statement into 4 bpf_core_read (BPF * BPF_CORE_READ will decompose above statement into 4 bpf_core_read (BPF
* CO-RE relocatable bpf_probe_read_kernel() wrapper) calls, logically * CO-RE relocatable bpf_probe_read() wrapper) calls, logically equivalent to:
* equivalent to:
* 1. const void *__t = s->a.b.c; * 1. const void *__t = s->a.b.c;
* 2. __t = __t->d.e; * 2. __t = __t->d.e;
* 3. __t = __t->f; * 3. __t = __t->f;
* 4. return __t->g; * 4. return __t->g;
* *
* Equivalence is logical, because there is a heavy type casting/preservation * Equivalence is logical, because there is a heavy type casting/preservation
* involved, as well as all the reads are happening through * involved, as well as all the reads are happening through bpf_probe_read()
* bpf_probe_read_kernel() calls using __builtin_preserve_access_index() to * calls using __builtin_preserve_access_index() to emit CO-RE relocations.
* emit CO-RE relocations.
* *
* N.B. Only up to 9 "field accessors" are supported, which should be more * N.B. Only up to 9 "field accessors" are supported, which should be more
* than enough for any practical purpose. * than enough for any practical purpose.
*/ */
#define BPF_CORE_READ(src, a, ...) ({ \ #define BPF_CORE_READ(src, a, ...) \
___type((src), a, ##__VA_ARGS__) __r; \ ({ \
BPF_CORE_READ_INTO(&__r, (src), a, ##__VA_ARGS__); \ ___type(src, a, ##__VA_ARGS__) __r; \
__r; \ BPF_CORE_READ_INTO(&__r, src, a, ##__VA_ARGS__); \
}) __r; \
})
/*
* Variant of BPF_CORE_READ() for reading from user-space memory.
*
* NOTE: all the source types involved are still *kernel types* and need to
* exist in kernel (or kernel module) BTF, otherwise CO-RE relocation will
* fail. Custom user types are not relocatable with CO-RE.
* The typical situation in which BPF_CORE_READ_USER() might be used is to
* read kernel UAPI types from the user-space memory passed in as a syscall
* input argument.
*/
#define BPF_CORE_READ_USER(src, a, ...) ({ \
___type((src), a, ##__VA_ARGS__) __r; \
BPF_CORE_READ_USER_INTO(&__r, (src), a, ##__VA_ARGS__); \
__r; \
})
/* Non-CO-RE variant of BPF_CORE_READ() */
#define BPF_PROBE_READ(src, a, ...) ({ \
___type((src), a, ##__VA_ARGS__) __r; \
BPF_PROBE_READ_INTO(&__r, (src), a, ##__VA_ARGS__); \
__r; \
})
/*
* Non-CO-RE variant of BPF_CORE_READ_USER().
*
* As no CO-RE relocations are emitted, source types can be arbitrary and are
* not restricted to kernel types only.
*/
#define BPF_PROBE_READ_USER(src, a, ...) ({ \
___type((src), a, ##__VA_ARGS__) __r; \
BPF_PROBE_READ_USER_INTO(&__r, (src), a, ##__VA_ARGS__); \
__r; \
})
#endif #endif

View File

@@ -2,35 +2,8 @@
#ifndef __BPF_ENDIAN__ #ifndef __BPF_ENDIAN__
#define __BPF_ENDIAN__ #define __BPF_ENDIAN__
/* #include <linux/stddef.h>
* Isolate byte #n and put it into byte #m, for __u##b type. #include <linux/swab.h>
* E.g., moving byte #6 (nnnnnnnn) into byte #1 (mmmmmmmm) for __u64:
* 1) xxxxxxxx nnnnnnnn xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx mmmmmmmm xxxxxxxx
* 2) nnnnnnnn xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx mmmmmmmm xxxxxxxx 00000000
* 3) 00000000 00000000 00000000 00000000 00000000 00000000 00000000 nnnnnnnn
* 4) 00000000 00000000 00000000 00000000 00000000 00000000 nnnnnnnn 00000000
*/
#define ___bpf_mvb(x, b, n, m) ((__u##b)(x) << (b-(n+1)*8) >> (b-8) << (m*8))
#define ___bpf_swab16(x) ((__u16)( \
___bpf_mvb(x, 16, 0, 1) | \
___bpf_mvb(x, 16, 1, 0)))
#define ___bpf_swab32(x) ((__u32)( \
___bpf_mvb(x, 32, 0, 3) | \
___bpf_mvb(x, 32, 1, 2) | \
___bpf_mvb(x, 32, 2, 1) | \
___bpf_mvb(x, 32, 3, 0)))
#define ___bpf_swab64(x) ((__u64)( \
___bpf_mvb(x, 64, 0, 7) | \
___bpf_mvb(x, 64, 1, 6) | \
___bpf_mvb(x, 64, 2, 5) | \
___bpf_mvb(x, 64, 3, 4) | \
___bpf_mvb(x, 64, 4, 3) | \
___bpf_mvb(x, 64, 5, 2) | \
___bpf_mvb(x, 64, 6, 1) | \
___bpf_mvb(x, 64, 7, 0)))
/* LLVM's BPF target selects the endianness of the CPU /* LLVM's BPF target selects the endianness of the CPU
* it compiles on, or the user specifies (bpfel/bpfeb), * it compiles on, or the user specifies (bpfel/bpfeb),
@@ -50,16 +23,16 @@
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define __bpf_ntohs(x) __builtin_bswap16(x) # define __bpf_ntohs(x) __builtin_bswap16(x)
# define __bpf_htons(x) __builtin_bswap16(x) # define __bpf_htons(x) __builtin_bswap16(x)
# define __bpf_constant_ntohs(x) ___bpf_swab16(x) # define __bpf_constant_ntohs(x) ___constant_swab16(x)
# define __bpf_constant_htons(x) ___bpf_swab16(x) # define __bpf_constant_htons(x) ___constant_swab16(x)
# define __bpf_ntohl(x) __builtin_bswap32(x) # define __bpf_ntohl(x) __builtin_bswap32(x)
# define __bpf_htonl(x) __builtin_bswap32(x) # define __bpf_htonl(x) __builtin_bswap32(x)
# define __bpf_constant_ntohl(x) ___bpf_swab32(x) # define __bpf_constant_ntohl(x) ___constant_swab32(x)
# define __bpf_constant_htonl(x) ___bpf_swab32(x) # define __bpf_constant_htonl(x) ___constant_swab32(x)
# define __bpf_be64_to_cpu(x) __builtin_bswap64(x) # define __bpf_be64_to_cpu(x) __builtin_bswap64(x)
# define __bpf_cpu_to_be64(x) __builtin_bswap64(x) # define __bpf_cpu_to_be64(x) __builtin_bswap64(x)
# define __bpf_constant_be64_to_cpu(x) ___bpf_swab64(x) # define __bpf_constant_be64_to_cpu(x) ___constant_swab64(x)
# define __bpf_constant_cpu_to_be64(x) ___bpf_swab64(x) # define __bpf_constant_cpu_to_be64(x) ___constant_swab64(x)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define __bpf_ntohs(x) (x) # define __bpf_ntohs(x) (x)
# define __bpf_htons(x) (x) # define __bpf_htons(x) (x)

View File

@@ -1,55 +0,0 @@
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
/* Copyright (c) 2021 Facebook */
#ifndef __BPF_GEN_INTERNAL_H
#define __BPF_GEN_INTERNAL_H
struct ksym_relo_desc {
const char *name;
int kind;
int insn_idx;
bool is_weak;
};
struct ksym_desc {
const char *name;
int ref;
int kind;
int off;
int insn;
};
struct bpf_gen {
struct gen_loader_opts *opts;
void *data_start;
void *data_cur;
void *insn_start;
void *insn_cur;
ssize_t cleanup_label;
__u32 nr_progs;
__u32 nr_maps;
int log_level;
int error;
struct ksym_relo_desc *relos;
int relo_cnt;
char attach_target[128];
int attach_kind;
struct ksym_desc *ksyms;
__u32 nr_ksyms;
int fd_array;
int nr_fd_array;
};
void bpf_gen__init(struct bpf_gen *gen, int log_level);
int bpf_gen__finish(struct bpf_gen *gen);
void bpf_gen__free(struct bpf_gen *gen);
void bpf_gen__load_btf(struct bpf_gen *gen, const void *raw_data, __u32 raw_size);
void bpf_gen__map_create(struct bpf_gen *gen, struct bpf_create_map_attr *map_attr, int map_idx);
struct bpf_prog_load_params;
void bpf_gen__prog_load(struct bpf_gen *gen, struct bpf_prog_load_params *load_attr, int prog_idx);
void bpf_gen__map_update_elem(struct bpf_gen *gen, int map_idx, void *value, __u32 value_size);
void bpf_gen__map_freeze(struct bpf_gen *gen, int map_idx);
void bpf_gen__record_attach_target(struct bpf_gen *gen, const char *name, enum bpf_attach_type type);
void bpf_gen__record_extern(struct bpf_gen *gen, const char *name, bool is_weak, int kind,
int insn_idx);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -14,58 +14,33 @@
#define __type(name, val) typeof(val) *name #define __type(name, val) typeof(val) *name
#define __array(name, val) typeof(val) *name[] #define __array(name, val) typeof(val) *name[]
/* Helper macro to print out debug messages */
#define bpf_printk(fmt, ...) \
({ \
char ____fmt[] = fmt; \
bpf_trace_printk(____fmt, sizeof(____fmt), \
##__VA_ARGS__); \
})
/* /*
* Helper macro to place programs, maps, license in * Helper macro to place programs, maps, license in
* different sections in elf_bpf file. Section names * different sections in elf_bpf file. Section names
* are interpreted by libbpf depending on the context (BPF programs, BPF maps, * are interpreted by elf_bpf loader
* extern variables, etc).
* To allow use of SEC() with externs (e.g., for extern .maps declarations),
* make sure __attribute__((unused)) doesn't trigger compilation warning.
*/ */
#define SEC(name) \ #define SEC(NAME) __attribute__((section(NAME), used))
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wignored-attributes\"") \
__attribute__((section(name), used)) \
_Pragma("GCC diagnostic pop") \
/* Avoid 'linux/stddef.h' definition of '__always_inline'. */ #ifndef __always_inline
#undef __always_inline #define __always_inline __attribute__((always_inline))
#define __always_inline inline __attribute__((always_inline))
#ifndef __noinline
#define __noinline __attribute__((noinline))
#endif #endif
#ifndef __weak #ifndef __weak
#define __weak __attribute__((weak)) #define __weak __attribute__((weak))
#endif #endif
/* /*
* Use __hidden attribute to mark a non-static BPF subprogram effectively * Helper macro to manipulate data structures
* static for BPF verifier's verification algorithm purposes, allowing more
* extensive and permissive BPF verification process, taking into account
* subprogram's caller context.
*/
#define __hidden __attribute__((visibility("hidden")))
/* When utilizing vmlinux.h with BPF CO-RE, user BPF programs can't include
* any system-level headers (such as stddef.h, linux/version.h, etc), and
* commonly-used macros like NULL and KERNEL_VERSION aren't available through
* vmlinux.h. This just adds unnecessary hurdles and forces users to re-define
* them on their own. So as a convenience, provide such definitions here.
*/
#ifndef NULL
#define NULL ((void *)0)
#endif
#ifndef KERNEL_VERSION
#define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + ((c) > 255 ? 255 : (c)))
#endif
/*
* Helper macros to manipulate data structures
*/ */
#ifndef offsetof #ifndef offsetof
#define offsetof(TYPE, MEMBER) ((unsigned long)&((TYPE *)0)->MEMBER) #define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
#endif #endif
#ifndef container_of #ifndef container_of
#define container_of(ptr, type, member) \ #define container_of(ptr, type, member) \
@@ -75,54 +50,6 @@
}) })
#endif #endif
/*
* Helper macro to throw a compilation error if __bpf_unreachable() gets
* built into the resulting code. This works given BPF back end does not
* implement __builtin_trap(). This is useful to assert that certain paths
* of the program code are never used and hence eliminated by the compiler.
*
* For example, consider a switch statement that covers known cases used by
* the program. __bpf_unreachable() can then reside in the default case. If
* the program gets extended such that a case is not covered in the switch
* statement, then it will throw a build error due to the default case not
* being compiled out.
*/
#ifndef __bpf_unreachable
# define __bpf_unreachable() __builtin_trap()
#endif
/*
* Helper function to perform a tail call with a constant/immediate map slot.
*/
#if __clang_major__ >= 8 && defined(__bpf__)
static __always_inline void
bpf_tail_call_static(void *ctx, const void *map, const __u32 slot)
{
if (!__builtin_constant_p(slot))
__bpf_unreachable();
/*
* Provide a hard guarantee that LLVM won't optimize setting r2 (map
* pointer) and r3 (constant map index) from _different paths_ ending
* up at the _same_ call insn as otherwise we won't be able to use the
* jmpq/nopl retpoline-free patching by the x86-64 JIT in the kernel
* given they mismatch. See also d2e4c1e6c294 ("bpf: Constant map key
* tracking for prog array pokes") for details on verifier tracking.
*
* Note on clobber list: we need to stay in-line with BPF calling
* convention, so even if we don't end up using r0, r4, r5, we need
* to mark them as clobber so that LLVM doesn't end up using them
* before / after the call.
*/
asm volatile("r1 = %[ctx]\n\t"
"r2 = %[map]\n\t"
"r3 = %[slot]\n\t"
"call 12"
:: [ctx]"r"(ctx), [map]"r"(map), [slot]"i"(slot)
: "r0", "r1", "r2", "r3", "r4", "r5");
}
#endif
/* /*
* Helper structure used by eBPF C program * Helper structure used by eBPF C program
* to describe BPF map attributes to libbpf loader * to describe BPF map attributes to libbpf loader
@@ -148,115 +75,5 @@ enum libbpf_tristate {
}; };
#define __kconfig __attribute__((section(".kconfig"))) #define __kconfig __attribute__((section(".kconfig")))
#define __ksym __attribute__((section(".ksyms")))
#ifndef ___bpf_concat
#define ___bpf_concat(a, b) a ## b
#endif
#ifndef ___bpf_apply
#define ___bpf_apply(fn, n) ___bpf_concat(fn, n)
#endif
#ifndef ___bpf_nth
#define ___bpf_nth(_, _1, _2, _3, _4, _5, _6, _7, _8, _9, _a, _b, _c, N, ...) N
#endif
#ifndef ___bpf_narg
#define ___bpf_narg(...) \
___bpf_nth(_, ##__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#endif
#define ___bpf_fill0(arr, p, x) do {} while (0)
#define ___bpf_fill1(arr, p, x) arr[p] = x
#define ___bpf_fill2(arr, p, x, args...) arr[p] = x; ___bpf_fill1(arr, p + 1, args)
#define ___bpf_fill3(arr, p, x, args...) arr[p] = x; ___bpf_fill2(arr, p + 1, args)
#define ___bpf_fill4(arr, p, x, args...) arr[p] = x; ___bpf_fill3(arr, p + 1, args)
#define ___bpf_fill5(arr, p, x, args...) arr[p] = x; ___bpf_fill4(arr, p + 1, args)
#define ___bpf_fill6(arr, p, x, args...) arr[p] = x; ___bpf_fill5(arr, p + 1, args)
#define ___bpf_fill7(arr, p, x, args...) arr[p] = x; ___bpf_fill6(arr, p + 1, args)
#define ___bpf_fill8(arr, p, x, args...) arr[p] = x; ___bpf_fill7(arr, p + 1, args)
#define ___bpf_fill9(arr, p, x, args...) arr[p] = x; ___bpf_fill8(arr, p + 1, args)
#define ___bpf_fill10(arr, p, x, args...) arr[p] = x; ___bpf_fill9(arr, p + 1, args)
#define ___bpf_fill11(arr, p, x, args...) arr[p] = x; ___bpf_fill10(arr, p + 1, args)
#define ___bpf_fill12(arr, p, x, args...) arr[p] = x; ___bpf_fill11(arr, p + 1, args)
#define ___bpf_fill(arr, args...) \
___bpf_apply(___bpf_fill, ___bpf_narg(args))(arr, 0, args)
/*
* BPF_SEQ_PRINTF to wrap bpf_seq_printf to-be-printed values
* in a structure.
*/
#define BPF_SEQ_PRINTF(seq, fmt, args...) \
({ \
static const char ___fmt[] = fmt; \
unsigned long long ___param[___bpf_narg(args)]; \
\
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
___bpf_fill(___param, args); \
_Pragma("GCC diagnostic pop") \
\
bpf_seq_printf(seq, ___fmt, sizeof(___fmt), \
___param, sizeof(___param)); \
})
/*
* BPF_SNPRINTF wraps the bpf_snprintf helper with variadic arguments instead of
* an array of u64.
*/
#define BPF_SNPRINTF(out, out_size, fmt, args...) \
({ \
static const char ___fmt[] = fmt; \
unsigned long long ___param[___bpf_narg(args)]; \
\
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
___bpf_fill(___param, args); \
_Pragma("GCC diagnostic pop") \
\
bpf_snprintf(out, out_size, ___fmt, \
___param, sizeof(___param)); \
})
#ifdef BPF_NO_GLOBAL_DATA
#define BPF_PRINTK_FMT_MOD
#else
#define BPF_PRINTK_FMT_MOD static const
#endif
#define __bpf_printk(fmt, ...) \
({ \
BPF_PRINTK_FMT_MOD char ____fmt[] = fmt; \
bpf_trace_printk(____fmt, sizeof(____fmt), \
##__VA_ARGS__); \
})
/*
* __bpf_vprintk wraps the bpf_trace_vprintk helper with variadic arguments
* instead of an array of u64.
*/
#define __bpf_vprintk(fmt, args...) \
({ \
static const char ___fmt[] = fmt; \
unsigned long long ___param[___bpf_narg(args)]; \
\
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
___bpf_fill(___param, args); \
_Pragma("GCC diagnostic pop") \
\
bpf_trace_vprintk(___fmt, sizeof(___fmt), \
___param, sizeof(___param)); \
})
/* Use __bpf_printk when bpf_printk call has 3 or fewer fmt args
* Otherwise use __bpf_vprintk
*/
#define ___bpf_pick_printk(...) \
___bpf_nth(_, ##__VA_ARGS__, __bpf_vprintk, __bpf_vprintk, __bpf_vprintk, \
__bpf_vprintk, __bpf_vprintk, __bpf_vprintk, __bpf_vprintk, \
__bpf_vprintk, __bpf_vprintk, __bpf_printk /*3*/, __bpf_printk /*2*/,\
__bpf_printk /*1*/, __bpf_printk /*0*/)
/* Helper macro to print out debug messages */
#define bpf_printk(fmt, args...) ___bpf_pick_printk(args)(fmt, ##args)
#endif #endif

View File

@@ -8,6 +8,9 @@
#include "libbpf.h" #include "libbpf.h"
#include "libbpf_internal.h" #include "libbpf_internal.h"
/* make sure libbpf doesn't use kernel-only integer typedefs */
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
struct bpf_prog_linfo { struct bpf_prog_linfo {
void *raw_linfo; void *raw_linfo;
void *raw_jited_linfo; void *raw_jited_linfo;
@@ -106,7 +109,7 @@ struct bpf_prog_linfo *bpf_prog_linfo__new(const struct bpf_prog_info *info)
nr_linfo = info->nr_line_info; nr_linfo = info->nr_line_info;
if (!nr_linfo) if (!nr_linfo)
return errno = EINVAL, NULL; return NULL;
/* /*
* The min size that bpf_prog_linfo has to access for * The min size that bpf_prog_linfo has to access for
@@ -114,11 +117,11 @@ struct bpf_prog_linfo *bpf_prog_linfo__new(const struct bpf_prog_info *info)
*/ */
if (info->line_info_rec_size < if (info->line_info_rec_size <
offsetof(struct bpf_line_info, file_name_off)) offsetof(struct bpf_line_info, file_name_off))
return errno = EINVAL, NULL; return NULL;
prog_linfo = calloc(1, sizeof(*prog_linfo)); prog_linfo = calloc(1, sizeof(*prog_linfo));
if (!prog_linfo) if (!prog_linfo)
return errno = ENOMEM, NULL; return NULL;
/* Copy xlated line_info */ /* Copy xlated line_info */
prog_linfo->nr_linfo = nr_linfo; prog_linfo->nr_linfo = nr_linfo;
@@ -174,7 +177,7 @@ struct bpf_prog_linfo *bpf_prog_linfo__new(const struct bpf_prog_info *info)
err_free: err_free:
bpf_prog_linfo__free(prog_linfo); bpf_prog_linfo__free(prog_linfo);
return errno = EINVAL, NULL; return NULL;
} }
const struct bpf_line_info * const struct bpf_line_info *
@@ -186,11 +189,11 @@ bpf_prog_linfo__lfind_addr_func(const struct bpf_prog_linfo *prog_linfo,
const __u64 *jited_linfo; const __u64 *jited_linfo;
if (func_idx >= prog_linfo->nr_jited_func) if (func_idx >= prog_linfo->nr_jited_func)
return errno = ENOENT, NULL; return NULL;
nr_linfo = prog_linfo->nr_jited_linfo_per_func[func_idx]; nr_linfo = prog_linfo->nr_jited_linfo_per_func[func_idx];
if (nr_skip >= nr_linfo) if (nr_skip >= nr_linfo)
return errno = ENOENT, NULL; return NULL;
start = prog_linfo->jited_linfo_func_idx[func_idx] + nr_skip; start = prog_linfo->jited_linfo_func_idx[func_idx] + nr_skip;
jited_rec_size = prog_linfo->jited_rec_size; jited_rec_size = prog_linfo->jited_rec_size;
@@ -198,7 +201,7 @@ bpf_prog_linfo__lfind_addr_func(const struct bpf_prog_linfo *prog_linfo,
(start * jited_rec_size); (start * jited_rec_size);
jited_linfo = raw_jited_linfo; jited_linfo = raw_jited_linfo;
if (addr < *jited_linfo) if (addr < *jited_linfo)
return errno = ENOENT, NULL; return NULL;
nr_linfo -= nr_skip; nr_linfo -= nr_skip;
rec_size = prog_linfo->rec_size; rec_size = prog_linfo->rec_size;
@@ -225,13 +228,13 @@ bpf_prog_linfo__lfind(const struct bpf_prog_linfo *prog_linfo,
nr_linfo = prog_linfo->nr_linfo; nr_linfo = prog_linfo->nr_linfo;
if (nr_skip >= nr_linfo) if (nr_skip >= nr_linfo)
return errno = ENOENT, NULL; return NULL;
rec_size = prog_linfo->rec_size; rec_size = prog_linfo->rec_size;
raw_linfo = prog_linfo->raw_linfo + (nr_skip * rec_size); raw_linfo = prog_linfo->raw_linfo + (nr_skip * rec_size);
linfo = raw_linfo; linfo = raw_linfo;
if (insn_off < linfo->insn_off) if (insn_off < linfo->insn_off)
return errno = ENOENT, NULL; return NULL;
nr_linfo -= nr_skip; nr_linfo -= nr_skip;
for (i = 0; i < nr_linfo; i++) { for (i = 0; i < nr_linfo; i++) {

View File

@@ -25,35 +25,26 @@
#define bpf_target_sparc #define bpf_target_sparc
#define bpf_target_defined #define bpf_target_defined
#else #else
#undef bpf_target_defined
/* Fall back to what the compiler says */
#if defined(__x86_64__)
#define bpf_target_x86
#define bpf_target_defined
#elif defined(__s390__)
#define bpf_target_s390
#define bpf_target_defined
#elif defined(__arm__)
#define bpf_target_arm
#define bpf_target_defined
#elif defined(__aarch64__)
#define bpf_target_arm64
#define bpf_target_defined
#elif defined(__mips__)
#define bpf_target_mips
#define bpf_target_defined
#elif defined(__powerpc__)
#define bpf_target_powerpc
#define bpf_target_defined
#elif defined(__sparc__)
#define bpf_target_sparc
#define bpf_target_defined
#endif /* no compiler target */
#endif #endif
#ifndef __BPF_TARGET_MISSING /* Fall back to what the compiler says */
#define __BPF_TARGET_MISSING "GCC error \"Must specify a BPF target arch via __TARGET_ARCH_xxx\"" #ifndef bpf_target_defined
#if defined(__x86_64__)
#define bpf_target_x86
#elif defined(__s390__)
#define bpf_target_s390
#elif defined(__arm__)
#define bpf_target_arm
#elif defined(__aarch64__)
#define bpf_target_arm64
#elif defined(__mips__)
#define bpf_target_mips
#elif defined(__powerpc__)
#define bpf_target_powerpc
#elif defined(__sparc__)
#define bpf_target_sparc
#endif
#endif #endif
#if defined(bpf_target_x86) #if defined(bpf_target_x86)
@@ -224,7 +215,7 @@ struct pt_regs;
#define PT_REGS_PARM5(x) ((x)->regs[8]) #define PT_REGS_PARM5(x) ((x)->regs[8])
#define PT_REGS_RET(x) ((x)->regs[31]) #define PT_REGS_RET(x) ((x)->regs[31])
#define PT_REGS_FP(x) ((x)->regs[30]) /* Works only with CONFIG_FRAME_POINTER */ #define PT_REGS_FP(x) ((x)->regs[30]) /* Works only with CONFIG_FRAME_POINTER */
#define PT_REGS_RC(x) ((x)->regs[2]) #define PT_REGS_RC(x) ((x)->regs[1])
#define PT_REGS_SP(x) ((x)->regs[29]) #define PT_REGS_SP(x) ((x)->regs[29])
#define PT_REGS_IP(x) ((x)->cp0_epc) #define PT_REGS_IP(x) ((x)->cp0_epc)
@@ -235,7 +226,7 @@ struct pt_regs;
#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), regs[8]) #define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), regs[8])
#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), regs[31]) #define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), regs[31])
#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), regs[30]) #define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), regs[30])
#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), regs[2]) #define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), regs[1])
#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), regs[29]) #define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), regs[29])
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), cp0_epc) #define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), cp0_epc)
@@ -296,56 +287,21 @@ struct pt_regs;
#elif defined(bpf_target_sparc) #elif defined(bpf_target_sparc)
#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = PT_REGS_RET(ctx); }) #define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = PT_REGS_RET(ctx); })
#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP #define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP
#elif defined(bpf_target_defined) #else
#define BPF_KPROBE_READ_RET_IP(ip, ctx) \ #define BPF_KPROBE_READ_RET_IP(ip, ctx) \
({ bpf_probe_read_kernel(&(ip), sizeof(ip), (void *)PT_REGS_RET(ctx)); }) ({ bpf_probe_read(&(ip), sizeof(ip), (void *)PT_REGS_RET(ctx)); })
#define BPF_KRETPROBE_READ_RET_IP(ip, ctx) \ #define BPF_KRETPROBE_READ_RET_IP(ip, ctx) \
({ bpf_probe_read_kernel(&(ip), sizeof(ip), \ ({ bpf_probe_read(&(ip), sizeof(ip), \
(void *)(PT_REGS_FP(ctx) + sizeof(ip))); }) (void *)(PT_REGS_FP(ctx) + sizeof(ip))); })
#endif #endif
#if !defined(bpf_target_defined)
#define PT_REGS_PARM1(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#define PT_REGS_PARM2(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#define PT_REGS_PARM3(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#define PT_REGS_PARM4(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#define PT_REGS_PARM5(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#define PT_REGS_RET(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#define PT_REGS_FP(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#define PT_REGS_RC(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#define PT_REGS_SP(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#define PT_REGS_IP(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#define PT_REGS_PARM1_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#define PT_REGS_PARM2_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#define PT_REGS_PARM3_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#define PT_REGS_PARM4_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#define PT_REGS_PARM5_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#define PT_REGS_RET_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#define PT_REGS_FP_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#define PT_REGS_RC_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#define PT_REGS_SP_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#define PT_REGS_IP_CORE(x) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#define BPF_KRETPROBE_READ_RET_IP(ip, ctx) ({ _Pragma(__BPF_TARGET_MISSING); 0l; })
#endif /* !defined(bpf_target_defined) */
#ifndef ___bpf_concat
#define ___bpf_concat(a, b) a ## b #define ___bpf_concat(a, b) a ## b
#endif
#ifndef ___bpf_apply
#define ___bpf_apply(fn, n) ___bpf_concat(fn, n) #define ___bpf_apply(fn, n) ___bpf_concat(fn, n)
#endif
#ifndef ___bpf_nth
#define ___bpf_nth(_, _1, _2, _3, _4, _5, _6, _7, _8, _9, _a, _b, _c, N, ...) N #define ___bpf_nth(_, _1, _2, _3, _4, _5, _6, _7, _8, _9, _a, _b, _c, N, ...) N
#endif
#ifndef ___bpf_narg
#define ___bpf_narg(...) \ #define ___bpf_narg(...) \
___bpf_nth(_, ##__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) ___bpf_nth(_, ##__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#endif #define ___bpf_empty(...) \
___bpf_nth(_, ##__VA_ARGS__, N, N, N, N, N, N, N, N, N, N, 0)
#define ___bpf_ctx_cast0() ctx #define ___bpf_ctx_cast0() ctx
#define ___bpf_ctx_cast1(x) ___bpf_ctx_cast0(), (void *)ctx[0] #define ___bpf_ctx_cast1(x) ___bpf_ctx_cast0(), (void *)ctx[0]
@@ -457,4 +413,20 @@ typeof(name(0)) name(struct pt_regs *ctx) \
} \ } \
static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args) static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args)
/*
* BPF_SEQ_PRINTF to wrap bpf_seq_printf to-be-printed values
* in a structure.
*/
#define BPF_SEQ_PRINTF(seq, fmt, args...) \
({ \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
static const char ___fmt[] = fmt; \
unsigned long long ___param[] = { args }; \
_Pragma("GCC diagnostic pop") \
int ___ret = bpf_seq_printf(seq, ___fmt, sizeof(___fmt), \
___param, sizeof(___param)); \
___ret; \
})
#endif #endif

3175
src/btf.c

File diff suppressed because it is too large Load Diff

278
src/btf.h
View File

@@ -1,12 +1,10 @@
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
/* Copyright (c) 2018 Facebook */ /* Copyright (c) 2018 Facebook */
/*! \file */
#ifndef __LIBBPF_BTF_H #ifndef __LIBBPF_BTF_H
#define __LIBBPF_BTF_H #define __LIBBPF_BTF_H
#include <stdarg.h> #include <stdarg.h>
#include <stdbool.h>
#include <linux/btf.h> #include <linux/btf.h>
#include <linux/types.h> #include <linux/types.h>
@@ -26,127 +24,64 @@ struct btf_type;
struct bpf_object; struct bpf_object;
enum btf_endianness { /*
BTF_LITTLE_ENDIAN = 0, * The .BTF.ext ELF section layout defined as
BTF_BIG_ENDIAN = 1, * struct btf_ext_header
* func_info subsection
*
* The func_info subsection layout:
* record size for struct bpf_func_info in the func_info subsection
* struct btf_sec_func_info for section #1
* a list of bpf_func_info records for section #1
* where struct bpf_func_info mimics one in include/uapi/linux/bpf.h
* but may not be identical
* struct btf_sec_func_info for section #2
* a list of bpf_func_info records for section #2
* ......
*
* Note that the bpf_func_info record size in .BTF.ext may not
* be the same as the one defined in include/uapi/linux/bpf.h.
* The loader should ensure that record_size meets minimum
* requirement and pass the record as is to the kernel. The
* kernel will handle the func_info properly based on its contents.
*/
struct btf_ext_header {
__u16 magic;
__u8 version;
__u8 flags;
__u32 hdr_len;
/* All offsets are in bytes relative to the end of this header */
__u32 func_info_off;
__u32 func_info_len;
__u32 line_info_off;
__u32 line_info_len;
/* optional part of .BTF.ext header */
__u32 field_reloc_off;
__u32 field_reloc_len;
}; };
/**
* @brief **btf__free()** frees all data of a BTF object
* @param btf BTF object to free
*/
LIBBPF_API void btf__free(struct btf *btf); LIBBPF_API void btf__free(struct btf *btf);
LIBBPF_API struct btf *btf__new(__u8 *data, __u32 size);
/** LIBBPF_API struct btf *btf__parse_elf(const char *path,
* @brief **btf__new()** creates a new instance of a BTF object from the raw struct btf_ext **btf_ext);
* bytes of an ELF's BTF section
* @param data raw bytes
* @param size number of bytes passed in `data`
* @return new BTF object instance which has to be eventually freed with
* **btf__free()**
*
* On error, error-code-encoded-as-pointer is returned, not a NULL. To extract
* error code from such a pointer `libbpf_get_error()` should be used. If
* `libbpf_set_strict_mode(LIBBPF_STRICT_CLEAN_PTRS)` is enabled, NULL is
* returned on error instead. In both cases thread-local `errno` variable is
* always set to error code as well.
*/
LIBBPF_API struct btf *btf__new(const void *data, __u32 size);
/**
* @brief **btf__new_split()** create a new instance of a BTF object from the
* provided raw data bytes. It takes another BTF instance, **base_btf**, which
* serves as a base BTF, which is extended by types in a newly created BTF
* instance
* @param data raw bytes
* @param size length of raw bytes
* @param base_btf the base BTF object
* @return new BTF object instance which has to be eventually freed with
* **btf__free()**
*
* If *base_btf* is NULL, `btf__new_split()` is equivalent to `btf__new()` and
* creates non-split BTF.
*
* On error, error-code-encoded-as-pointer is returned, not a NULL. To extract
* error code from such a pointer `libbpf_get_error()` should be used. If
* `libbpf_set_strict_mode(LIBBPF_STRICT_CLEAN_PTRS)` is enabled, NULL is
* returned on error instead. In both cases thread-local `errno` variable is
* always set to error code as well.
*/
LIBBPF_API struct btf *btf__new_split(const void *data, __u32 size, struct btf *base_btf);
/**
* @brief **btf__new_empty()** creates an empty BTF object. Use
* `btf__add_*()` to populate such BTF object.
* @return new BTF object instance which has to be eventually freed with
* **btf__free()**
*
* On error, error-code-encoded-as-pointer is returned, not a NULL. To extract
* error code from such a pointer `libbpf_get_error()` should be used. If
* `libbpf_set_strict_mode(LIBBPF_STRICT_CLEAN_PTRS)` is enabled, NULL is
* returned on error instead. In both cases thread-local `errno` variable is
* always set to error code as well.
*/
LIBBPF_API struct btf *btf__new_empty(void);
/**
* @brief **btf__new_empty_split()** creates an unpopulated BTF object from an
* ELF BTF section except with a base BTF on top of which split BTF should be
* based
* @return new BTF object instance which has to be eventually freed with
* **btf__free()**
*
* If *base_btf* is NULL, `btf__new_empty_split()` is equivalent to
* `btf__new_empty()` and creates non-split BTF.
*
* On error, error-code-encoded-as-pointer is returned, not a NULL. To extract
* error code from such a pointer `libbpf_get_error()` should be used. If
* `libbpf_set_strict_mode(LIBBPF_STRICT_CLEAN_PTRS)` is enabled, NULL is
* returned on error instead. In both cases thread-local `errno` variable is
* always set to error code as well.
*/
LIBBPF_API struct btf *btf__new_empty_split(struct btf *base_btf);
LIBBPF_API struct btf *btf__parse(const char *path, struct btf_ext **btf_ext);
LIBBPF_API struct btf *btf__parse_split(const char *path, struct btf *base_btf);
LIBBPF_API struct btf *btf__parse_elf(const char *path, struct btf_ext **btf_ext);
LIBBPF_API struct btf *btf__parse_elf_split(const char *path, struct btf *base_btf);
LIBBPF_API struct btf *btf__parse_raw(const char *path);
LIBBPF_API struct btf *btf__parse_raw_split(const char *path, struct btf *base_btf);
LIBBPF_API struct btf *btf__load_vmlinux_btf(void);
LIBBPF_API struct btf *btf__load_module_btf(const char *module_name, struct btf *vmlinux_btf);
LIBBPF_API struct btf *libbpf_find_kernel_btf(void);
LIBBPF_API struct btf *btf__load_from_kernel_by_id(__u32 id);
LIBBPF_API struct btf *btf__load_from_kernel_by_id_split(__u32 id, struct btf *base_btf);
LIBBPF_DEPRECATED_SINCE(0, 6, "use btf__load_from_kernel_by_id instead")
LIBBPF_API int btf__get_from_id(__u32 id, struct btf **btf);
LIBBPF_API int btf__finalize_data(struct bpf_object *obj, struct btf *btf); LIBBPF_API int btf__finalize_data(struct bpf_object *obj, struct btf *btf);
LIBBPF_DEPRECATED_SINCE(0, 6, "use btf__load_into_kernel instead")
LIBBPF_API int btf__load(struct btf *btf); LIBBPF_API int btf__load(struct btf *btf);
LIBBPF_API int btf__load_into_kernel(struct btf *btf);
LIBBPF_API __s32 btf__find_by_name(const struct btf *btf, LIBBPF_API __s32 btf__find_by_name(const struct btf *btf,
const char *type_name); const char *type_name);
LIBBPF_API __s32 btf__find_by_name_kind(const struct btf *btf, LIBBPF_API __s32 btf__find_by_name_kind(const struct btf *btf,
const char *type_name, __u32 kind); const char *type_name, __u32 kind);
LIBBPF_API __u32 btf__get_nr_types(const struct btf *btf); LIBBPF_API __u32 btf__get_nr_types(const struct btf *btf);
LIBBPF_API const struct btf *btf__base_btf(const struct btf *btf);
LIBBPF_API const struct btf_type *btf__type_by_id(const struct btf *btf, LIBBPF_API const struct btf_type *btf__type_by_id(const struct btf *btf,
__u32 id); __u32 id);
LIBBPF_API size_t btf__pointer_size(const struct btf *btf);
LIBBPF_API int btf__set_pointer_size(struct btf *btf, size_t ptr_sz);
LIBBPF_API enum btf_endianness btf__endianness(const struct btf *btf);
LIBBPF_API int btf__set_endianness(struct btf *btf, enum btf_endianness endian);
LIBBPF_API __s64 btf__resolve_size(const struct btf *btf, __u32 type_id); LIBBPF_API __s64 btf__resolve_size(const struct btf *btf, __u32 type_id);
LIBBPF_API int btf__resolve_type(const struct btf *btf, __u32 type_id); LIBBPF_API int btf__resolve_type(const struct btf *btf, __u32 type_id);
LIBBPF_API int btf__align_of(const struct btf *btf, __u32 id); LIBBPF_API int btf__align_of(const struct btf *btf, __u32 id);
LIBBPF_API int btf__fd(const struct btf *btf); LIBBPF_API int btf__fd(const struct btf *btf);
LIBBPF_API void btf__set_fd(struct btf *btf, int fd);
LIBBPF_API const void *btf__get_raw_data(const struct btf *btf, __u32 *size); LIBBPF_API const void *btf__get_raw_data(const struct btf *btf, __u32 *size);
LIBBPF_API const char *btf__name_by_offset(const struct btf *btf, __u32 offset); LIBBPF_API const char *btf__name_by_offset(const struct btf *btf, __u32 offset);
LIBBPF_API const char *btf__str_by_offset(const struct btf *btf, __u32 offset); LIBBPF_API int btf__get_from_id(__u32 id, struct btf **btf);
LIBBPF_API int btf__get_map_kv_tids(const struct btf *btf, const char *map_name, LIBBPF_API int btf__get_map_kv_tids(const struct btf *btf, const char *map_name,
__u32 expected_key_size, __u32 expected_key_size,
__u32 expected_value_size, __u32 expected_value_size,
@@ -156,88 +91,18 @@ LIBBPF_API struct btf_ext *btf_ext__new(__u8 *data, __u32 size);
LIBBPF_API void btf_ext__free(struct btf_ext *btf_ext); LIBBPF_API void btf_ext__free(struct btf_ext *btf_ext);
LIBBPF_API const void *btf_ext__get_raw_data(const struct btf_ext *btf_ext, LIBBPF_API const void *btf_ext__get_raw_data(const struct btf_ext *btf_ext,
__u32 *size); __u32 *size);
LIBBPF_API LIBBPF_DEPRECATED("btf_ext__reloc_func_info was never meant as a public API and has wrong assumptions embedded in it; it will be removed in the future libbpf versions") LIBBPF_API int btf_ext__reloc_func_info(const struct btf *btf,
int btf_ext__reloc_func_info(const struct btf *btf, const struct btf_ext *btf_ext,
const struct btf_ext *btf_ext, const char *sec_name, __u32 insns_cnt,
const char *sec_name, __u32 insns_cnt, void **func_info, __u32 *cnt);
void **func_info, __u32 *cnt); LIBBPF_API int btf_ext__reloc_line_info(const struct btf *btf,
LIBBPF_API LIBBPF_DEPRECATED("btf_ext__reloc_line_info was never meant as a public API and has wrong assumptions embedded in it; it will be removed in the future libbpf versions") const struct btf_ext *btf_ext,
int btf_ext__reloc_line_info(const struct btf *btf, const char *sec_name, __u32 insns_cnt,
const struct btf_ext *btf_ext, void **line_info, __u32 *cnt);
const char *sec_name, __u32 insns_cnt,
void **line_info, __u32 *cnt);
LIBBPF_API __u32 btf_ext__func_info_rec_size(const struct btf_ext *btf_ext); LIBBPF_API __u32 btf_ext__func_info_rec_size(const struct btf_ext *btf_ext);
LIBBPF_API __u32 btf_ext__line_info_rec_size(const struct btf_ext *btf_ext); LIBBPF_API __u32 btf_ext__line_info_rec_size(const struct btf_ext *btf_ext);
LIBBPF_API int btf__find_str(struct btf *btf, const char *s); LIBBPF_API struct btf *libbpf_find_kernel_btf(void);
LIBBPF_API int btf__add_str(struct btf *btf, const char *s);
LIBBPF_API int btf__add_type(struct btf *btf, const struct btf *src_btf,
const struct btf_type *src_type);
/**
* @brief **btf__add_btf()** appends all the BTF types from *src_btf* into *btf*
* @param btf BTF object which all the BTF types and strings are added to
* @param src_btf BTF object which all BTF types and referenced strings are copied from
* @return BTF type ID of the first appended BTF type, or negative error code
*
* **btf__add_btf()** can be used to simply and efficiently append the entire
* contents of one BTF object to another one. All the BTF type data is copied
* over, all referenced type IDs are adjusted by adding a necessary ID offset.
* Only strings referenced from BTF types are copied over and deduplicated, so
* if there were some unused strings in *src_btf*, those won't be copied over,
* which is consistent with the general string deduplication semantics of BTF
* writing APIs.
*
* If any error is encountered during this process, the contents of *btf* is
* left intact, which means that **btf__add_btf()** follows the transactional
* semantics and the operation as a whole is all-or-nothing.
*
* *src_btf* has to be non-split BTF, as of now copying types from split BTF
* is not supported and will result in -ENOTSUP error code returned.
*/
LIBBPF_API int btf__add_btf(struct btf *btf, const struct btf *src_btf);
LIBBPF_API int btf__add_int(struct btf *btf, const char *name, size_t byte_sz, int encoding);
LIBBPF_API int btf__add_float(struct btf *btf, const char *name, size_t byte_sz);
LIBBPF_API int btf__add_ptr(struct btf *btf, int ref_type_id);
LIBBPF_API int btf__add_array(struct btf *btf,
int index_type_id, int elem_type_id, __u32 nr_elems);
/* struct/union construction APIs */
LIBBPF_API int btf__add_struct(struct btf *btf, const char *name, __u32 sz);
LIBBPF_API int btf__add_union(struct btf *btf, const char *name, __u32 sz);
LIBBPF_API int btf__add_field(struct btf *btf, const char *name, int field_type_id,
__u32 bit_offset, __u32 bit_size);
/* enum construction APIs */
LIBBPF_API int btf__add_enum(struct btf *btf, const char *name, __u32 bytes_sz);
LIBBPF_API int btf__add_enum_value(struct btf *btf, const char *name, __s64 value);
enum btf_fwd_kind {
BTF_FWD_STRUCT = 0,
BTF_FWD_UNION = 1,
BTF_FWD_ENUM = 2,
};
LIBBPF_API int btf__add_fwd(struct btf *btf, const char *name, enum btf_fwd_kind fwd_kind);
LIBBPF_API int btf__add_typedef(struct btf *btf, const char *name, int ref_type_id);
LIBBPF_API int btf__add_volatile(struct btf *btf, int ref_type_id);
LIBBPF_API int btf__add_const(struct btf *btf, int ref_type_id);
LIBBPF_API int btf__add_restrict(struct btf *btf, int ref_type_id);
/* func and func_proto construction APIs */
LIBBPF_API int btf__add_func(struct btf *btf, const char *name,
enum btf_func_linkage linkage, int proto_type_id);
LIBBPF_API int btf__add_func_proto(struct btf *btf, int ret_type_id);
LIBBPF_API int btf__add_func_param(struct btf *btf, const char *name, int type_id);
/* var & datasec construction APIs */
LIBBPF_API int btf__add_var(struct btf *btf, const char *name, int linkage, int type_id);
LIBBPF_API int btf__add_datasec(struct btf *btf, const char *name, __u32 byte_sz);
LIBBPF_API int btf__add_datasec_var_info(struct btf *btf, int var_type_id,
__u32 offset, __u32 byte_sz);
/* tag construction API */
LIBBPF_API int btf__add_tag(struct btf *btf, const char *value, int ref_type_id,
int component_idx);
struct btf_dedup_opts { struct btf_dedup_opts {
unsigned int dedup_table_size; unsigned int dedup_table_size;
@@ -278,35 +143,13 @@ struct btf_dump_emit_type_decl_opts {
* necessary indentation already * necessary indentation already
*/ */
int indent_level; int indent_level;
/* strip all the const/volatile/restrict mods */
bool strip_mods;
size_t :0;
}; };
#define btf_dump_emit_type_decl_opts__last_field strip_mods #define btf_dump_emit_type_decl_opts__last_field indent_level
LIBBPF_API int LIBBPF_API int
btf_dump__emit_type_decl(struct btf_dump *d, __u32 id, btf_dump__emit_type_decl(struct btf_dump *d, __u32 id,
const struct btf_dump_emit_type_decl_opts *opts); const struct btf_dump_emit_type_decl_opts *opts);
struct btf_dump_type_data_opts {
/* size of this struct, for forward/backward compatibility */
size_t sz;
const char *indent_str;
int indent_level;
/* below match "show" flags for bpf_show_snprintf() */
bool compact; /* no newlines/indentation */
bool skip_names; /* skip member/type names */
bool emit_zeroes; /* show 0-valued fields */
size_t :0;
};
#define btf_dump_type_data_opts__last_field emit_zeroes
LIBBPF_API int
btf_dump__dump_type_data(struct btf_dump *d, __u32 id,
const void *data, size_t data_sz,
const struct btf_dump_type_data_opts *opts);
/* /*
* A set of helpers for easier BTF types handling * A set of helpers for easier BTF types handling
*/ */
@@ -325,11 +168,6 @@ static inline bool btf_kflag(const struct btf_type *t)
return BTF_INFO_KFLAG(t->info); return BTF_INFO_KFLAG(t->info);
} }
static inline bool btf_is_void(const struct btf_type *t)
{
return btf_kind(t) == BTF_KIND_UNKN;
}
static inline bool btf_is_int(const struct btf_type *t) static inline bool btf_is_int(const struct btf_type *t)
{ {
return btf_kind(t) == BTF_KIND_INT; return btf_kind(t) == BTF_KIND_INT;
@@ -421,16 +259,6 @@ static inline bool btf_is_datasec(const struct btf_type *t)
return btf_kind(t) == BTF_KIND_DATASEC; return btf_kind(t) == BTF_KIND_DATASEC;
} }
static inline bool btf_is_float(const struct btf_type *t)
{
return btf_kind(t) == BTF_KIND_FLOAT;
}
static inline bool btf_is_tag(const struct btf_type *t)
{
return btf_kind(t) == BTF_KIND_TAG;
}
static inline __u8 btf_int_encoding(const struct btf_type *t) static inline __u8 btf_int_encoding(const struct btf_type *t)
{ {
return BTF_INT_ENCODING(*(__u32 *)(t + 1)); return BTF_INT_ENCODING(*(__u32 *)(t + 1));
@@ -499,12 +327,6 @@ btf_var_secinfos(const struct btf_type *t)
return (struct btf_var_secinfo *)(t + 1); return (struct btf_var_secinfo *)(t + 1);
} }
struct btf_tag;
static inline struct btf_tag *btf_tag(const struct btf_type *t)
{
return (struct btf_tag *)(t + 1);
}
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,942 +0,0 @@
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
/* Copyright (c) 2021 Facebook */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <linux/filter.h>
#include <sys/param.h>
#include "btf.h"
#include "bpf.h"
#include "libbpf.h"
#include "libbpf_internal.h"
#include "hashmap.h"
#include "bpf_gen_internal.h"
#include "skel_internal.h"
#define MAX_USED_MAPS 64
#define MAX_USED_PROGS 32
#define MAX_KFUNC_DESCS 256
#define MAX_FD_ARRAY_SZ (MAX_USED_PROGS + MAX_KFUNC_DESCS)
/* The following structure describes the stack layout of the loader program.
* In addition R6 contains the pointer to context.
* R7 contains the result of the last sys_bpf command (typically error or FD).
* R9 contains the result of the last sys_close command.
*
* Naming convention:
* ctx - bpf program context
* stack - bpf program stack
* blob - bpf_attr-s, strings, insns, map data.
* All the bytes that loader prog will use for read/write.
*/
struct loader_stack {
__u32 btf_fd;
__u32 prog_fd[MAX_USED_PROGS];
__u32 inner_map_fd;
};
#define stack_off(field) \
(__s16)(-sizeof(struct loader_stack) + offsetof(struct loader_stack, field))
#define attr_field(attr, field) (attr + offsetof(union bpf_attr, field))
static int realloc_insn_buf(struct bpf_gen *gen, __u32 size)
{
size_t off = gen->insn_cur - gen->insn_start;
void *insn_start;
if (gen->error)
return gen->error;
if (size > INT32_MAX || off + size > INT32_MAX) {
gen->error = -ERANGE;
return -ERANGE;
}
insn_start = realloc(gen->insn_start, off + size);
if (!insn_start) {
gen->error = -ENOMEM;
free(gen->insn_start);
gen->insn_start = NULL;
return -ENOMEM;
}
gen->insn_start = insn_start;
gen->insn_cur = insn_start + off;
return 0;
}
static int realloc_data_buf(struct bpf_gen *gen, __u32 size)
{
size_t off = gen->data_cur - gen->data_start;
void *data_start;
if (gen->error)
return gen->error;
if (size > INT32_MAX || off + size > INT32_MAX) {
gen->error = -ERANGE;
return -ERANGE;
}
data_start = realloc(gen->data_start, off + size);
if (!data_start) {
gen->error = -ENOMEM;
free(gen->data_start);
gen->data_start = NULL;
return -ENOMEM;
}
gen->data_start = data_start;
gen->data_cur = data_start + off;
return 0;
}
static void emit(struct bpf_gen *gen, struct bpf_insn insn)
{
if (realloc_insn_buf(gen, sizeof(insn)))
return;
memcpy(gen->insn_cur, &insn, sizeof(insn));
gen->insn_cur += sizeof(insn);
}
static void emit2(struct bpf_gen *gen, struct bpf_insn insn1, struct bpf_insn insn2)
{
emit(gen, insn1);
emit(gen, insn2);
}
void bpf_gen__init(struct bpf_gen *gen, int log_level)
{
size_t stack_sz = sizeof(struct loader_stack);
int i;
gen->log_level = log_level;
/* save ctx pointer into R6 */
emit(gen, BPF_MOV64_REG(BPF_REG_6, BPF_REG_1));
/* bzero stack */
emit(gen, BPF_MOV64_REG(BPF_REG_1, BPF_REG_10));
emit(gen, BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -stack_sz));
emit(gen, BPF_MOV64_IMM(BPF_REG_2, stack_sz));
emit(gen, BPF_MOV64_IMM(BPF_REG_3, 0));
emit(gen, BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel));
/* jump over cleanup code */
emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0,
/* size of cleanup code below */
(stack_sz / 4) * 3 + 2));
/* remember the label where all error branches will jump to */
gen->cleanup_label = gen->insn_cur - gen->insn_start;
/* emit cleanup code: close all temp FDs */
for (i = 0; i < stack_sz; i += 4) {
emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_10, -stack_sz + i));
emit(gen, BPF_JMP_IMM(BPF_JSLE, BPF_REG_1, 0, 1));
emit(gen, BPF_EMIT_CALL(BPF_FUNC_sys_close));
}
/* R7 contains the error code from sys_bpf. Copy it into R0 and exit. */
emit(gen, BPF_MOV64_REG(BPF_REG_0, BPF_REG_7));
emit(gen, BPF_EXIT_INSN());
}
static int add_data(struct bpf_gen *gen, const void *data, __u32 size)
{
__u32 size8 = roundup(size, 8);
__u64 zero = 0;
void *prev;
if (realloc_data_buf(gen, size8))
return 0;
prev = gen->data_cur;
if (data) {
memcpy(gen->data_cur, data, size);
memcpy(gen->data_cur + size, &zero, size8 - size);
} else {
memset(gen->data_cur, 0, size8);
}
gen->data_cur += size8;
return prev - gen->data_start;
}
/* Get index for map_fd/btf_fd slot in reserved fd_array, or in data relative
* to start of fd_array. Caller can decide if it is usable or not.
*/
static int add_map_fd(struct bpf_gen *gen)
{
if (!gen->fd_array)
gen->fd_array = add_data(gen, NULL, MAX_FD_ARRAY_SZ * sizeof(int));
if (gen->nr_maps == MAX_USED_MAPS) {
pr_warn("Total maps exceeds %d\n", MAX_USED_MAPS);
gen->error = -E2BIG;
return 0;
}
return gen->nr_maps++;
}
static int add_kfunc_btf_fd(struct bpf_gen *gen)
{
int cur;
if (!gen->fd_array)
gen->fd_array = add_data(gen, NULL, MAX_FD_ARRAY_SZ * sizeof(int));
if (gen->nr_fd_array == MAX_KFUNC_DESCS) {
cur = add_data(gen, NULL, sizeof(int));
return (cur - gen->fd_array) / sizeof(int);
}
return MAX_USED_MAPS + gen->nr_fd_array++;
}
static int blob_fd_array_off(struct bpf_gen *gen, int index)
{
return gen->fd_array + index * sizeof(int);
}
static int insn_bytes_to_bpf_size(__u32 sz)
{
switch (sz) {
case 8: return BPF_DW;
case 4: return BPF_W;
case 2: return BPF_H;
case 1: return BPF_B;
default: return -1;
}
}
/* *(u64 *)(blob + off) = (u64)(void *)(blob + data) */
static void emit_rel_store(struct bpf_gen *gen, int off, int data)
{
emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_0, BPF_PSEUDO_MAP_IDX_VALUE,
0, 0, 0, data));
emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
0, 0, 0, off));
emit(gen, BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0));
}
static void move_blob2blob(struct bpf_gen *gen, int off, int size, int blob_off)
{
emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_2, BPF_PSEUDO_MAP_IDX_VALUE,
0, 0, 0, blob_off));
emit(gen, BPF_LDX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_0, BPF_REG_2, 0));
emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
0, 0, 0, off));
emit(gen, BPF_STX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_1, BPF_REG_0, 0));
}
static void move_blob2ctx(struct bpf_gen *gen, int ctx_off, int size, int blob_off)
{
emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
0, 0, 0, blob_off));
emit(gen, BPF_LDX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_0, BPF_REG_1, 0));
emit(gen, BPF_STX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_6, BPF_REG_0, ctx_off));
}
static void move_ctx2blob(struct bpf_gen *gen, int off, int size, int ctx_off,
bool check_non_zero)
{
emit(gen, BPF_LDX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_0, BPF_REG_6, ctx_off));
if (check_non_zero)
/* If value in ctx is zero don't update the blob.
* For example: when ctx->map.max_entries == 0, keep default max_entries from bpf.c
*/
emit(gen, BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3));
emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
0, 0, 0, off));
emit(gen, BPF_STX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_1, BPF_REG_0, 0));
}
static void move_stack2blob(struct bpf_gen *gen, int off, int size, int stack_off)
{
emit(gen, BPF_LDX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_0, BPF_REG_10, stack_off));
emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
0, 0, 0, off));
emit(gen, BPF_STX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_1, BPF_REG_0, 0));
}
static void move_stack2ctx(struct bpf_gen *gen, int ctx_off, int size, int stack_off)
{
emit(gen, BPF_LDX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_0, BPF_REG_10, stack_off));
emit(gen, BPF_STX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_6, BPF_REG_0, ctx_off));
}
static void emit_sys_bpf(struct bpf_gen *gen, int cmd, int attr, int attr_size)
{
emit(gen, BPF_MOV64_IMM(BPF_REG_1, cmd));
emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_2, BPF_PSEUDO_MAP_IDX_VALUE,
0, 0, 0, attr));
emit(gen, BPF_MOV64_IMM(BPF_REG_3, attr_size));
emit(gen, BPF_EMIT_CALL(BPF_FUNC_sys_bpf));
/* remember the result in R7 */
emit(gen, BPF_MOV64_REG(BPF_REG_7, BPF_REG_0));
}
static bool is_simm16(__s64 value)
{
return value == (__s64)(__s16)value;
}
static void emit_check_err(struct bpf_gen *gen)
{
__s64 off = -(gen->insn_cur - gen->insn_start - gen->cleanup_label) / 8 - 1;
/* R7 contains result of last sys_bpf command.
* if (R7 < 0) goto cleanup;
*/
if (is_simm16(off)) {
emit(gen, BPF_JMP_IMM(BPF_JSLT, BPF_REG_7, 0, off));
} else {
gen->error = -ERANGE;
emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0, -1));
}
}
/* reg1 and reg2 should not be R1 - R5. They can be R0, R6 - R10 */
static void emit_debug(struct bpf_gen *gen, int reg1, int reg2,
const char *fmt, va_list args)
{
char buf[1024];
int addr, len, ret;
if (!gen->log_level)
return;
ret = vsnprintf(buf, sizeof(buf), fmt, args);
if (ret < 1024 - 7 && reg1 >= 0 && reg2 < 0)
/* The special case to accommodate common debug_ret():
* to avoid specifying BPF_REG_7 and adding " r=%%d" to
* prints explicitly.
*/
strcat(buf, " r=%d");
len = strlen(buf) + 1;
addr = add_data(gen, buf, len);
emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
0, 0, 0, addr));
emit(gen, BPF_MOV64_IMM(BPF_REG_2, len));
if (reg1 >= 0)
emit(gen, BPF_MOV64_REG(BPF_REG_3, reg1));
if (reg2 >= 0)
emit(gen, BPF_MOV64_REG(BPF_REG_4, reg2));
emit(gen, BPF_EMIT_CALL(BPF_FUNC_trace_printk));
}
static void debug_regs(struct bpf_gen *gen, int reg1, int reg2, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
emit_debug(gen, reg1, reg2, fmt, args);
va_end(args);
}
static void debug_ret(struct bpf_gen *gen, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
emit_debug(gen, BPF_REG_7, -1, fmt, args);
va_end(args);
}
static void __emit_sys_close(struct bpf_gen *gen)
{
emit(gen, BPF_JMP_IMM(BPF_JSLE, BPF_REG_1, 0,
/* 2 is the number of the following insns
* * 6 is additional insns in debug_regs
*/
2 + (gen->log_level ? 6 : 0)));
emit(gen, BPF_MOV64_REG(BPF_REG_9, BPF_REG_1));
emit(gen, BPF_EMIT_CALL(BPF_FUNC_sys_close));
debug_regs(gen, BPF_REG_9, BPF_REG_0, "close(%%d) = %%d");
}
static void emit_sys_close_stack(struct bpf_gen *gen, int stack_off)
{
emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_10, stack_off));
__emit_sys_close(gen);
}
static void emit_sys_close_blob(struct bpf_gen *gen, int blob_off)
{
emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_0, BPF_PSEUDO_MAP_IDX_VALUE,
0, 0, 0, blob_off));
emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0));
__emit_sys_close(gen);
}
int bpf_gen__finish(struct bpf_gen *gen)
{
int i;
emit_sys_close_stack(gen, stack_off(btf_fd));
for (i = 0; i < gen->nr_progs; i++)
move_stack2ctx(gen,
sizeof(struct bpf_loader_ctx) +
sizeof(struct bpf_map_desc) * gen->nr_maps +
sizeof(struct bpf_prog_desc) * i +
offsetof(struct bpf_prog_desc, prog_fd), 4,
stack_off(prog_fd[i]));
for (i = 0; i < gen->nr_maps; i++)
move_blob2ctx(gen,
sizeof(struct bpf_loader_ctx) +
sizeof(struct bpf_map_desc) * i +
offsetof(struct bpf_map_desc, map_fd), 4,
blob_fd_array_off(gen, i));
emit(gen, BPF_MOV64_IMM(BPF_REG_0, 0));
emit(gen, BPF_EXIT_INSN());
pr_debug("gen: finish %d\n", gen->error);
if (!gen->error) {
struct gen_loader_opts *opts = gen->opts;
opts->insns = gen->insn_start;
opts->insns_sz = gen->insn_cur - gen->insn_start;
opts->data = gen->data_start;
opts->data_sz = gen->data_cur - gen->data_start;
}
return gen->error;
}
void bpf_gen__free(struct bpf_gen *gen)
{
if (!gen)
return;
free(gen->data_start);
free(gen->insn_start);
free(gen);
}
void bpf_gen__load_btf(struct bpf_gen *gen, const void *btf_raw_data,
__u32 btf_raw_size)
{
int attr_size = offsetofend(union bpf_attr, btf_log_level);
int btf_data, btf_load_attr;
union bpf_attr attr;
memset(&attr, 0, attr_size);
pr_debug("gen: load_btf: size %d\n", btf_raw_size);
btf_data = add_data(gen, btf_raw_data, btf_raw_size);
attr.btf_size = btf_raw_size;
btf_load_attr = add_data(gen, &attr, attr_size);
/* populate union bpf_attr with user provided log details */
move_ctx2blob(gen, attr_field(btf_load_attr, btf_log_level), 4,
offsetof(struct bpf_loader_ctx, log_level), false);
move_ctx2blob(gen, attr_field(btf_load_attr, btf_log_size), 4,
offsetof(struct bpf_loader_ctx, log_size), false);
move_ctx2blob(gen, attr_field(btf_load_attr, btf_log_buf), 8,
offsetof(struct bpf_loader_ctx, log_buf), false);
/* populate union bpf_attr with a pointer to the BTF data */
emit_rel_store(gen, attr_field(btf_load_attr, btf), btf_data);
/* emit BTF_LOAD command */
emit_sys_bpf(gen, BPF_BTF_LOAD, btf_load_attr, attr_size);
debug_ret(gen, "btf_load size %d", btf_raw_size);
emit_check_err(gen);
/* remember btf_fd in the stack, if successful */
emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_7, stack_off(btf_fd)));
}
void bpf_gen__map_create(struct bpf_gen *gen,
struct bpf_create_map_attr *map_attr, int map_idx)
{
int attr_size = offsetofend(union bpf_attr, btf_vmlinux_value_type_id);
bool close_inner_map_fd = false;
int map_create_attr, idx;
union bpf_attr attr;
memset(&attr, 0, attr_size);
attr.map_type = map_attr->map_type;
attr.key_size = map_attr->key_size;
attr.value_size = map_attr->value_size;
attr.map_flags = map_attr->map_flags;
memcpy(attr.map_name, map_attr->name,
min((unsigned)strlen(map_attr->name), BPF_OBJ_NAME_LEN - 1));
attr.numa_node = map_attr->numa_node;
attr.map_ifindex = map_attr->map_ifindex;
attr.max_entries = map_attr->max_entries;
switch (attr.map_type) {
case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
case BPF_MAP_TYPE_CGROUP_ARRAY:
case BPF_MAP_TYPE_STACK_TRACE:
case BPF_MAP_TYPE_ARRAY_OF_MAPS:
case BPF_MAP_TYPE_HASH_OF_MAPS:
case BPF_MAP_TYPE_DEVMAP:
case BPF_MAP_TYPE_DEVMAP_HASH:
case BPF_MAP_TYPE_CPUMAP:
case BPF_MAP_TYPE_XSKMAP:
case BPF_MAP_TYPE_SOCKMAP:
case BPF_MAP_TYPE_SOCKHASH:
case BPF_MAP_TYPE_QUEUE:
case BPF_MAP_TYPE_STACK:
case BPF_MAP_TYPE_RINGBUF:
break;
default:
attr.btf_key_type_id = map_attr->btf_key_type_id;
attr.btf_value_type_id = map_attr->btf_value_type_id;
}
pr_debug("gen: map_create: %s idx %d type %d value_type_id %d\n",
attr.map_name, map_idx, map_attr->map_type, attr.btf_value_type_id);
map_create_attr = add_data(gen, &attr, attr_size);
if (attr.btf_value_type_id)
/* populate union bpf_attr with btf_fd saved in the stack earlier */
move_stack2blob(gen, attr_field(map_create_attr, btf_fd), 4,
stack_off(btf_fd));
switch (attr.map_type) {
case BPF_MAP_TYPE_ARRAY_OF_MAPS:
case BPF_MAP_TYPE_HASH_OF_MAPS:
move_stack2blob(gen, attr_field(map_create_attr, inner_map_fd), 4,
stack_off(inner_map_fd));
close_inner_map_fd = true;
break;
default:
break;
}
/* conditionally update max_entries */
if (map_idx >= 0)
move_ctx2blob(gen, attr_field(map_create_attr, max_entries), 4,
sizeof(struct bpf_loader_ctx) +
sizeof(struct bpf_map_desc) * map_idx +
offsetof(struct bpf_map_desc, max_entries),
true /* check that max_entries != 0 */);
/* emit MAP_CREATE command */
emit_sys_bpf(gen, BPF_MAP_CREATE, map_create_attr, attr_size);
debug_ret(gen, "map_create %s idx %d type %d value_size %d value_btf_id %d",
attr.map_name, map_idx, map_attr->map_type, attr.value_size,
attr.btf_value_type_id);
emit_check_err(gen);
/* remember map_fd in the stack, if successful */
if (map_idx < 0) {
/* This bpf_gen__map_create() function is called with map_idx >= 0
* for all maps that libbpf loading logic tracks.
* It's called with -1 to create an inner map.
*/
emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_7,
stack_off(inner_map_fd)));
} else if (map_idx != gen->nr_maps) {
gen->error = -EDOM; /* internal bug */
return;
} else {
/* add_map_fd does gen->nr_maps++ */
idx = add_map_fd(gen);
emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
0, 0, 0, blob_fd_array_off(gen, idx)));
emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_7, 0));
}
if (close_inner_map_fd)
emit_sys_close_stack(gen, stack_off(inner_map_fd));
}
void bpf_gen__record_attach_target(struct bpf_gen *gen, const char *attach_name,
enum bpf_attach_type type)
{
const char *prefix;
int kind, ret;
btf_get_kernel_prefix_kind(type, &prefix, &kind);
gen->attach_kind = kind;
ret = snprintf(gen->attach_target, sizeof(gen->attach_target), "%s%s",
prefix, attach_name);
if (ret == sizeof(gen->attach_target))
gen->error = -ENOSPC;
}
static void emit_find_attach_target(struct bpf_gen *gen)
{
int name, len = strlen(gen->attach_target) + 1;
pr_debug("gen: find_attach_tgt %s %d\n", gen->attach_target, gen->attach_kind);
name = add_data(gen, gen->attach_target, len);
emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
0, 0, 0, name));
emit(gen, BPF_MOV64_IMM(BPF_REG_2, len));
emit(gen, BPF_MOV64_IMM(BPF_REG_3, gen->attach_kind));
emit(gen, BPF_MOV64_IMM(BPF_REG_4, 0));
emit(gen, BPF_EMIT_CALL(BPF_FUNC_btf_find_by_name_kind));
emit(gen, BPF_MOV64_REG(BPF_REG_7, BPF_REG_0));
debug_ret(gen, "find_by_name_kind(%s,%d)",
gen->attach_target, gen->attach_kind);
emit_check_err(gen);
/* if successful, btf_id is in lower 32-bit of R7 and
* btf_obj_fd is in upper 32-bit
*/
}
void bpf_gen__record_extern(struct bpf_gen *gen, const char *name, bool is_weak,
int kind, int insn_idx)
{
struct ksym_relo_desc *relo;
relo = libbpf_reallocarray(gen->relos, gen->relo_cnt + 1, sizeof(*relo));
if (!relo) {
gen->error = -ENOMEM;
return;
}
gen->relos = relo;
relo += gen->relo_cnt;
relo->name = name;
relo->is_weak = is_weak;
relo->kind = kind;
relo->insn_idx = insn_idx;
gen->relo_cnt++;
}
/* returns existing ksym_desc with ref incremented, or inserts a new one */
static struct ksym_desc *get_ksym_desc(struct bpf_gen *gen, struct ksym_relo_desc *relo)
{
struct ksym_desc *kdesc;
for (int i = 0; i < gen->nr_ksyms; i++) {
if (!strcmp(gen->ksyms[i].name, relo->name)) {
gen->ksyms[i].ref++;
return &gen->ksyms[i];
}
}
kdesc = libbpf_reallocarray(gen->ksyms, gen->nr_ksyms + 1, sizeof(*kdesc));
if (!kdesc) {
gen->error = -ENOMEM;
return NULL;
}
gen->ksyms = kdesc;
kdesc = &gen->ksyms[gen->nr_ksyms++];
kdesc->name = relo->name;
kdesc->kind = relo->kind;
kdesc->ref = 1;
kdesc->off = 0;
kdesc->insn = 0;
return kdesc;
}
/* Overwrites BPF_REG_{0, 1, 2, 3, 4, 7}
* Returns result in BPF_REG_7
*/
static void emit_bpf_find_by_name_kind(struct bpf_gen *gen, struct ksym_relo_desc *relo)
{
int name_off, len = strlen(relo->name) + 1;
name_off = add_data(gen, relo->name, len);
emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
0, 0, 0, name_off));
emit(gen, BPF_MOV64_IMM(BPF_REG_2, len));
emit(gen, BPF_MOV64_IMM(BPF_REG_3, relo->kind));
emit(gen, BPF_MOV64_IMM(BPF_REG_4, 0));
emit(gen, BPF_EMIT_CALL(BPF_FUNC_btf_find_by_name_kind));
emit(gen, BPF_MOV64_REG(BPF_REG_7, BPF_REG_0));
debug_ret(gen, "find_by_name_kind(%s,%d)", relo->name, relo->kind);
}
/* Expects:
* BPF_REG_8 - pointer to instruction
*
* We need to reuse BTF fd for same symbol otherwise each relocation takes a new
* index, while kernel limits total kfunc BTFs to 256. For duplicate symbols,
* this would mean a new BTF fd index for each entry. By pairing symbol name
* with index, we get the insn->imm, insn->off pairing that kernel uses for
* kfunc_tab, which becomes the effective limit even though all of them may
* share same index in fd_array (such that kfunc_btf_tab has 1 element).
*/
static void emit_relo_kfunc_btf(struct bpf_gen *gen, struct ksym_relo_desc *relo, int insn)
{
struct ksym_desc *kdesc;
int btf_fd_idx;
kdesc = get_ksym_desc(gen, relo);
if (!kdesc)
return;
/* try to copy from existing bpf_insn */
if (kdesc->ref > 1) {
move_blob2blob(gen, insn + offsetof(struct bpf_insn, imm), 4,
kdesc->insn + offsetof(struct bpf_insn, imm));
move_blob2blob(gen, insn + offsetof(struct bpf_insn, off), 2,
kdesc->insn + offsetof(struct bpf_insn, off));
goto log;
}
/* remember insn offset, so we can copy BTF ID and FD later */
kdesc->insn = insn;
emit_bpf_find_by_name_kind(gen, relo);
if (!relo->is_weak)
emit_check_err(gen);
/* get index in fd_array to store BTF FD at */
btf_fd_idx = add_kfunc_btf_fd(gen);
if (btf_fd_idx > INT16_MAX) {
pr_warn("BTF fd off %d for kfunc %s exceeds INT16_MAX, cannot process relocation\n",
btf_fd_idx, relo->name);
gen->error = -E2BIG;
return;
}
kdesc->off = btf_fd_idx;
/* set a default value for imm */
emit(gen, BPF_ST_MEM(BPF_W, BPF_REG_8, offsetof(struct bpf_insn, imm), 0));
/* skip success case store if ret < 0 */
emit(gen, BPF_JMP_IMM(BPF_JSLT, BPF_REG_7, 0, 1));
/* store btf_id into insn[insn_idx].imm */
emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_8, BPF_REG_7, offsetof(struct bpf_insn, imm)));
/* load fd_array slot pointer */
emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_0, BPF_PSEUDO_MAP_IDX_VALUE,
0, 0, 0, blob_fd_array_off(gen, btf_fd_idx)));
/* skip store of BTF fd if ret < 0 */
emit(gen, BPF_JMP_IMM(BPF_JSLT, BPF_REG_7, 0, 3));
/* store BTF fd in slot */
emit(gen, BPF_MOV64_REG(BPF_REG_9, BPF_REG_7));
emit(gen, BPF_ALU64_IMM(BPF_RSH, BPF_REG_9, 32));
emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_9, 0));
/* set a default value for off */
emit(gen, BPF_ST_MEM(BPF_H, BPF_REG_8, offsetof(struct bpf_insn, off), 0));
/* skip insn->off store if ret < 0 */
emit(gen, BPF_JMP_IMM(BPF_JSLT, BPF_REG_7, 0, 2));
/* skip if vmlinux BTF */
emit(gen, BPF_JMP_IMM(BPF_JEQ, BPF_REG_9, 0, 1));
/* store index into insn[insn_idx].off */
emit(gen, BPF_ST_MEM(BPF_H, BPF_REG_8, offsetof(struct bpf_insn, off), btf_fd_idx));
log:
if (!gen->log_level)
return;
emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_8,
offsetof(struct bpf_insn, imm)));
emit(gen, BPF_LDX_MEM(BPF_H, BPF_REG_9, BPF_REG_8,
offsetof(struct bpf_insn, off)));
debug_regs(gen, BPF_REG_7, BPF_REG_9, " func (%s:count=%d): imm: %%d, off: %%d",
relo->name, kdesc->ref);
emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_0, BPF_PSEUDO_MAP_IDX_VALUE,
0, 0, 0, blob_fd_array_off(gen, kdesc->off)));
emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_0, 0));
debug_regs(gen, BPF_REG_9, -1, " func (%s:count=%d): btf_fd",
relo->name, kdesc->ref);
}
/* Expects:
* BPF_REG_8 - pointer to instruction
*/
static void emit_relo_ksym_btf(struct bpf_gen *gen, struct ksym_relo_desc *relo, int insn)
{
struct ksym_desc *kdesc;
kdesc = get_ksym_desc(gen, relo);
if (!kdesc)
return;
/* try to copy from existing ldimm64 insn */
if (kdesc->ref > 1) {
move_blob2blob(gen, insn + offsetof(struct bpf_insn, imm), 4,
kdesc->insn + offsetof(struct bpf_insn, imm));
move_blob2blob(gen, insn + sizeof(struct bpf_insn) + offsetof(struct bpf_insn, imm), 4,
kdesc->insn + sizeof(struct bpf_insn) + offsetof(struct bpf_insn, imm));
goto log;
}
/* remember insn offset, so we can copy BTF ID and FD later */
kdesc->insn = insn;
emit_bpf_find_by_name_kind(gen, relo);
emit_check_err(gen);
/* store btf_id into insn[insn_idx].imm */
emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_8, BPF_REG_7, offsetof(struct bpf_insn, imm)));
/* store btf_obj_fd into insn[insn_idx + 1].imm */
emit(gen, BPF_ALU64_IMM(BPF_RSH, BPF_REG_7, 32));
emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_8, BPF_REG_7,
sizeof(struct bpf_insn) + offsetof(struct bpf_insn, imm)));
log:
if (!gen->log_level)
return;
emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_8,
offsetof(struct bpf_insn, imm)));
emit(gen, BPF_LDX_MEM(BPF_H, BPF_REG_9, BPF_REG_8, sizeof(struct bpf_insn) +
offsetof(struct bpf_insn, imm)));
debug_regs(gen, BPF_REG_7, BPF_REG_9, " var (%s:count=%d): imm: %%d, fd: %%d",
relo->name, kdesc->ref);
}
static void emit_relo(struct bpf_gen *gen, struct ksym_relo_desc *relo, int insns)
{
int insn;
pr_debug("gen: emit_relo (%d): %s at %d\n", relo->kind, relo->name, relo->insn_idx);
insn = insns + sizeof(struct bpf_insn) * relo->insn_idx;
emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_8, BPF_PSEUDO_MAP_IDX_VALUE, 0, 0, 0, insn));
switch (relo->kind) {
case BTF_KIND_VAR:
emit_relo_ksym_btf(gen, relo, insn);
break;
case BTF_KIND_FUNC:
emit_relo_kfunc_btf(gen, relo, insn);
break;
default:
pr_warn("Unknown relocation kind '%d'\n", relo->kind);
gen->error = -EDOM;
return;
}
}
static void emit_relos(struct bpf_gen *gen, int insns)
{
int i;
for (i = 0; i < gen->relo_cnt; i++)
emit_relo(gen, gen->relos + i, insns);
}
static void cleanup_relos(struct bpf_gen *gen, int insns)
{
int i, insn;
for (i = 0; i < gen->nr_ksyms; i++) {
if (gen->ksyms[i].kind == BTF_KIND_VAR) {
/* close fd recorded in insn[insn_idx + 1].imm */
insn = gen->ksyms[i].insn;
insn += sizeof(struct bpf_insn) + offsetof(struct bpf_insn, imm);
emit_sys_close_blob(gen, insn);
} else { /* BTF_KIND_FUNC */
emit_sys_close_blob(gen, blob_fd_array_off(gen, gen->ksyms[i].off));
if (gen->ksyms[i].off < MAX_FD_ARRAY_SZ)
gen->nr_fd_array--;
}
}
if (gen->nr_ksyms) {
free(gen->ksyms);
gen->nr_ksyms = 0;
gen->ksyms = NULL;
}
if (gen->relo_cnt) {
free(gen->relos);
gen->relo_cnt = 0;
gen->relos = NULL;
}
}
void bpf_gen__prog_load(struct bpf_gen *gen,
struct bpf_prog_load_params *load_attr, int prog_idx)
{
int attr_size = offsetofend(union bpf_attr, fd_array);
int prog_load_attr, license, insns, func_info, line_info;
union bpf_attr attr;
memset(&attr, 0, attr_size);
pr_debug("gen: prog_load: type %d insns_cnt %zd\n",
load_attr->prog_type, load_attr->insn_cnt);
/* add license string to blob of bytes */
license = add_data(gen, load_attr->license, strlen(load_attr->license) + 1);
/* add insns to blob of bytes */
insns = add_data(gen, load_attr->insns,
load_attr->insn_cnt * sizeof(struct bpf_insn));
attr.prog_type = load_attr->prog_type;
attr.expected_attach_type = load_attr->expected_attach_type;
attr.attach_btf_id = load_attr->attach_btf_id;
attr.prog_ifindex = load_attr->prog_ifindex;
attr.kern_version = 0;
attr.insn_cnt = (__u32)load_attr->insn_cnt;
attr.prog_flags = load_attr->prog_flags;
attr.func_info_rec_size = load_attr->func_info_rec_size;
attr.func_info_cnt = load_attr->func_info_cnt;
func_info = add_data(gen, load_attr->func_info,
attr.func_info_cnt * attr.func_info_rec_size);
attr.line_info_rec_size = load_attr->line_info_rec_size;
attr.line_info_cnt = load_attr->line_info_cnt;
line_info = add_data(gen, load_attr->line_info,
attr.line_info_cnt * attr.line_info_rec_size);
memcpy(attr.prog_name, load_attr->name,
min((unsigned)strlen(load_attr->name), BPF_OBJ_NAME_LEN - 1));
prog_load_attr = add_data(gen, &attr, attr_size);
/* populate union bpf_attr with a pointer to license */
emit_rel_store(gen, attr_field(prog_load_attr, license), license);
/* populate union bpf_attr with a pointer to instructions */
emit_rel_store(gen, attr_field(prog_load_attr, insns), insns);
/* populate union bpf_attr with a pointer to func_info */
emit_rel_store(gen, attr_field(prog_load_attr, func_info), func_info);
/* populate union bpf_attr with a pointer to line_info */
emit_rel_store(gen, attr_field(prog_load_attr, line_info), line_info);
/* populate union bpf_attr fd_array with a pointer to data where map_fds are saved */
emit_rel_store(gen, attr_field(prog_load_attr, fd_array), gen->fd_array);
/* populate union bpf_attr with user provided log details */
move_ctx2blob(gen, attr_field(prog_load_attr, log_level), 4,
offsetof(struct bpf_loader_ctx, log_level), false);
move_ctx2blob(gen, attr_field(prog_load_attr, log_size), 4,
offsetof(struct bpf_loader_ctx, log_size), false);
move_ctx2blob(gen, attr_field(prog_load_attr, log_buf), 8,
offsetof(struct bpf_loader_ctx, log_buf), false);
/* populate union bpf_attr with btf_fd saved in the stack earlier */
move_stack2blob(gen, attr_field(prog_load_attr, prog_btf_fd), 4,
stack_off(btf_fd));
if (gen->attach_kind) {
emit_find_attach_target(gen);
/* populate union bpf_attr with btf_id and btf_obj_fd found by helper */
emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_0, BPF_PSEUDO_MAP_IDX_VALUE,
0, 0, 0, prog_load_attr));
emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_7,
offsetof(union bpf_attr, attach_btf_id)));
emit(gen, BPF_ALU64_IMM(BPF_RSH, BPF_REG_7, 32));
emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_7,
offsetof(union bpf_attr, attach_btf_obj_fd)));
}
emit_relos(gen, insns);
/* emit PROG_LOAD command */
emit_sys_bpf(gen, BPF_PROG_LOAD, prog_load_attr, attr_size);
debug_ret(gen, "prog_load %s insn_cnt %d", attr.prog_name, attr.insn_cnt);
/* successful or not, close btf module FDs used in extern ksyms and attach_btf_obj_fd */
cleanup_relos(gen, insns);
if (gen->attach_kind)
emit_sys_close_blob(gen,
attr_field(prog_load_attr, attach_btf_obj_fd));
emit_check_err(gen);
/* remember prog_fd in the stack, if successful */
emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_7,
stack_off(prog_fd[gen->nr_progs])));
gen->nr_progs++;
}
void bpf_gen__map_update_elem(struct bpf_gen *gen, int map_idx, void *pvalue,
__u32 value_size)
{
int attr_size = offsetofend(union bpf_attr, flags);
int map_update_attr, value, key;
union bpf_attr attr;
int zero = 0;
memset(&attr, 0, attr_size);
pr_debug("gen: map_update_elem: idx %d\n", map_idx);
value = add_data(gen, pvalue, value_size);
key = add_data(gen, &zero, sizeof(zero));
/* if (map_desc[map_idx].initial_value)
* copy_from_user(value, initial_value, value_size);
*/
emit(gen, BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_6,
sizeof(struct bpf_loader_ctx) +
sizeof(struct bpf_map_desc) * map_idx +
offsetof(struct bpf_map_desc, initial_value)));
emit(gen, BPF_JMP_IMM(BPF_JEQ, BPF_REG_3, 0, 4));
emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
0, 0, 0, value));
emit(gen, BPF_MOV64_IMM(BPF_REG_2, value_size));
emit(gen, BPF_EMIT_CALL(BPF_FUNC_copy_from_user));
map_update_attr = add_data(gen, &attr, attr_size);
move_blob2blob(gen, attr_field(map_update_attr, map_fd), 4,
blob_fd_array_off(gen, map_idx));
emit_rel_store(gen, attr_field(map_update_attr, key), key);
emit_rel_store(gen, attr_field(map_update_attr, value), value);
/* emit MAP_UPDATE_ELEM command */
emit_sys_bpf(gen, BPF_MAP_UPDATE_ELEM, map_update_attr, attr_size);
debug_ret(gen, "update_elem idx %d value_size %d", map_idx, value_size);
emit_check_err(gen);
}
void bpf_gen__map_freeze(struct bpf_gen *gen, int map_idx)
{
int attr_size = offsetofend(union bpf_attr, map_fd);
int map_freeze_attr;
union bpf_attr attr;
memset(&attr, 0, attr_size);
pr_debug("gen: map_freeze: idx %d\n", map_idx);
map_freeze_attr = add_data(gen, &attr, attr_size);
move_blob2blob(gen, attr_field(map_freeze_attr, map_fd), 4,
blob_fd_array_off(gen, map_idx));
/* emit MAP_FREEZE command */
emit_sys_bpf(gen, BPF_MAP_FREEZE, map_freeze_attr, attr_size);
debug_ret(gen, "map_freeze");
emit_check_err(gen);
}

View File

@@ -15,9 +15,6 @@
/* make sure libbpf doesn't use kernel-only integer typedefs */ /* make sure libbpf doesn't use kernel-only integer typedefs */
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64 #pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
/* prevent accidental re-addition of reallocarray() */
#pragma GCC poison reallocarray
/* start with 4 buckets */ /* start with 4 buckets */
#define HASHMAP_MIN_CAP_BITS 2 #define HASHMAP_MIN_CAP_BITS 2

View File

@@ -11,33 +11,14 @@
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <limits.h> #include <limits.h>
#ifndef __WORDSIZE
#define __WORDSIZE (__SIZEOF_LONG__ * 8)
#endif
static inline size_t hash_bits(size_t h, int bits) static inline size_t hash_bits(size_t h, int bits)
{ {
/* shuffle bits and return requested number of upper bits */ /* shuffle bits and return requested number of upper bits */
if (bits == 0) return (h * 11400714819323198485llu) >> (__WORDSIZE - bits);
return 0;
#if (__SIZEOF_SIZE_T__ == __SIZEOF_LONG_LONG__)
/* LP64 case */
return (h * 11400714819323198485llu) >> (__SIZEOF_LONG_LONG__ * 8 - bits);
#elif (__SIZEOF_SIZE_T__ <= __SIZEOF_LONG__)
return (h * 2654435769lu) >> (__SIZEOF_LONG__ * 8 - bits);
#else
# error "Unsupported size_t size"
#endif
}
/* generic C-string hashing function */
static inline size_t str_hash(const char *s)
{
size_t h = 0;
while (*s) {
h = h * 31 + *s;
s++;
}
return h;
} }
typedef size_t (*hashmap_hash_fn)(const void *key, void *ctx); typedef size_t (*hashmap_hash_fn)(const void *key, void *ctx);
@@ -177,17 +158,17 @@ bool hashmap__find(const struct hashmap *map, const void *key, void **value);
* @key: key to iterate entries for * @key: key to iterate entries for
*/ */
#define hashmap__for_each_key_entry(map, cur, _key) \ #define hashmap__for_each_key_entry(map, cur, _key) \
for (cur = map->buckets \ for (cur = ({ size_t bkt = hash_bits(map->hash_fn((_key), map->ctx),\
? map->buckets[hash_bits(map->hash_fn((_key), map->ctx), map->cap_bits)] \ map->cap_bits); \
: NULL; \ map->buckets ? map->buckets[bkt] : NULL; }); \
cur; \ cur; \
cur = cur->next) \ cur = cur->next) \
if (map->equal_fn(cur->key, (_key), map->ctx)) if (map->equal_fn(cur->key, (_key), map->ctx))
#define hashmap__for_each_key_entry_safe(map, cur, tmp, _key) \ #define hashmap__for_each_key_entry_safe(map, cur, tmp, _key) \
for (cur = map->buckets \ for (cur = ({ size_t bkt = hash_bits(map->hash_fn((_key), map->ctx),\
? map->buckets[hash_bits(map->hash_fn((_key), map->ctx), map->cap_bits)] \ map->cap_bits); \
: NULL; \ cur = map->buckets ? map->buckets[bkt] : NULL; }); \
cur && ({ tmp = cur->next; true; }); \ cur && ({ tmp = cur->next; true; }); \
cur = tmp) \ cur = tmp) \
if (map->equal_fn(cur->key, (_key), map->ctx)) if (map->equal_fn(cur->key, (_key), map->ctx))

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,6 @@
#include <linux/bpf.h> #include <linux/bpf.h>
#include "libbpf_common.h" #include "libbpf_common.h"
#include "libbpf_legacy.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -83,29 +82,19 @@ struct bpf_object_open_opts {
* Non-relocatable instructions are replaced with invalid ones to * Non-relocatable instructions are replaced with invalid ones to
* prevent accidental errors. * prevent accidental errors.
* */ * */
LIBBPF_DEPRECATED_SINCE(0, 6, "field has no effect")
bool relaxed_core_relocs; bool relaxed_core_relocs;
/* maps that set the 'pinning' attribute in their definition will have /* maps that set the 'pinning' attribute in their definition will have
* their pin_path attribute set to a file in this directory, and be * their pin_path attribute set to a file in this directory, and be
* auto-pinned to that path on load; defaults to "/sys/fs/bpf". * auto-pinned to that path on load; defaults to "/sys/fs/bpf".
*/ */
const char *pin_root_path; const char *pin_root_path;
LIBBPF_DEPRECATED_SINCE(0, 7, "use bpf_program__set_attach_target() on each individual bpf_program")
__u32 attach_prog_fd; __u32 attach_prog_fd;
/* Additional kernel config content that augments and overrides /* Additional kernel config content that augments and overrides
* system Kconfig for CONFIG_xxx externs. * system Kconfig for CONFIG_xxx externs.
*/ */
const char *kconfig; const char *kconfig;
/* Path to the custom BTF to be used for BPF CO-RE relocations.
* This custom BTF completely replaces the use of vmlinux BTF
* for the purpose of CO-RE relocations.
* NOTE: any other BPF feature (e.g., fentry/fexit programs,
* struct_ops, etc) will need actual kernel BTF at /sys/kernel/btf/vmlinux.
*/
const char *btf_custom_path;
}; };
#define bpf_object_open_opts__last_field btf_custom_path #define bpf_object_open_opts__last_field kconfig
LIBBPF_API struct bpf_object *bpf_object__open(const char *path); LIBBPF_API struct bpf_object *bpf_object__open(const char *path);
LIBBPF_API struct bpf_object * LIBBPF_API struct bpf_object *
@@ -150,12 +139,10 @@ struct bpf_object_load_attr {
/* Load/unload object into/from kernel */ /* Load/unload object into/from kernel */
LIBBPF_API int bpf_object__load(struct bpf_object *obj); LIBBPF_API int bpf_object__load(struct bpf_object *obj);
LIBBPF_API int bpf_object__load_xattr(struct bpf_object_load_attr *attr); LIBBPF_API int bpf_object__load_xattr(struct bpf_object_load_attr *attr);
LIBBPF_DEPRECATED_SINCE(0, 6, "bpf_object__unload() is deprecated, use bpf_object__close() instead")
LIBBPF_API int bpf_object__unload(struct bpf_object *obj); LIBBPF_API int bpf_object__unload(struct bpf_object *obj);
LIBBPF_API const char *bpf_object__name(const struct bpf_object *obj); LIBBPF_API const char *bpf_object__name(const struct bpf_object *obj);
LIBBPF_API unsigned int bpf_object__kversion(const struct bpf_object *obj); LIBBPF_API unsigned int bpf_object__kversion(const struct bpf_object *obj);
LIBBPF_API int bpf_object__set_kversion(struct bpf_object *obj, __u32 kern_version);
struct btf; struct btf;
LIBBPF_API struct btf *bpf_object__btf(const struct bpf_object *obj); LIBBPF_API struct btf *bpf_object__btf(const struct bpf_object *obj);
@@ -190,22 +177,16 @@ LIBBPF_API int libbpf_find_vmlinux_btf_id(const char *name,
/* Accessors of bpf_program */ /* Accessors of bpf_program */
struct bpf_program; struct bpf_program;
LIBBPF_API LIBBPF_DEPRECATED_SINCE(0, 7, "use bpf_object__next_program() instead") LIBBPF_API struct bpf_program *bpf_program__next(struct bpf_program *prog,
struct bpf_program *bpf_program__next(struct bpf_program *prog, const struct bpf_object *obj);
const struct bpf_object *obj);
LIBBPF_API struct bpf_program *
bpf_object__next_program(const struct bpf_object *obj, struct bpf_program *prog);
#define bpf_object__for_each_program(pos, obj) \ #define bpf_object__for_each_program(pos, obj) \
for ((pos) = bpf_object__next_program((obj), NULL); \ for ((pos) = bpf_program__next(NULL, (obj)); \
(pos) != NULL; \ (pos) != NULL; \
(pos) = bpf_object__next_program((obj), (pos))) (pos) = bpf_program__next((pos), (obj)))
LIBBPF_API LIBBPF_DEPRECATED_SINCE(0, 7, "use bpf_object__prev_program() instead") LIBBPF_API struct bpf_program *bpf_program__prev(struct bpf_program *prog,
struct bpf_program *bpf_program__prev(struct bpf_program *prog, const struct bpf_object *obj);
const struct bpf_object *obj);
LIBBPF_API struct bpf_program *
bpf_object__prev_program(const struct bpf_object *obj, struct bpf_program *prog);
typedef void (*bpf_program_clear_priv_t)(struct bpf_program *, void *); typedef void (*bpf_program_clear_priv_t)(struct bpf_program *, void *);
@@ -217,11 +198,8 @@ LIBBPF_API void bpf_program__set_ifindex(struct bpf_program *prog,
__u32 ifindex); __u32 ifindex);
LIBBPF_API const char *bpf_program__name(const struct bpf_program *prog); LIBBPF_API const char *bpf_program__name(const struct bpf_program *prog);
LIBBPF_API const char *bpf_program__section_name(const struct bpf_program *prog); LIBBPF_API const char *bpf_program__title(const struct bpf_program *prog,
LIBBPF_API LIBBPF_DEPRECATED("BPF program title is confusing term; please use bpf_program__section_name() instead") bool needs_copy);
const char *bpf_program__title(const struct bpf_program *prog, bool needs_copy);
LIBBPF_API bool bpf_program__autoload(const struct bpf_program *prog);
LIBBPF_API int bpf_program__set_autoload(struct bpf_program *prog, bool autoload);
/* returns program size in bytes */ /* returns program size in bytes */
LIBBPF_API size_t bpf_program__size(const struct bpf_program *prog); LIBBPF_API size_t bpf_program__size(const struct bpf_program *prog);
@@ -249,120 +227,46 @@ LIBBPF_API int bpf_link__unpin(struct bpf_link *link);
LIBBPF_API int bpf_link__update_program(struct bpf_link *link, LIBBPF_API int bpf_link__update_program(struct bpf_link *link,
struct bpf_program *prog); struct bpf_program *prog);
LIBBPF_API void bpf_link__disconnect(struct bpf_link *link); LIBBPF_API void bpf_link__disconnect(struct bpf_link *link);
LIBBPF_API int bpf_link__detach(struct bpf_link *link);
LIBBPF_API int bpf_link__destroy(struct bpf_link *link); LIBBPF_API int bpf_link__destroy(struct bpf_link *link);
LIBBPF_API struct bpf_link * LIBBPF_API struct bpf_link *
bpf_program__attach(const struct bpf_program *prog); 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 * LIBBPF_API struct bpf_link *
bpf_program__attach_perf_event(const struct bpf_program *prog, int pfd); bpf_program__attach_perf_event(struct bpf_program *prog, int pfd);
LIBBPF_API struct bpf_link * LIBBPF_API struct bpf_link *
bpf_program__attach_perf_event_opts(const struct bpf_program *prog, int pfd, bpf_program__attach_kprobe(struct bpf_program *prog, bool retprobe,
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 */
size_t 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(const struct bpf_program *prog, bool retprobe,
const char *func_name); const char *func_name);
LIBBPF_API struct bpf_link * LIBBPF_API struct bpf_link *
bpf_program__attach_kprobe_opts(const struct bpf_program *prog, bpf_program__attach_uprobe(struct bpf_program *prog, bool retprobe,
const char *func_name,
const struct bpf_kprobe_opts *opts);
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 */
bool retprobe;
size_t :0;
};
#define bpf_uprobe_opts__last_field retprobe
LIBBPF_API struct bpf_link *
bpf_program__attach_uprobe(const struct bpf_program *prog, bool retprobe,
pid_t pid, const char *binary_path, pid_t pid, const char *binary_path,
size_t func_offset); size_t func_offset);
LIBBPF_API struct bpf_link * LIBBPF_API struct bpf_link *
bpf_program__attach_uprobe_opts(const struct bpf_program *prog, pid_t pid, bpf_program__attach_tracepoint(struct bpf_program *prog,
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(const struct bpf_program *prog,
const char *tp_category, const char *tp_category,
const char *tp_name); const char *tp_name);
LIBBPF_API struct bpf_link * LIBBPF_API struct bpf_link *
bpf_program__attach_tracepoint_opts(const struct bpf_program *prog, bpf_program__attach_raw_tracepoint(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(const struct bpf_program *prog,
const char *tp_name); const char *tp_name);
LIBBPF_API struct bpf_link * LIBBPF_API struct bpf_link *
bpf_program__attach_trace(const struct bpf_program *prog); bpf_program__attach_trace(struct bpf_program *prog);
LIBBPF_API struct bpf_link * LIBBPF_API struct bpf_link *
bpf_program__attach_lsm(const struct bpf_program *prog); bpf_program__attach_lsm(struct bpf_program *prog);
LIBBPF_API struct bpf_link * LIBBPF_API struct bpf_link *
bpf_program__attach_cgroup(const struct bpf_program *prog, int cgroup_fd); bpf_program__attach_cgroup(struct bpf_program *prog, int cgroup_fd);
LIBBPF_API struct bpf_link * LIBBPF_API struct bpf_link *
bpf_program__attach_netns(const struct bpf_program *prog, int netns_fd); bpf_program__attach_netns(struct bpf_program *prog, int netns_fd);
LIBBPF_API struct bpf_link *
bpf_program__attach_xdp(const struct bpf_program *prog, int ifindex);
LIBBPF_API struct bpf_link *
bpf_program__attach_freplace(const struct bpf_program *prog,
int target_fd, const char *attach_func_name);
struct bpf_map; struct bpf_map;
LIBBPF_API struct bpf_link *bpf_map__attach_struct_ops(const struct bpf_map *map); LIBBPF_API struct bpf_link *bpf_map__attach_struct_ops(struct bpf_map *map);
struct bpf_iter_attach_opts { struct bpf_iter_attach_opts {
size_t sz; /* size of this struct for forward/backward compatibility */ size_t sz; /* size of this struct for forward/backward compatibility */
union bpf_iter_link_info *link_info;
__u32 link_info_len;
}; };
#define bpf_iter_attach_opts__last_field link_info_len #define bpf_iter_attach_opts__last_field sz
LIBBPF_API struct bpf_link * LIBBPF_API struct bpf_link *
bpf_program__attach_iter(const struct bpf_program *prog, bpf_program__attach_iter(struct bpf_program *prog,
const struct bpf_iter_attach_opts *opts); const struct bpf_iter_attach_opts *opts);
struct bpf_insn; struct bpf_insn;
@@ -444,14 +348,13 @@ LIBBPF_API int bpf_program__set_perf_event(struct bpf_program *prog);
LIBBPF_API int bpf_program__set_tracing(struct bpf_program *prog); LIBBPF_API int bpf_program__set_tracing(struct bpf_program *prog);
LIBBPF_API int bpf_program__set_struct_ops(struct bpf_program *prog); LIBBPF_API int bpf_program__set_struct_ops(struct bpf_program *prog);
LIBBPF_API int bpf_program__set_extension(struct bpf_program *prog); LIBBPF_API int bpf_program__set_extension(struct bpf_program *prog);
LIBBPF_API int bpf_program__set_sk_lookup(struct bpf_program *prog);
LIBBPF_API enum bpf_prog_type bpf_program__get_type(const struct bpf_program *prog); LIBBPF_API enum bpf_prog_type bpf_program__get_type(struct bpf_program *prog);
LIBBPF_API void bpf_program__set_type(struct bpf_program *prog, LIBBPF_API void bpf_program__set_type(struct bpf_program *prog,
enum bpf_prog_type type); enum bpf_prog_type type);
LIBBPF_API enum bpf_attach_type LIBBPF_API enum bpf_attach_type
bpf_program__get_expected_attach_type(const struct bpf_program *prog); bpf_program__get_expected_attach_type(struct bpf_program *prog);
LIBBPF_API void LIBBPF_API void
bpf_program__set_expected_attach_type(struct bpf_program *prog, bpf_program__set_expected_attach_type(struct bpf_program *prog,
enum bpf_attach_type type); enum bpf_attach_type type);
@@ -472,7 +375,6 @@ LIBBPF_API bool bpf_program__is_perf_event(const struct bpf_program *prog);
LIBBPF_API bool bpf_program__is_tracing(const struct bpf_program *prog); LIBBPF_API bool bpf_program__is_tracing(const struct bpf_program *prog);
LIBBPF_API bool bpf_program__is_struct_ops(const struct bpf_program *prog); LIBBPF_API bool bpf_program__is_struct_ops(const struct bpf_program *prog);
LIBBPF_API bool bpf_program__is_extension(const struct bpf_program *prog); LIBBPF_API bool bpf_program__is_extension(const struct bpf_program *prog);
LIBBPF_API bool bpf_program__is_sk_lookup(const struct bpf_program *prog);
/* /*
* No need for __attribute__((packed)), all members of 'bpf_map_def' * No need for __attribute__((packed)), all members of 'bpf_map_def'
@@ -488,13 +390,9 @@ struct bpf_map_def {
unsigned int map_flags; unsigned int map_flags;
}; };
/** /*
* @brief **bpf_object__find_map_by_name()** returns BPF map of * The 'struct bpf_map' in include/linux/bpf.h is internal to the kernel,
* the given name, if it exists within the passed BPF object * so no need to worry about a name clash.
* @param obj BPF object
* @param name name of the BPF map
* @return BPF map instance, if such map exists within the BPF object;
* or NULL otherwise.
*/ */
LIBBPF_API struct bpf_map * LIBBPF_API struct bpf_map *
bpf_object__find_map_by_name(const struct bpf_object *obj, const char *name); bpf_object__find_map_by_name(const struct bpf_object *obj, const char *name);
@@ -509,59 +407,22 @@ bpf_object__find_map_fd_by_name(const struct bpf_object *obj, const char *name);
LIBBPF_API struct bpf_map * LIBBPF_API struct bpf_map *
bpf_object__find_map_by_offset(struct bpf_object *obj, size_t offset); bpf_object__find_map_by_offset(struct bpf_object *obj, size_t offset);
LIBBPF_API LIBBPF_DEPRECATED_SINCE(0, 7, "use bpf_object__next_map() instead")
struct bpf_map *bpf_map__next(const struct bpf_map *map, const struct bpf_object *obj);
LIBBPF_API struct bpf_map * LIBBPF_API struct bpf_map *
bpf_object__next_map(const struct bpf_object *obj, const struct bpf_map *map); bpf_map__next(const struct bpf_map *map, const struct bpf_object *obj);
#define bpf_object__for_each_map(pos, obj) \ #define bpf_object__for_each_map(pos, obj) \
for ((pos) = bpf_object__next_map((obj), NULL); \ for ((pos) = bpf_map__next(NULL, (obj)); \
(pos) != NULL; \ (pos) != NULL; \
(pos) = bpf_object__next_map((obj), (pos))) (pos) = bpf_map__next((pos), (obj)))
#define bpf_map__for_each bpf_object__for_each_map #define bpf_map__for_each bpf_object__for_each_map
LIBBPF_API LIBBPF_DEPRECATED_SINCE(0, 7, "use bpf_object__prev_map() instead")
struct bpf_map *bpf_map__prev(const struct bpf_map *map, const struct bpf_object *obj);
LIBBPF_API struct bpf_map * LIBBPF_API struct bpf_map *
bpf_object__prev_map(const struct bpf_object *obj, const struct bpf_map *map); bpf_map__prev(const struct bpf_map *map, const struct bpf_object *obj);
/**
* @brief **bpf_map__fd()** gets the file descriptor of the passed
* BPF map
* @param map the BPF map instance
* @return the file descriptor; or -EINVAL in case of an error
*/
LIBBPF_API int bpf_map__fd(const struct bpf_map *map); LIBBPF_API int bpf_map__fd(const struct bpf_map *map);
LIBBPF_API int bpf_map__reuse_fd(struct bpf_map *map, int fd);
/* get map definition */
LIBBPF_API const struct bpf_map_def *bpf_map__def(const struct bpf_map *map); LIBBPF_API const struct bpf_map_def *bpf_map__def(const struct bpf_map *map);
/* get map name */
LIBBPF_API const char *bpf_map__name(const struct bpf_map *map); LIBBPF_API const char *bpf_map__name(const struct bpf_map *map);
/* get/set map type */
LIBBPF_API enum bpf_map_type bpf_map__type(const struct bpf_map *map);
LIBBPF_API int bpf_map__set_type(struct bpf_map *map, enum bpf_map_type type);
/* get/set map size (max_entries) */
LIBBPF_API __u32 bpf_map__max_entries(const struct bpf_map *map);
LIBBPF_API int bpf_map__set_max_entries(struct bpf_map *map, __u32 max_entries);
LIBBPF_API int bpf_map__resize(struct bpf_map *map, __u32 max_entries);
/* get/set map flags */
LIBBPF_API __u32 bpf_map__map_flags(const struct bpf_map *map);
LIBBPF_API int bpf_map__set_map_flags(struct bpf_map *map, __u32 flags);
/* get/set map NUMA node */
LIBBPF_API __u32 bpf_map__numa_node(const struct bpf_map *map);
LIBBPF_API int bpf_map__set_numa_node(struct bpf_map *map, __u32 numa_node);
/* get/set map key size */
LIBBPF_API __u32 bpf_map__key_size(const struct bpf_map *map);
LIBBPF_API int bpf_map__set_key_size(struct bpf_map *map, __u32 size);
/* get/set map value size */
LIBBPF_API __u32 bpf_map__value_size(const struct bpf_map *map);
LIBBPF_API int bpf_map__set_value_size(struct bpf_map *map, __u32 size);
/* get map key/value BTF type IDs */
LIBBPF_API __u32 bpf_map__btf_key_type_id(const struct bpf_map *map); LIBBPF_API __u32 bpf_map__btf_key_type_id(const struct bpf_map *map);
LIBBPF_API __u32 bpf_map__btf_value_type_id(const struct bpf_map *map); LIBBPF_API __u32 bpf_map__btf_value_type_id(const struct bpf_map *map);
/* get/set map if_index */
LIBBPF_API __u32 bpf_map__ifindex(const struct bpf_map *map);
LIBBPF_API int bpf_map__set_ifindex(struct bpf_map *map, __u32 ifindex);
typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *); typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);
LIBBPF_API int bpf_map__set_priv(struct bpf_map *map, void *priv, LIBBPF_API int bpf_map__set_priv(struct bpf_map *map, void *priv,
@@ -569,59 +430,19 @@ LIBBPF_API int bpf_map__set_priv(struct bpf_map *map, void *priv,
LIBBPF_API void *bpf_map__priv(const struct bpf_map *map); LIBBPF_API void *bpf_map__priv(const struct bpf_map *map);
LIBBPF_API int bpf_map__set_initial_value(struct bpf_map *map, LIBBPF_API int bpf_map__set_initial_value(struct bpf_map *map,
const void *data, size_t size); const void *data, size_t size);
LIBBPF_API const void *bpf_map__initial_value(struct bpf_map *map, size_t *psize); LIBBPF_API int bpf_map__reuse_fd(struct bpf_map *map, int fd);
LIBBPF_API int bpf_map__resize(struct bpf_map *map, __u32 max_entries);
LIBBPF_API bool bpf_map__is_offload_neutral(const struct bpf_map *map); LIBBPF_API bool bpf_map__is_offload_neutral(const struct bpf_map *map);
/**
* @brief **bpf_map__is_internal()** tells the caller whether or not the
* passed map is a special map created by libbpf automatically for things like
* global variables, __ksym externs, Kconfig values, etc
* @param map the bpf_map
* @return true, if the map is an internal map; false, otherwise
*/
LIBBPF_API bool bpf_map__is_internal(const struct bpf_map *map); LIBBPF_API bool bpf_map__is_internal(const struct bpf_map *map);
LIBBPF_API void bpf_map__set_ifindex(struct bpf_map *map, __u32 ifindex);
LIBBPF_API int bpf_map__set_pin_path(struct bpf_map *map, const char *path); LIBBPF_API int bpf_map__set_pin_path(struct bpf_map *map, const char *path);
LIBBPF_API const char *bpf_map__get_pin_path(const struct bpf_map *map); LIBBPF_API const char *bpf_map__get_pin_path(const struct bpf_map *map);
LIBBPF_API const char *bpf_map__pin_path(const struct bpf_map *map);
LIBBPF_API bool bpf_map__is_pinned(const struct bpf_map *map); LIBBPF_API bool bpf_map__is_pinned(const struct bpf_map *map);
LIBBPF_API int bpf_map__pin(struct bpf_map *map, const char *path); LIBBPF_API int bpf_map__pin(struct bpf_map *map, const char *path);
LIBBPF_API int bpf_map__unpin(struct bpf_map *map, const char *path); LIBBPF_API int bpf_map__unpin(struct bpf_map *map, const char *path);
LIBBPF_API int bpf_map__set_inner_map_fd(struct bpf_map *map, int fd); LIBBPF_API int bpf_map__set_inner_map_fd(struct bpf_map *map, int fd);
LIBBPF_API struct bpf_map *bpf_map__inner_map(struct bpf_map *map);
/**
* @brief **libbpf_get_error()** extracts the error code from the passed
* pointer
* @param ptr pointer returned from libbpf API function
* @return error code; or 0 if no error occured
*
* Many libbpf API functions which return pointers have logic to encode error
* codes as pointers, and do not return NULL. Meaning **libbpf_get_error()**
* should be used on the return value from these functions immediately after
* calling the API function, with no intervening calls that could clobber the
* `errno` variable. Consult the individual functions documentation to verify
* if this logic applies should be used.
*
* For these API functions, if `libbpf_set_strict_mode(LIBBPF_STRICT_CLEAN_PTRS)`
* is enabled, NULL is returned on error instead.
*
* If ptr is NULL, then errno should be already set by the failing
* API, because libbpf never returns NULL on success and it now always
* sets errno on error.
*
* Example usage:
*
* struct perf_buffer *pb;
*
* pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES, &opts);
* err = libbpf_get_error(pb);
* if (err) {
* pb = NULL;
* fprintf(stderr, "failed to open perf buffer: %d\n", err);
* goto cleanup;
* }
*/
LIBBPF_API long libbpf_get_error(const void *ptr); LIBBPF_API long libbpf_get_error(const void *ptr);
struct bpf_prog_load_attr { struct bpf_prog_load_attr {
@@ -638,7 +459,6 @@ LIBBPF_API int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
LIBBPF_API int bpf_prog_load(const char *file, enum bpf_prog_type type, LIBBPF_API int bpf_prog_load(const char *file, enum bpf_prog_type type,
struct bpf_object **pobj, int *prog_fd); struct bpf_object **pobj, int *prog_fd);
/* XDP related API */
struct xdp_link_info { struct xdp_link_info {
__u32 prog_id; __u32 prog_id;
__u32 drv_prog_id; __u32 drv_prog_id;
@@ -650,7 +470,6 @@ struct xdp_link_info {
struct bpf_xdp_set_link_opts { struct bpf_xdp_set_link_opts {
size_t sz; size_t sz;
int old_fd; int old_fd;
size_t :0;
}; };
#define bpf_xdp_set_link_opts__last_field old_fd #define bpf_xdp_set_link_opts__last_field old_fd
@@ -661,49 +480,6 @@ LIBBPF_API int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags);
LIBBPF_API int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info, LIBBPF_API int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info,
size_t info_size, __u32 flags); size_t info_size, __u32 flags);
/* TC related API */
enum bpf_tc_attach_point {
BPF_TC_INGRESS = 1 << 0,
BPF_TC_EGRESS = 1 << 1,
BPF_TC_CUSTOM = 1 << 2,
};
#define BPF_TC_PARENT(a, b) \
((((a) << 16) & 0xFFFF0000U) | ((b) & 0x0000FFFFU))
enum bpf_tc_flags {
BPF_TC_F_REPLACE = 1 << 0,
};
struct bpf_tc_hook {
size_t sz;
int ifindex;
enum bpf_tc_attach_point attach_point;
__u32 parent;
size_t :0;
};
#define bpf_tc_hook__last_field parent
struct bpf_tc_opts {
size_t sz;
int prog_fd;
__u32 flags;
__u32 prog_id;
__u32 handle;
__u32 priority;
size_t :0;
};
#define bpf_tc_opts__last_field priority
LIBBPF_API int bpf_tc_hook_create(struct bpf_tc_hook *hook);
LIBBPF_API int bpf_tc_hook_destroy(struct bpf_tc_hook *hook);
LIBBPF_API int bpf_tc_attach(const struct bpf_tc_hook *hook,
struct bpf_tc_opts *opts);
LIBBPF_API int bpf_tc_detach(const struct bpf_tc_hook *hook,
const struct bpf_tc_opts *opts);
LIBBPF_API int bpf_tc_query(const struct bpf_tc_hook *hook,
struct bpf_tc_opts *opts);
/* Ring buffer APIs */ /* Ring buffer APIs */
struct ring_buffer; struct ring_buffer;
@@ -723,7 +499,6 @@ LIBBPF_API int ring_buffer__add(struct ring_buffer *rb, int map_fd,
ring_buffer_sample_fn sample_cb, void *ctx); ring_buffer_sample_fn sample_cb, void *ctx);
LIBBPF_API int ring_buffer__poll(struct ring_buffer *rb, int timeout_ms); LIBBPF_API int ring_buffer__poll(struct ring_buffer *rb, int timeout_ms);
LIBBPF_API int ring_buffer__consume(struct ring_buffer *rb); LIBBPF_API int ring_buffer__consume(struct ring_buffer *rb);
LIBBPF_API int ring_buffer__epoll_fd(const struct ring_buffer *rb);
/* Perf buffer APIs */ /* Perf buffer APIs */
struct perf_buffer; struct perf_buffer;
@@ -780,12 +555,8 @@ perf_buffer__new_raw(int map_fd, size_t page_cnt,
const struct perf_buffer_raw_opts *opts); const struct perf_buffer_raw_opts *opts);
LIBBPF_API void perf_buffer__free(struct perf_buffer *pb); LIBBPF_API void perf_buffer__free(struct perf_buffer *pb);
LIBBPF_API int perf_buffer__epoll_fd(const struct perf_buffer *pb);
LIBBPF_API int perf_buffer__poll(struct perf_buffer *pb, int timeout_ms); LIBBPF_API int perf_buffer__poll(struct perf_buffer *pb, int timeout_ms);
LIBBPF_API int perf_buffer__consume(struct perf_buffer *pb); LIBBPF_API int perf_buffer__consume(struct perf_buffer *pb);
LIBBPF_API int perf_buffer__consume_buffer(struct perf_buffer *pb, size_t buf_idx);
LIBBPF_API size_t perf_buffer__buffer_cnt(const struct perf_buffer *pb);
LIBBPF_API int perf_buffer__buffer_fd(const struct perf_buffer *pb, size_t buf_idx);
typedef enum bpf_perf_event_ret typedef enum bpf_perf_event_ret
(*bpf_perf_event_print_t)(struct perf_event_header *hdr, (*bpf_perf_event_print_t)(struct perf_event_header *hdr,
@@ -886,10 +657,9 @@ bpf_program__bpil_addr_to_offs(struct bpf_prog_info_linear *info_linear);
LIBBPF_API void LIBBPF_API void
bpf_program__bpil_offs_to_addr(struct bpf_prog_info_linear *info_linear); bpf_program__bpil_offs_to_addr(struct bpf_prog_info_linear *info_linear);
/** /*
* @brief **libbpf_num_possible_cpus()** is a helper function to get the * A helper function to get the number of possible CPUs before looking up
* number of possible CPUs that the host kernel supports and expects. * per-CPU maps. Negative errno is returned on failure.
* @return number of possible CPUs; or error code on failure
* *
* Example usage: * Example usage:
* *
@@ -899,6 +669,7 @@ bpf_program__bpil_offs_to_addr(struct bpf_prog_info_linear *info_linear);
* } * }
* long values[ncpus]; * long values[ncpus];
* bpf_map_lookup_elem(per_cpu_map_fd, key, values); * bpf_map_lookup_elem(per_cpu_map_fd, key, values);
*
*/ */
LIBBPF_API int libbpf_num_possible_cpus(void); LIBBPF_API int libbpf_num_possible_cpus(void);
@@ -918,7 +689,7 @@ struct bpf_object_skeleton {
size_t sz; /* size of this struct, for forward/backward compatibility */ size_t sz; /* size of this struct, for forward/backward compatibility */
const char *name; const char *name;
const void *data; void *data;
size_t data_sz; size_t data_sz;
struct bpf_object **obj; struct bpf_object **obj;
@@ -940,45 +711,12 @@ LIBBPF_API int bpf_object__attach_skeleton(struct bpf_object_skeleton *s);
LIBBPF_API void bpf_object__detach_skeleton(struct bpf_object_skeleton *s); LIBBPF_API void bpf_object__detach_skeleton(struct bpf_object_skeleton *s);
LIBBPF_API void bpf_object__destroy_skeleton(struct bpf_object_skeleton *s); LIBBPF_API void bpf_object__destroy_skeleton(struct bpf_object_skeleton *s);
struct gen_loader_opts {
size_t sz; /* size of this struct, for forward/backward compatiblity */
const char *data;
const char *insns;
__u32 data_sz;
__u32 insns_sz;
};
#define gen_loader_opts__last_field insns_sz
LIBBPF_API int bpf_object__gen_loader(struct bpf_object *obj,
struct gen_loader_opts *opts);
enum libbpf_tristate { enum libbpf_tristate {
TRI_NO = 0, TRI_NO = 0,
TRI_YES = 1, TRI_YES = 1,
TRI_MODULE = 2, TRI_MODULE = 2,
}; };
struct bpf_linker_opts {
/* size of this struct, for forward/backward compatiblity */
size_t sz;
};
#define bpf_linker_opts__last_field sz
struct bpf_linker_file_opts {
/* size of this struct, for forward/backward compatiblity */
size_t sz;
};
#define bpf_linker_file_opts__last_field sz
struct bpf_linker;
LIBBPF_API struct bpf_linker *bpf_linker__new(const char *filename, struct bpf_linker_opts *opts);
LIBBPF_API int bpf_linker__add_file(struct bpf_linker *linker,
const char *filename,
const struct bpf_linker_file_opts *opts);
LIBBPF_API int bpf_linker__finalize(struct bpf_linker *linker);
LIBBPF_API void bpf_linker__free(struct bpf_linker *linker);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif

View File

@@ -270,129 +270,3 @@ LIBBPF_0.0.9 {
ring_buffer__new; ring_buffer__new;
ring_buffer__poll; ring_buffer__poll;
} LIBBPF_0.0.8; } LIBBPF_0.0.8;
LIBBPF_0.1.0 {
global:
bpf_link__detach;
bpf_link_detach;
bpf_map__ifindex;
bpf_map__key_size;
bpf_map__map_flags;
bpf_map__max_entries;
bpf_map__numa_node;
bpf_map__set_key_size;
bpf_map__set_map_flags;
bpf_map__set_max_entries;
bpf_map__set_numa_node;
bpf_map__set_type;
bpf_map__set_value_size;
bpf_map__type;
bpf_map__value_size;
bpf_program__attach_xdp;
bpf_program__autoload;
bpf_program__is_sk_lookup;
bpf_program__set_autoload;
bpf_program__set_sk_lookup;
btf__parse;
btf__parse_raw;
btf__pointer_size;
btf__set_fd;
btf__set_pointer_size;
} LIBBPF_0.0.9;
LIBBPF_0.2.0 {
global:
bpf_prog_bind_map;
bpf_prog_test_run_opts;
bpf_program__attach_freplace;
bpf_program__section_name;
btf__add_array;
btf__add_const;
btf__add_enum;
btf__add_enum_value;
btf__add_datasec;
btf__add_datasec_var_info;
btf__add_field;
btf__add_func;
btf__add_func_param;
btf__add_func_proto;
btf__add_fwd;
btf__add_int;
btf__add_ptr;
btf__add_restrict;
btf__add_str;
btf__add_struct;
btf__add_typedef;
btf__add_union;
btf__add_var;
btf__add_volatile;
btf__endianness;
btf__find_str;
btf__new_empty;
btf__set_endianness;
btf__str_by_offset;
perf_buffer__buffer_cnt;
perf_buffer__buffer_fd;
perf_buffer__epoll_fd;
perf_buffer__consume_buffer;
xsk_socket__create_shared;
} LIBBPF_0.1.0;
LIBBPF_0.3.0 {
global:
btf__base_btf;
btf__parse_elf_split;
btf__parse_raw_split;
btf__parse_split;
btf__new_empty_split;
btf__new_split;
ring_buffer__epoll_fd;
xsk_setup_xdp_prog;
xsk_socket__update_xskmap;
} LIBBPF_0.2.0;
LIBBPF_0.4.0 {
global:
btf__add_float;
btf__add_type;
bpf_linker__add_file;
bpf_linker__finalize;
bpf_linker__free;
bpf_linker__new;
bpf_map__inner_map;
bpf_object__set_kversion;
bpf_tc_attach;
bpf_tc_detach;
bpf_tc_hook_create;
bpf_tc_hook_destroy;
bpf_tc_query;
} LIBBPF_0.3.0;
LIBBPF_0.5.0 {
global:
bpf_map__initial_value;
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;
btf__load_into_kernel;
btf__load_module_btf;
btf__load_vmlinux_btf;
btf_dump__dump_type_data;
libbpf_set_strict_mode;
} LIBBPF_0.4.0;
LIBBPF_0.6.0 {
global:
bpf_object__next_map;
bpf_object__next_program;
bpf_object__prev_map;
bpf_object__prev_program;
btf__add_btf;
btf__add_tag;
} LIBBPF_0.5.0;

View File

@@ -10,37 +10,11 @@
#define __LIBBPF_LIBBPF_COMMON_H #define __LIBBPF_LIBBPF_COMMON_H
#include <string.h> #include <string.h>
#include "libbpf_version.h"
#ifndef LIBBPF_API #ifndef LIBBPF_API
#define LIBBPF_API __attribute__((visibility("default"))) #define LIBBPF_API __attribute__((visibility("default")))
#endif #endif
#define LIBBPF_DEPRECATED(msg) __attribute__((deprecated(msg)))
/* Mark a symbol as deprecated when libbpf version is >= {major}.{minor} */
#define LIBBPF_DEPRECATED_SINCE(major, minor, msg) \
__LIBBPF_MARK_DEPRECATED_ ## major ## _ ## minor \
(LIBBPF_DEPRECATED("libbpf v" # major "." # minor "+: " msg))
#define __LIBBPF_CURRENT_VERSION_GEQ(major, minor) \
(LIBBPF_MAJOR_VERSION > (major) || \
(LIBBPF_MAJOR_VERSION == (major) && LIBBPF_MINOR_VERSION >= (minor)))
/* Add checks for other versions below when planning deprecation of API symbols
* with the LIBBPF_DEPRECATED_SINCE macro.
*/
#if __LIBBPF_CURRENT_VERSION_GEQ(0, 6)
#define __LIBBPF_MARK_DEPRECATED_0_6(X) X
#else
#define __LIBBPF_MARK_DEPRECATED_0_6(X)
#endif
#if __LIBBPF_CURRENT_VERSION_GEQ(0, 7)
#define __LIBBPF_MARK_DEPRECATED_0_7(X) X
#else
#define __LIBBPF_MARK_DEPRECATED_0_7(X)
#endif
/* Helper macro to declare and initialize libbpf options struct /* Helper macro to declare and initialize libbpf options struct
* *
* This dance with uninitialized declaration, followed by memset to zero, * This dance with uninitialized declaration, followed by memset to zero,

View File

@@ -12,7 +12,6 @@
#include <string.h> #include <string.h>
#include "libbpf.h" #include "libbpf.h"
#include "libbpf_internal.h"
/* make sure libbpf doesn't use kernel-only integer typedefs */ /* make sure libbpf doesn't use kernel-only integer typedefs */
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64 #pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
@@ -40,7 +39,7 @@ static const char *libbpf_strerror_table[NR_ERRNO] = {
int libbpf_strerror(int err, char *buf, size_t size) int libbpf_strerror(int err, char *buf, size_t size)
{ {
if (!buf || !size) if (!buf || !size)
return libbpf_err(-EINVAL); return -1;
err = err > 0 ? err : -err; err = err > 0 ? err : -err;
@@ -49,7 +48,7 @@ int libbpf_strerror(int err, char *buf, size_t size)
ret = strerror_r(err, buf, size); ret = strerror_r(err, buf, size);
buf[size - 1] = '\0'; buf[size - 1] = '\0';
return libbpf_err_errno(ret); return ret;
} }
if (err < __LIBBPF_ERRNO__END) { if (err < __LIBBPF_ERRNO__END) {
@@ -63,5 +62,5 @@ int libbpf_strerror(int err, char *buf, size_t size)
snprintf(buf, size, "Unknown libbpf error %d", err); snprintf(buf, size, "Unknown libbpf error %d", err);
buf[size - 1] = '\0'; buf[size - 1] = '\0';
return libbpf_err(-ENOENT); return -1;
} }

View File

@@ -9,52 +9,7 @@
#ifndef __LIBBPF_LIBBPF_INTERNAL_H #ifndef __LIBBPF_LIBBPF_INTERNAL_H
#define __LIBBPF_LIBBPF_INTERNAL_H #define __LIBBPF_LIBBPF_INTERNAL_H
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <linux/err.h>
#include "libbpf_legacy.h"
#include "relo_core.h"
/* make sure libbpf doesn't use kernel-only integer typedefs */
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
/* prevent accidental re-addition of reallocarray() */
#pragma GCC poison reallocarray
#include "libbpf.h" #include "libbpf.h"
#include "btf.h"
#ifndef EM_BPF
#define EM_BPF 247
#endif
#ifndef R_BPF_64_64
#define R_BPF_64_64 1
#endif
#ifndef R_BPF_64_ABS64
#define R_BPF_64_ABS64 2
#endif
#ifndef R_BPF_64_ABS32
#define R_BPF_64_ABS32 3
#endif
#ifndef R_BPF_64_32
#define R_BPF_64_32 10
#endif
#ifndef SHT_LLVM_ADDRSIG
#define SHT_LLVM_ADDRSIG 0x6FFF4C03
#endif
/* if libelf is old and doesn't support mmap(), fall back to read() */
#ifndef ELF_C_READ_MMAP
#define ELF_C_READ_MMAP ELF_C_READ
#endif
/* Older libelf all end up in this expression, for both 32 and 64 bit */
#ifndef GELF_ST_VISIBILITY
#define GELF_ST_VISIBILITY(o) ((o) & 0x03)
#endif
#define BTF_INFO_ENC(kind, kind_flag, vlen) \ #define BTF_INFO_ENC(kind, kind_flag, vlen) \
((!!(kind_flag) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN)) ((!!(kind_flag) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
@@ -67,17 +22,7 @@
#define BTF_MEMBER_ENC(name, type, bits_offset) (name), (type), (bits_offset) #define BTF_MEMBER_ENC(name, type, bits_offset) (name), (type), (bits_offset)
#define BTF_PARAM_ENC(name, type) (name), (type) #define BTF_PARAM_ENC(name, type) (name), (type)
#define BTF_VAR_SECINFO_ENC(type, offset, size) (type), (offset), (size) #define BTF_VAR_SECINFO_ENC(type, offset, size) (type), (offset), (size)
#define BTF_TYPE_FLOAT_ENC(name, sz) \
BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_FLOAT, 0, 0), sz)
#define BTF_TYPE_TAG_ENC(value, type, component_idx) \
BTF_TYPE_ENC(value, BTF_INFO_ENC(BTF_KIND_TAG, 0, 0), type), (component_idx)
#ifndef likely
#define likely(x) __builtin_expect(!!(x), 1)
#endif
#ifndef unlikely
#define unlikely(x) __builtin_expect(!!(x), 0)
#endif
#ifndef min #ifndef min
# define min(x, y) ((x) < (y) ? (x) : (y)) # define min(x, y) ((x) < (y) ? (x) : (y))
#endif #endif
@@ -89,40 +34,20 @@
(offsetof(TYPE, FIELD) + sizeof(((TYPE *)0)->FIELD)) (offsetof(TYPE, FIELD) + sizeof(((TYPE *)0)->FIELD))
#endif #endif
/* Check whether a string `str` has prefix `pfx`, regardless if `pfx` is
* a string literal known at compilation time or char * pointer known only at
* runtime.
*/
#define str_has_pfx(str, pfx) \
(strncmp(str, pfx, __builtin_constant_p(pfx) ? sizeof(pfx) - 1 : strlen(pfx)) == 0)
/* Symbol versioning is different between static and shared library. /* Symbol versioning is different between static and shared library.
* Properly versioned symbols are needed for shared library, but * Properly versioned symbols are needed for shared library, but
* only the symbol of the new version is needed for static library. * only the symbol of the new version is needed for static library.
* Starting with GNU C 10, use symver attribute instead of .symver assembler
* directive, which works better with GCC LTO builds.
*/ */
#if defined(SHARED) && defined(__GNUC__) && __GNUC__ >= 10 #ifdef SHARED
# define COMPAT_VERSION(internal_name, api_name, version) \
#define DEFAULT_VERSION(internal_name, api_name, version) \
__attribute__((symver(#api_name "@@" #version)))
#define COMPAT_VERSION(internal_name, api_name, version) \
__attribute__((symver(#api_name "@" #version)))
#elif defined(SHARED)
#define COMPAT_VERSION(internal_name, api_name, version) \
asm(".symver " #internal_name "," #api_name "@" #version); asm(".symver " #internal_name "," #api_name "@" #version);
#define DEFAULT_VERSION(internal_name, api_name, version) \ # define DEFAULT_VERSION(internal_name, api_name, version) \
asm(".symver " #internal_name "," #api_name "@@" #version); asm(".symver " #internal_name "," #api_name "@@" #version);
#else
#else /* !SHARED */ # define COMPAT_VERSION(internal_name, api_name, version)
# define DEFAULT_VERSION(internal_name, api_name, version) \
#define COMPAT_VERSION(internal_name, api_name, version)
#define DEFAULT_VERSION(internal_name, api_name, version) \
extern typeof(internal_name) api_name \ extern typeof(internal_name) api_name \
__attribute__((alias(#internal_name))); __attribute__((alias(#internal_name)));
#endif #endif
extern void libbpf_print(enum libbpf_print_level level, extern void libbpf_print(enum libbpf_print_level level,
@@ -138,97 +63,6 @@ do { \
#define pr_info(fmt, ...) __pr(LIBBPF_INFO, fmt, ##__VA_ARGS__) #define pr_info(fmt, ...) __pr(LIBBPF_INFO, fmt, ##__VA_ARGS__)
#define pr_debug(fmt, ...) __pr(LIBBPF_DEBUG, fmt, ##__VA_ARGS__) #define pr_debug(fmt, ...) __pr(LIBBPF_DEBUG, fmt, ##__VA_ARGS__)
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
/*
* Re-implement glibc's reallocarray() for libbpf internal-only use.
* reallocarray(), unfortunately, is not available in all versions of glibc,
* so requires extra feature detection and using reallocarray() stub from
* <tools/libc_compat.h> and COMPAT_NEED_REALLOCARRAY. All this complicates
* build of libbpf unnecessarily and is just a maintenance burden. Instead,
* it's trivial to implement libbpf-specific internal version and use it
* throughout libbpf.
*/
static inline void *libbpf_reallocarray(void *ptr, size_t nmemb, size_t size)
{
size_t total;
#if __has_builtin(__builtin_mul_overflow)
if (unlikely(__builtin_mul_overflow(nmemb, size, &total)))
return NULL;
#else
if (size == 0 || nmemb > ULONG_MAX / size)
return NULL;
total = nmemb * size;
#endif
return realloc(ptr, total);
}
struct btf;
struct btf_type;
struct btf_type *btf_type_by_id(struct btf *btf, __u32 type_id);
const char *btf_kind_str(const struct btf_type *t);
const struct btf_type *skip_mods_and_typedefs(const struct btf *btf, __u32 id, __u32 *res_id);
static inline enum btf_func_linkage btf_func_linkage(const struct btf_type *t)
{
return (enum btf_func_linkage)(int)btf_vlen(t);
}
static inline __u32 btf_type_info(int kind, int vlen, int kflag)
{
return (kflag << 31) | (kind << 24) | vlen;
}
enum map_def_parts {
MAP_DEF_MAP_TYPE = 0x001,
MAP_DEF_KEY_TYPE = 0x002,
MAP_DEF_KEY_SIZE = 0x004,
MAP_DEF_VALUE_TYPE = 0x008,
MAP_DEF_VALUE_SIZE = 0x010,
MAP_DEF_MAX_ENTRIES = 0x020,
MAP_DEF_MAP_FLAGS = 0x040,
MAP_DEF_NUMA_NODE = 0x080,
MAP_DEF_PINNING = 0x100,
MAP_DEF_INNER_MAP = 0x200,
MAP_DEF_ALL = 0x3ff, /* combination of all above */
};
struct btf_map_def {
enum map_def_parts parts;
__u32 map_type;
__u32 key_type_id;
__u32 key_size;
__u32 value_type_id;
__u32 value_size;
__u32 max_entries;
__u32 map_flags;
__u32 numa_node;
__u32 pinning;
};
int parse_btf_map_def(const char *map_name, struct btf *btf,
const struct btf_type *def_t, bool strict,
struct btf_map_def *map_def, struct btf_map_def *inner_def);
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, static inline bool libbpf_validate_opts(const char *opts,
size_t opts_sz, size_t user_sz, size_t opts_sz, size_t user_sz,
const char *type_name) const char *type_name)
@@ -237,9 +71,16 @@ static inline bool libbpf_validate_opts(const char *opts,
pr_warn("%s size (%zu) is too small\n", type_name, user_sz); pr_warn("%s size (%zu) is too small\n", type_name, user_sz);
return false; return false;
} }
if (!libbpf_is_mem_zeroed(opts + opts_sz, (ssize_t)user_sz - opts_sz)) { if (user_sz > opts_sz) {
pr_warn("%s has non-zero extra bytes\n", type_name); size_t i;
return false;
for (i = opts_sz; i < user_sz; i++) {
if (opts[i]) {
pr_warn("%s has non-zero extra bytes\n",
type_name);
return false;
}
}
} }
return true; return true;
} }
@@ -253,63 +94,28 @@ static inline bool libbpf_validate_opts(const char *opts,
((opts) && opts->sz >= offsetofend(typeof(*(opts)), field)) ((opts) && opts->sz >= offsetofend(typeof(*(opts)), field))
#define OPTS_GET(opts, field, fallback_value) \ #define OPTS_GET(opts, field, fallback_value) \
(OPTS_HAS(opts, field) ? (opts)->field : fallback_value) (OPTS_HAS(opts, field) ? (opts)->field : fallback_value)
#define OPTS_SET(opts, field, value) \
do { \
if (OPTS_HAS(opts, field)) \
(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_str(const char *s, bool **mask, int *mask_sz);
int parse_cpu_mask_file(const char *fcpu, 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, int libbpf__load_raw_btf(const char *raw_types, size_t types_len,
const char *str_sec, size_t str_len); const char *str_sec, size_t str_len);
struct bpf_prog_load_params {
enum bpf_prog_type prog_type;
enum bpf_attach_type expected_attach_type;
const char *name;
const struct bpf_insn *insns;
size_t insn_cnt;
const char *license;
__u32 kern_version;
__u32 attach_prog_fd;
__u32 attach_btf_obj_fd;
__u32 attach_btf_id;
__u32 prog_ifindex;
__u32 prog_btf_fd;
__u32 prog_flags;
__u32 func_info_rec_size;
const void *func_info;
__u32 func_info_cnt;
__u32 line_info_rec_size;
const void *line_info;
__u32 line_info_cnt;
__u32 log_level;
char *log_buf;
size_t log_buf_sz;
int *fd_array;
};
int libbpf__bpf_prog_load(const struct bpf_prog_load_params *load_attr);
int bpf_object__section_size(const struct bpf_object *obj, const char *name, int bpf_object__section_size(const struct bpf_object *obj, const char *name,
__u32 *size); __u32 *size);
int bpf_object__variable_offset(const struct bpf_object *obj, const char *name, int bpf_object__variable_offset(const struct bpf_object *obj, const char *name,
__u32 *off); __u32 *off);
struct btf *btf_get_from_fd(int btf_fd, struct btf *base_btf);
void btf_get_kernel_prefix_kind(enum bpf_attach_type attach_type, struct nlattr;
const char **prefix, int *kind); typedef int (*libbpf_dump_nlmsg_t)(void *cookie, void *msg, struct nlattr **tb);
int libbpf_netlink_open(unsigned int *nl_pid);
int libbpf_nl_get_link(int sock, unsigned int nl_pid,
libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie);
int libbpf_nl_get_class(int sock, unsigned int nl_pid, int ifindex,
libbpf_dump_nlmsg_t dump_class_nlmsg, void *cookie);
int libbpf_nl_get_qdisc(int sock, unsigned int nl_pid, int ifindex,
libbpf_dump_nlmsg_t dump_qdisc_nlmsg, void *cookie);
int libbpf_nl_get_filter(int sock, unsigned int nl_pid, int ifindex, int handle,
libbpf_dump_nlmsg_t dump_filter_nlmsg, void *cookie);
struct btf_ext_info { struct btf_ext_info {
/* /*
@@ -332,44 +138,6 @@ struct btf_ext_info {
i < (sec)->num_info; \ i < (sec)->num_info; \
i++, rec = (void *)rec + (seg)->rec_size) i++, rec = (void *)rec + (seg)->rec_size)
/*
* The .BTF.ext ELF section layout defined as
* struct btf_ext_header
* func_info subsection
*
* The func_info subsection layout:
* record size for struct bpf_func_info in the func_info subsection
* struct btf_sec_func_info for section #1
* a list of bpf_func_info records for section #1
* where struct bpf_func_info mimics one in include/uapi/linux/bpf.h
* but may not be identical
* struct btf_sec_func_info for section #2
* a list of bpf_func_info records for section #2
* ......
*
* Note that the bpf_func_info record size in .BTF.ext may not
* be the same as the one defined in include/uapi/linux/bpf.h.
* The loader should ensure that record_size meets minimum
* requirement and pass the record as is to the kernel. The
* kernel will handle the func_info properly based on its contents.
*/
struct btf_ext_header {
__u16 magic;
__u8 version;
__u8 flags;
__u32 hdr_len;
/* All offsets are in bytes relative to the end of this header */
__u32 func_info_off;
__u32 func_info_len;
__u32 line_info_off;
__u32 line_info_len;
/* optional part of .BTF.ext header */
__u32 core_relo_off;
__u32 core_relo_len;
};
struct btf_ext { struct btf_ext {
union { union {
struct btf_ext_header *hdr; struct btf_ext_header *hdr;
@@ -377,7 +145,7 @@ struct btf_ext {
}; };
struct btf_ext_info func_info; struct btf_ext_info func_info;
struct btf_ext_info line_info; struct btf_ext_info line_info;
struct btf_ext_info core_relo_info; struct btf_ext_info field_reloc_info;
__u32 data_size; __u32 data_size;
}; };
@@ -402,74 +170,67 @@ struct bpf_line_info_min {
__u32 line_col; __u32 line_col;
}; };
/* bpf_field_info_kind encodes which aspect of captured field has to be
typedef int (*type_id_visit_fn)(__u32 *type_id, void *ctx); * adjusted by relocations. Currently supported values are:
typedef int (*str_off_visit_fn)(__u32 *str_off, void *ctx); * - BPF_FIELD_BYTE_OFFSET: field offset (in bytes);
int btf_type_visit_type_ids(struct btf_type *t, type_id_visit_fn visit, void *ctx); * - BPF_FIELD_EXISTS: field existence (1, if field exists; 0, otherwise);
int btf_type_visit_str_offs(struct btf_type *t, str_off_visit_fn visit, void *ctx);
int btf_ext_visit_type_ids(struct btf_ext *btf_ext, type_id_visit_fn visit, void *ctx);
int btf_ext_visit_str_offs(struct btf_ext *btf_ext, str_off_visit_fn visit, void *ctx);
__s32 btf__find_by_name_kind_own(const struct btf *btf, const char *type_name,
__u32 kind);
extern enum libbpf_strict_mode libbpf_mode;
/* handle direct returned errors */
static inline int libbpf_err(int ret)
{
if (ret < 0)
errno = -ret;
return ret;
}
/* handle errno-based (e.g., syscall or libc) errors according to libbpf's
* strict mode settings
*/ */
static inline int libbpf_err_errno(int ret) enum bpf_field_info_kind {
{ BPF_FIELD_BYTE_OFFSET = 0, /* field byte offset */
if (libbpf_mode & LIBBPF_STRICT_DIRECT_ERRS) BPF_FIELD_BYTE_SIZE = 1,
/* errno is already assumed to be set on error */ BPF_FIELD_EXISTS = 2, /* field existence in target kernel */
return ret < 0 ? -errno : ret; BPF_FIELD_SIGNED = 3,
BPF_FIELD_LSHIFT_U64 = 4,
BPF_FIELD_RSHIFT_U64 = 5,
};
/* legacy: on error return -1 directly and don't touch errno */ /* The minimum bpf_field_reloc checked by the loader
return ret; *
} * Field relocation captures the following data:
* - insn_off - instruction offset (in bytes) within a BPF program that needs
/* handle error for pointer-returning APIs, err is assumed to be < 0 always */ * its insn->imm field to be relocated with actual field info;
static inline void *libbpf_err_ptr(int err) * - type_id - BTF type ID of the "root" (containing) entity of a relocatable
{ * field;
/* set errno on error, this doesn't break anything */ * - access_str_off - offset into corresponding .BTF string section. String
errno = -err; * itself encodes an accessed field using a sequence of field and array
* indicies, separated by colon (:). It's conceptually very close to LLVM's
if (libbpf_mode & LIBBPF_STRICT_CLEAN_PTRS) * getelementptr ([0]) instruction's arguments for identifying offset to
return NULL; * a field.
*
/* legacy: encode err as ptr */ * Example to provide a better feel.
return ERR_PTR(err); *
} * struct sample {
* int a;
/* handle pointer-returning APIs' error handling */ * struct {
static inline void *libbpf_ptr(void *ret) * int b[10];
{ * };
/* set errno on error, this doesn't break anything */ * };
if (IS_ERR(ret)) *
errno = -PTR_ERR(ret); * struct sample *s = ...;
* int x = &s->a; // encoded as "0:0" (a is field #0)
if (libbpf_mode & LIBBPF_STRICT_CLEAN_PTRS) * int y = &s->b[5]; // encoded as "0:1:0:5" (anon struct is field #1,
return IS_ERR(ret) ? NULL : ret; * // b is field #0 inside anon struct, accessing elem #5)
* int z = &s[10]->b; // encoded as "10:1" (ptr is used as an array)
/* legacy: pass-through original pointer */ *
return ret; * type_id for all relocs in this example will capture BTF type id of
} * `struct sample`.
*
static inline bool str_is_empty(const char *s) * Such relocation is emitted when using __builtin_preserve_access_index()
{ * Clang built-in, passing expression that captures field address, e.g.:
return !s || !s[0]; *
} * bpf_probe_read(&dst, sizeof(dst),
* __builtin_preserve_access_index(&src->a.b.c));
static inline bool is_ldimm64_insn(struct bpf_insn *insn) *
{ * In this case Clang will emit field relocation recording necessary data to
return insn->code == (BPF_LD | BPF_IMM | BPF_DW); * be able to find offset of embedded `a.b.c` field within `src` struct.
} *
* [0] https://llvm.org/docs/LangRef.html#getelementptr-instruction
*/
struct bpf_field_reloc {
__u32 insn_off;
__u32 type_id;
__u32 access_str_off;
enum bpf_field_info_kind kind;
};
#endif /* __LIBBPF_LIBBPF_INTERNAL_H */ #endif /* __LIBBPF_LIBBPF_INTERNAL_H */

View File

@@ -1,68 +0,0 @@
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
/*
* Libbpf legacy APIs (either discouraged or deprecated, as mentioned in [0])
*
* [0] https://docs.google.com/document/d/1UyjTZuPFWiPFyKk1tV5an11_iaRuec6U-ZESZ54nNTY
*
* Copyright (C) 2021 Facebook
*/
#ifndef __LIBBPF_LEGACY_BPF_H
#define __LIBBPF_LEGACY_BPF_H
#include <linux/bpf.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "libbpf_common.h"
#ifdef __cplusplus
extern "C" {
#endif
enum libbpf_strict_mode {
/* Turn on all supported strict features of libbpf to simulate libbpf
* v1.0 behavior.
* This will be the default behavior in libbpf v1.0.
*/
LIBBPF_STRICT_ALL = 0xffffffff,
/*
* Disable any libbpf 1.0 behaviors. This is the default before libbpf
* v1.0. It won't be supported anymore in v1.0, please update your
* code so that it handles LIBBPF_STRICT_ALL mode before libbpf v1.0.
*/
LIBBPF_STRICT_NONE = 0x00,
/*
* Return NULL pointers on error, not ERR_PTR(err).
* Additionally, libbpf also always sets errno to corresponding Exx
* (positive) error code.
*/
LIBBPF_STRICT_CLEAN_PTRS = 0x01,
/*
* Return actual error codes from low-level APIs directly, not just -1.
* Additionally, libbpf also always sets errno to corresponding Exx
* (positive) error code.
*/
LIBBPF_STRICT_DIRECT_ERRS = 0x02,
/*
* Enforce strict BPF program section (SEC()) names.
* E.g., while prefiously SEC("xdp_whatever") or SEC("perf_event_blah") were
* allowed, with LIBBPF_STRICT_SEC_PREFIX this will become
* unrecognized by libbpf and would have to be just SEC("xdp") and
* SEC("xdp") and SEC("perf_event").
*/
LIBBPF_STRICT_SEC_NAME = 0x04,
__LIBBPF_STRICT_LAST,
};
LIBBPF_API int libbpf_set_strict_mode(enum libbpf_strict_mode mode);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* __LIBBPF_LEGACY_BPF_H */

View File

@@ -17,6 +17,9 @@
#include "libbpf.h" #include "libbpf.h"
#include "libbpf_internal.h" #include "libbpf_internal.h"
/* make sure libbpf doesn't use kernel-only integer typedefs */
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
static bool grep(const char *buffer, const char *pattern) static bool grep(const char *buffer, const char *pattern)
{ {
return !!strstr(buffer, pattern); return !!strstr(buffer, pattern);
@@ -75,12 +78,6 @@ probe_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns,
case BPF_PROG_TYPE_CGROUP_SOCK_ADDR: case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
xattr.expected_attach_type = BPF_CGROUP_INET4_CONNECT; xattr.expected_attach_type = BPF_CGROUP_INET4_CONNECT;
break; break;
case BPF_PROG_TYPE_CGROUP_SOCKOPT:
xattr.expected_attach_type = BPF_CGROUP_GETSOCKOPT;
break;
case BPF_PROG_TYPE_SK_LOOKUP:
xattr.expected_attach_type = BPF_SK_LOOKUP;
break;
case BPF_PROG_TYPE_KPROBE: case BPF_PROG_TYPE_KPROBE:
xattr.kern_version = get_kernel_version(); xattr.kern_version = get_kernel_version();
break; break;
@@ -107,6 +104,7 @@ probe_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns,
case BPF_PROG_TYPE_SK_REUSEPORT: case BPF_PROG_TYPE_SK_REUSEPORT:
case BPF_PROG_TYPE_FLOW_DISSECTOR: case BPF_PROG_TYPE_FLOW_DISSECTOR:
case BPF_PROG_TYPE_CGROUP_SYSCTL: case BPF_PROG_TYPE_CGROUP_SYSCTL:
case BPF_PROG_TYPE_CGROUP_SOCKOPT:
case BPF_PROG_TYPE_TRACING: case BPF_PROG_TYPE_TRACING:
case BPF_PROG_TYPE_STRUCT_OPS: case BPF_PROG_TYPE_STRUCT_OPS:
case BPF_PROG_TYPE_EXT: case BPF_PROG_TYPE_EXT:
@@ -172,7 +170,7 @@ int libbpf__load_raw_btf(const char *raw_types, size_t types_len,
return btf_fd; return btf_fd;
} }
static int load_local_storage_btf(void) static int load_sk_storage_btf(void)
{ {
const char strs[] = "\0bpf_spin_lock\0val\0cnt\0l"; const char strs[] = "\0bpf_spin_lock\0val\0cnt\0l";
/* struct bpf_spin_lock { /* struct bpf_spin_lock {
@@ -231,14 +229,12 @@ bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex)
key_size = 0; key_size = 0;
break; break;
case BPF_MAP_TYPE_SK_STORAGE: case BPF_MAP_TYPE_SK_STORAGE:
case BPF_MAP_TYPE_INODE_STORAGE:
case BPF_MAP_TYPE_TASK_STORAGE:
btf_key_type_id = 1; btf_key_type_id = 1;
btf_value_type_id = 3; btf_value_type_id = 3;
value_size = 8; value_size = 8;
max_entries = 0; max_entries = 0;
map_flags = BPF_F_NO_PREALLOC; map_flags = BPF_F_NO_PREALLOC;
btf_fd = load_local_storage_btf(); btf_fd = load_sk_storage_btf();
if (btf_fd < 0) if (btf_fd < 0)
return false; return false;
break; break;

47
src/libbpf_util.h Normal file
View File

@@ -0,0 +1,47 @@
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
/* Copyright (c) 2019 Facebook */
#ifndef __LIBBPF_LIBBPF_UTIL_H
#define __LIBBPF_LIBBPF_UTIL_H
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Use these barrier functions instead of smp_[rw]mb() when they are
* used in a libbpf header file. That way they can be built into the
* application that uses libbpf.
*/
#if defined(__i386__) || defined(__x86_64__)
# define libbpf_smp_rmb() asm volatile("" : : : "memory")
# define libbpf_smp_wmb() asm volatile("" : : : "memory")
# define libbpf_smp_mb() \
asm volatile("lock; addl $0,-4(%%rsp)" : : : "memory", "cc")
/* Hinders stores to be observed before older loads. */
# define libbpf_smp_rwmb() asm volatile("" : : : "memory")
#elif defined(__aarch64__)
# define libbpf_smp_rmb() asm volatile("dmb ishld" : : : "memory")
# define libbpf_smp_wmb() asm volatile("dmb ishst" : : : "memory")
# define libbpf_smp_mb() asm volatile("dmb ish" : : : "memory")
# define libbpf_smp_rwmb() libbpf_smp_mb()
#elif defined(__arm__)
/* These are only valid for armv7 and above */
# define libbpf_smp_rmb() asm volatile("dmb ish" : : : "memory")
# define libbpf_smp_wmb() asm volatile("dmb ishst" : : : "memory")
# define libbpf_smp_mb() asm volatile("dmb ish" : : : "memory")
# define libbpf_smp_rwmb() libbpf_smp_mb()
#else
/* Architecture missing native barrier functions. */
# define libbpf_smp_rmb() __sync_synchronize()
# define libbpf_smp_wmb() __sync_synchronize()
# define libbpf_smp_mb() __sync_synchronize()
# define libbpf_smp_rwmb() __sync_synchronize()
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

View File

@@ -1,9 +0,0 @@
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
/* Copyright (C) 2021 Facebook */
#ifndef __LIBBPF_VERSION_H
#define __LIBBPF_VERSION_H
#define LIBBPF_MAJOR_VERSION 0
#define LIBBPF_MINOR_VERSION 6
#endif /* __LIBBPF_VERSION_H */

File diff suppressed because it is too large Load Diff

View File

@@ -4,10 +4,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <memory.h> #include <memory.h>
#include <unistd.h> #include <unistd.h>
#include <arpa/inet.h>
#include <linux/bpf.h> #include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/pkt_cls.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <errno.h> #include <errno.h>
@@ -18,12 +15,13 @@
#include "libbpf_internal.h" #include "libbpf_internal.h"
#include "nlattr.h" #include "nlattr.h"
/* make sure libbpf doesn't use kernel-only integer typedefs */
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
#ifndef SOL_NETLINK #ifndef SOL_NETLINK
#define SOL_NETLINK 270 #define SOL_NETLINK 270
#endif #endif
typedef int (*libbpf_dump_nlmsg_t)(void *cookie, void *msg, struct nlattr **tb);
typedef int (*__dump_nlmsg_t)(struct nlmsghdr *nlmsg, libbpf_dump_nlmsg_t, typedef int (*__dump_nlmsg_t)(struct nlmsghdr *nlmsg, libbpf_dump_nlmsg_t,
void *cookie); void *cookie);
@@ -33,7 +31,7 @@ struct xdp_id_md {
struct xdp_link_info info; struct xdp_link_info info;
}; };
static int libbpf_netlink_open(__u32 *nl_pid) int libbpf_netlink_open(__u32 *nl_pid)
{ {
struct sockaddr_nl sa; struct sockaddr_nl sa;
socklen_t addrlen; socklen_t addrlen;
@@ -43,7 +41,7 @@ static int libbpf_netlink_open(__u32 *nl_pid)
memset(&sa, 0, sizeof(sa)); memset(&sa, 0, sizeof(sa));
sa.nl_family = AF_NETLINK; sa.nl_family = AF_NETLINK;
sock = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE); sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (sock < 0) if (sock < 0)
return -errno; return -errno;
@@ -76,20 +74,9 @@ cleanup:
return ret; return ret;
} }
static void libbpf_netlink_close(int sock) static int bpf_netlink_recv(int sock, __u32 nl_pid, int seq,
{ __dump_nlmsg_t _fn, libbpf_dump_nlmsg_t fn,
close(sock); void *cookie)
}
enum {
NL_CONT,
NL_NEXT,
NL_DONE,
};
static int libbpf_netlink_recv(int sock, __u32 nl_pid, int seq,
__dump_nlmsg_t _fn, libbpf_dump_nlmsg_t fn,
void *cookie)
{ {
bool multipart = true; bool multipart = true;
struct nlmsgerr *err; struct nlmsgerr *err;
@@ -98,7 +85,6 @@ static int libbpf_netlink_recv(int sock, __u32 nl_pid, int seq,
int len, ret; int len, ret;
while (multipart) { while (multipart) {
start:
multipart = false; multipart = false;
len = recv(sock, buf, sizeof(buf), 0); len = recv(sock, buf, sizeof(buf), 0);
if (len < 0) { if (len < 0) {
@@ -136,16 +122,8 @@ start:
} }
if (_fn) { if (_fn) {
ret = _fn(nh, fn, cookie); ret = _fn(nh, fn, cookie);
switch (ret) { if (ret)
case NL_CONT:
break;
case NL_NEXT:
goto start;
case NL_DONE:
return 0;
default:
return ret; return ret;
}
} }
} }
} }
@@ -154,92 +132,95 @@ done:
return ret; return ret;
} }
static int libbpf_netlink_send_recv(struct libbpf_nla_req *req, static int __bpf_set_link_xdp_fd_replace(int ifindex, int fd, int old_fd,
__dump_nlmsg_t parse_msg, __u32 flags)
libbpf_dump_nlmsg_t parse_attr,
void *cookie)
{ {
int sock, seq = 0, ret;
struct nlattr *nla, *nla_xdp;
struct {
struct nlmsghdr nh;
struct ifinfomsg ifinfo;
char attrbuf[64];
} req;
__u32 nl_pid = 0; __u32 nl_pid = 0;
int sock, ret;
sock = libbpf_netlink_open(&nl_pid); sock = libbpf_netlink_open(&nl_pid);
if (sock < 0) if (sock < 0)
return sock; return sock;
req->nh.nlmsg_pid = 0;
req->nh.nlmsg_seq = time(NULL);
if (send(sock, req, req->nh.nlmsg_len, 0) < 0) {
ret = -errno;
goto out;
}
ret = libbpf_netlink_recv(sock, nl_pid, req->nh.nlmsg_seq,
parse_msg, parse_attr, cookie);
out:
libbpf_netlink_close(sock);
return ret;
}
static int __bpf_set_link_xdp_fd_replace(int ifindex, int fd, int old_fd,
__u32 flags)
{
struct nlattr *nla;
int ret;
struct libbpf_nla_req req;
memset(&req, 0, sizeof(req)); memset(&req, 0, sizeof(req));
req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
req.nh.nlmsg_type = RTM_SETLINK; req.nh.nlmsg_type = RTM_SETLINK;
req.nh.nlmsg_pid = 0;
req.nh.nlmsg_seq = ++seq;
req.ifinfo.ifi_family = AF_UNSPEC; req.ifinfo.ifi_family = AF_UNSPEC;
req.ifinfo.ifi_index = ifindex; req.ifinfo.ifi_index = ifindex;
nla = nlattr_begin_nested(&req, IFLA_XDP); /* started nested attribute for XDP */
if (!nla) nla = (struct nlattr *)(((char *)&req)
return -EMSGSIZE; + NLMSG_ALIGN(req.nh.nlmsg_len));
ret = nlattr_add(&req, IFLA_XDP_FD, &fd, sizeof(fd)); nla->nla_type = NLA_F_NESTED | IFLA_XDP;
if (ret < 0) nla->nla_len = NLA_HDRLEN;
return ret;
/* add XDP fd */
nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
nla_xdp->nla_type = IFLA_XDP_FD;
nla_xdp->nla_len = NLA_HDRLEN + sizeof(int);
memcpy((char *)nla_xdp + NLA_HDRLEN, &fd, sizeof(fd));
nla->nla_len += nla_xdp->nla_len;
/* if user passed in any flags, add those too */
if (flags) { if (flags) {
ret = nlattr_add(&req, IFLA_XDP_FLAGS, &flags, sizeof(flags)); nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
if (ret < 0) nla_xdp->nla_type = IFLA_XDP_FLAGS;
return ret; nla_xdp->nla_len = NLA_HDRLEN + sizeof(flags);
memcpy((char *)nla_xdp + NLA_HDRLEN, &flags, sizeof(flags));
nla->nla_len += nla_xdp->nla_len;
} }
if (flags & XDP_FLAGS_REPLACE) {
ret = nlattr_add(&req, IFLA_XDP_EXPECTED_FD, &old_fd,
sizeof(old_fd));
if (ret < 0)
return ret;
}
nlattr_end_nested(&req, nla);
return libbpf_netlink_send_recv(&req, NULL, NULL, NULL); if (flags & XDP_FLAGS_REPLACE) {
nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
nla_xdp->nla_type = IFLA_XDP_EXPECTED_FD;
nla_xdp->nla_len = NLA_HDRLEN + sizeof(old_fd);
memcpy((char *)nla_xdp + NLA_HDRLEN, &old_fd, sizeof(old_fd));
nla->nla_len += nla_xdp->nla_len;
}
req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);
if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
ret = -errno;
goto cleanup;
}
ret = bpf_netlink_recv(sock, nl_pid, seq, NULL, NULL, NULL);
cleanup:
close(sock);
return ret;
} }
int bpf_set_link_xdp_fd_opts(int ifindex, int fd, __u32 flags, int bpf_set_link_xdp_fd_opts(int ifindex, int fd, __u32 flags,
const struct bpf_xdp_set_link_opts *opts) const struct bpf_xdp_set_link_opts *opts)
{ {
int old_fd = -1, ret; int old_fd = -1;
if (!OPTS_VALID(opts, bpf_xdp_set_link_opts)) if (!OPTS_VALID(opts, bpf_xdp_set_link_opts))
return libbpf_err(-EINVAL); return -EINVAL;
if (OPTS_HAS(opts, old_fd)) { if (OPTS_HAS(opts, old_fd)) {
old_fd = OPTS_GET(opts, old_fd, -1); old_fd = OPTS_GET(opts, old_fd, -1);
flags |= XDP_FLAGS_REPLACE; flags |= XDP_FLAGS_REPLACE;
} }
ret = __bpf_set_link_xdp_fd_replace(ifindex, fd, old_fd, flags); return __bpf_set_link_xdp_fd_replace(ifindex, fd,
return libbpf_err(ret); old_fd,
flags);
} }
int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags) int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
{ {
int ret; return __bpf_set_link_xdp_fd_replace(ifindex, fd, 0, flags);
ret = __bpf_set_link_xdp_fd_replace(ifindex, fd, 0, flags);
return libbpf_err(ret);
} }
static int __dump_link_nlmsg(struct nlmsghdr *nlh, static int __dump_link_nlmsg(struct nlmsghdr *nlh,
@@ -251,7 +232,6 @@ static int __dump_link_nlmsg(struct nlmsghdr *nlh,
len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi)); len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
attr = (struct nlattr *) ((void *) ifi + NLMSG_ALIGN(sizeof(*ifi))); attr = (struct nlattr *) ((void *) ifi + NLMSG_ALIGN(sizeof(*ifi)));
if (libbpf_nla_parse(tb, IFLA_MAX, attr, len, NULL) != 0) if (libbpf_nla_parse(tb, IFLA_MAX, attr, len, NULL) != 0)
return -LIBBPF_ERRNO__NLPARSE; return -LIBBPF_ERRNO__NLPARSE;
@@ -307,29 +287,27 @@ int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info,
size_t info_size, __u32 flags) size_t info_size, __u32 flags)
{ {
struct xdp_id_md xdp_id = {}; struct xdp_id_md xdp_id = {};
int sock, ret;
__u32 nl_pid = 0;
__u32 mask; __u32 mask;
int ret;
struct libbpf_nla_req req = {
.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
.nh.nlmsg_type = RTM_GETLINK,
.nh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
.ifinfo.ifi_family = AF_PACKET,
};
if (flags & ~XDP_FLAGS_MASK || !info_size) if (flags & ~XDP_FLAGS_MASK || !info_size)
return libbpf_err(-EINVAL); return -EINVAL;
/* Check whether the single {HW,DRV,SKB} mode is set */ /* Check whether the single {HW,DRV,SKB} mode is set */
flags &= (XDP_FLAGS_SKB_MODE | XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE); flags &= (XDP_FLAGS_SKB_MODE | XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE);
mask = flags - 1; mask = flags - 1;
if (flags && flags & mask) if (flags && flags & mask)
return libbpf_err(-EINVAL); return -EINVAL;
sock = libbpf_netlink_open(&nl_pid);
if (sock < 0)
return sock;
xdp_id.ifindex = ifindex; xdp_id.ifindex = ifindex;
xdp_id.flags = flags; xdp_id.flags = flags;
ret = libbpf_netlink_send_recv(&req, __dump_link_nlmsg, ret = libbpf_nl_get_link(sock, nl_pid, get_xdp_info, &xdp_id);
get_xdp_info, &xdp_id);
if (!ret) { if (!ret) {
size_t sz = min(info_size, sizeof(xdp_id.info)); size_t sz = min(info_size, sizeof(xdp_id.info));
@@ -337,7 +315,8 @@ int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info,
memset((void *) info + sz, 0, info_size - sz); memset((void *) info + sz, 0, info_size - sz);
} }
return libbpf_err(ret); close(sock);
return ret;
} }
static __u32 get_xdp_id(struct xdp_link_info *info, __u32 flags) static __u32 get_xdp_id(struct xdp_link_info *info, __u32 flags)
@@ -365,394 +344,145 @@ int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags)
if (!ret) if (!ret)
*prog_id = get_xdp_id(&info, flags); *prog_id = get_xdp_id(&info, flags);
return libbpf_err(ret); return ret;
} }
typedef int (*qdisc_config_t)(struct libbpf_nla_req *req); int libbpf_nl_get_link(int sock, unsigned int nl_pid,
libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie)
static int clsact_config(struct libbpf_nla_req *req)
{ {
req->tc.tcm_parent = TC_H_CLSACT; struct {
req->tc.tcm_handle = TC_H_MAKE(TC_H_CLSACT, 0); struct nlmsghdr nlh;
struct ifinfomsg ifm;
} req = {
.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
.nlh.nlmsg_type = RTM_GETLINK,
.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
.ifm.ifi_family = AF_PACKET,
};
int seq = time(NULL);
return nlattr_add(req, TCA_KIND, "clsact", sizeof("clsact")); req.nlh.nlmsg_seq = seq;
} if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0)
static int attach_point_to_config(struct bpf_tc_hook *hook,
qdisc_config_t *config)
{
switch (OPTS_GET(hook, attach_point, 0)) {
case BPF_TC_INGRESS:
case BPF_TC_EGRESS:
case BPF_TC_INGRESS | BPF_TC_EGRESS:
if (OPTS_GET(hook, parent, 0))
return -EINVAL;
*config = &clsact_config;
return 0;
case BPF_TC_CUSTOM:
return -EOPNOTSUPP;
default:
return -EINVAL;
}
}
static int tc_get_tcm_parent(enum bpf_tc_attach_point attach_point,
__u32 *parent)
{
switch (attach_point) {
case BPF_TC_INGRESS:
case BPF_TC_EGRESS:
if (*parent)
return -EINVAL;
*parent = TC_H_MAKE(TC_H_CLSACT,
attach_point == BPF_TC_INGRESS ?
TC_H_MIN_INGRESS : TC_H_MIN_EGRESS);
break;
case BPF_TC_CUSTOM:
if (!*parent)
return -EINVAL;
break;
default:
return -EINVAL;
}
return 0;
}
static int tc_qdisc_modify(struct bpf_tc_hook *hook, int cmd, int flags)
{
qdisc_config_t config;
int ret;
struct libbpf_nla_req req;
ret = attach_point_to_config(hook, &config);
if (ret < 0)
return ret;
memset(&req, 0, sizeof(req));
req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
req.nh.nlmsg_type = cmd;
req.tc.tcm_family = AF_UNSPEC;
req.tc.tcm_ifindex = OPTS_GET(hook, ifindex, 0);
ret = config(&req);
if (ret < 0)
return ret;
return libbpf_netlink_send_recv(&req, NULL, NULL, NULL);
}
static int tc_qdisc_create_excl(struct bpf_tc_hook *hook)
{
return tc_qdisc_modify(hook, RTM_NEWQDISC, NLM_F_CREATE | NLM_F_EXCL);
}
static int tc_qdisc_delete(struct bpf_tc_hook *hook)
{
return tc_qdisc_modify(hook, RTM_DELQDISC, 0);
}
int bpf_tc_hook_create(struct bpf_tc_hook *hook)
{
int ret;
if (!hook || !OPTS_VALID(hook, bpf_tc_hook) ||
OPTS_GET(hook, ifindex, 0) <= 0)
return libbpf_err(-EINVAL);
ret = tc_qdisc_create_excl(hook);
return libbpf_err(ret);
}
static int __bpf_tc_detach(const struct bpf_tc_hook *hook,
const struct bpf_tc_opts *opts,
const bool flush);
int bpf_tc_hook_destroy(struct bpf_tc_hook *hook)
{
if (!hook || !OPTS_VALID(hook, bpf_tc_hook) ||
OPTS_GET(hook, ifindex, 0) <= 0)
return libbpf_err(-EINVAL);
switch (OPTS_GET(hook, attach_point, 0)) {
case BPF_TC_INGRESS:
case BPF_TC_EGRESS:
return libbpf_err(__bpf_tc_detach(hook, NULL, true));
case BPF_TC_INGRESS | BPF_TC_EGRESS:
return libbpf_err(tc_qdisc_delete(hook));
case BPF_TC_CUSTOM:
return libbpf_err(-EOPNOTSUPP);
default:
return libbpf_err(-EINVAL);
}
}
struct bpf_cb_ctx {
struct bpf_tc_opts *opts;
bool processed;
};
static int __get_tc_info(void *cookie, struct tcmsg *tc, struct nlattr **tb,
bool unicast)
{
struct nlattr *tbb[TCA_BPF_MAX + 1];
struct bpf_cb_ctx *info = cookie;
if (!info || !info->opts)
return -EINVAL;
if (unicast && info->processed)
return -EINVAL;
if (!tb[TCA_OPTIONS])
return NL_CONT;
libbpf_nla_parse_nested(tbb, TCA_BPF_MAX, tb[TCA_OPTIONS], NULL);
if (!tbb[TCA_BPF_ID])
return -EINVAL;
OPTS_SET(info->opts, prog_id, libbpf_nla_getattr_u32(tbb[TCA_BPF_ID]));
OPTS_SET(info->opts, handle, tc->tcm_handle);
OPTS_SET(info->opts, priority, TC_H_MAJ(tc->tcm_info) >> 16);
info->processed = true;
return unicast ? NL_NEXT : NL_DONE;
}
static int get_tc_info(struct nlmsghdr *nh, libbpf_dump_nlmsg_t fn,
void *cookie)
{
struct tcmsg *tc = NLMSG_DATA(nh);
struct nlattr *tb[TCA_MAX + 1];
libbpf_nla_parse(tb, TCA_MAX,
(struct nlattr *)((void *)tc + NLMSG_ALIGN(sizeof(*tc))),
NLMSG_PAYLOAD(nh, sizeof(*tc)), NULL);
if (!tb[TCA_KIND])
return NL_CONT;
return __get_tc_info(cookie, tc, tb, nh->nlmsg_flags & NLM_F_ECHO);
}
static int tc_add_fd_and_name(struct libbpf_nla_req *req, int fd)
{
struct bpf_prog_info info = {};
__u32 info_len = sizeof(info);
char name[256];
int len, ret;
ret = bpf_obj_get_info_by_fd(fd, &info, &info_len);
if (ret < 0)
return ret;
ret = nlattr_add(req, TCA_BPF_FD, &fd, sizeof(fd));
if (ret < 0)
return ret;
len = snprintf(name, sizeof(name), "%s:[%u]", info.name, info.id);
if (len < 0)
return -errno; return -errno;
if (len >= sizeof(name))
return -ENAMETOOLONG; return bpf_netlink_recv(sock, nl_pid, seq, __dump_link_nlmsg,
return nlattr_add(req, TCA_BPF_NAME, name, len + 1); dump_link_nlmsg, cookie);
} }
int bpf_tc_attach(const struct bpf_tc_hook *hook, struct bpf_tc_opts *opts) static int __dump_class_nlmsg(struct nlmsghdr *nlh,
libbpf_dump_nlmsg_t dump_class_nlmsg,
void *cookie)
{ {
__u32 protocol, bpf_flags, handle, priority, parent, prog_id, flags; struct nlattr *tb[TCA_MAX + 1], *attr;
int ret, ifindex, attach_point, prog_fd; struct tcmsg *t = NLMSG_DATA(nlh);
struct bpf_cb_ctx info = {}; int len;
struct libbpf_nla_req req;
struct nlattr *nla;
if (!hook || !opts || len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t));
!OPTS_VALID(hook, bpf_tc_hook) || attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t)));
!OPTS_VALID(opts, bpf_tc_opts)) if (libbpf_nla_parse(tb, TCA_MAX, attr, len, NULL) != 0)
return libbpf_err(-EINVAL); return -LIBBPF_ERRNO__NLPARSE;
ifindex = OPTS_GET(hook, ifindex, 0); return dump_class_nlmsg(cookie, t, tb);
parent = OPTS_GET(hook, parent, 0);
attach_point = OPTS_GET(hook, attach_point, 0);
handle = OPTS_GET(opts, handle, 0);
priority = OPTS_GET(opts, priority, 0);
prog_fd = OPTS_GET(opts, prog_fd, 0);
prog_id = OPTS_GET(opts, prog_id, 0);
flags = OPTS_GET(opts, flags, 0);
if (ifindex <= 0 || !prog_fd || prog_id)
return libbpf_err(-EINVAL);
if (priority > UINT16_MAX)
return libbpf_err(-EINVAL);
if (flags & ~BPF_TC_F_REPLACE)
return libbpf_err(-EINVAL);
flags = (flags & BPF_TC_F_REPLACE) ? NLM_F_REPLACE : NLM_F_EXCL;
protocol = ETH_P_ALL;
memset(&req, 0, sizeof(req));
req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE |
NLM_F_ECHO | flags;
req.nh.nlmsg_type = RTM_NEWTFILTER;
req.tc.tcm_family = AF_UNSPEC;
req.tc.tcm_ifindex = ifindex;
req.tc.tcm_handle = handle;
req.tc.tcm_info = TC_H_MAKE(priority << 16, htons(protocol));
ret = tc_get_tcm_parent(attach_point, &parent);
if (ret < 0)
return libbpf_err(ret);
req.tc.tcm_parent = parent;
ret = nlattr_add(&req, TCA_KIND, "bpf", sizeof("bpf"));
if (ret < 0)
return libbpf_err(ret);
nla = nlattr_begin_nested(&req, TCA_OPTIONS);
if (!nla)
return libbpf_err(-EMSGSIZE);
ret = tc_add_fd_and_name(&req, prog_fd);
if (ret < 0)
return libbpf_err(ret);
bpf_flags = TCA_BPF_FLAG_ACT_DIRECT;
ret = nlattr_add(&req, TCA_BPF_FLAGS, &bpf_flags, sizeof(bpf_flags));
if (ret < 0)
return libbpf_err(ret);
nlattr_end_nested(&req, nla);
info.opts = opts;
ret = libbpf_netlink_send_recv(&req, get_tc_info, NULL, &info);
if (ret < 0)
return libbpf_err(ret);
if (!info.processed)
return libbpf_err(-ENOENT);
return ret;
} }
static int __bpf_tc_detach(const struct bpf_tc_hook *hook, int libbpf_nl_get_class(int sock, unsigned int nl_pid, int ifindex,
const struct bpf_tc_opts *opts, libbpf_dump_nlmsg_t dump_class_nlmsg, void *cookie)
const bool flush)
{ {
__u32 protocol = 0, handle, priority, parent, prog_id, flags; struct {
int ret, ifindex, attach_point, prog_fd; struct nlmsghdr nlh;
struct libbpf_nla_req req; struct tcmsg t;
} req = {
.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)),
.nlh.nlmsg_type = RTM_GETTCLASS,
.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
.t.tcm_family = AF_UNSPEC,
.t.tcm_ifindex = ifindex,
};
int seq = time(NULL);
if (!hook || req.nlh.nlmsg_seq = seq;
!OPTS_VALID(hook, bpf_tc_hook) || if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0)
!OPTS_VALID(opts, bpf_tc_opts)) return -errno;
return -EINVAL;
ifindex = OPTS_GET(hook, ifindex, 0); return bpf_netlink_recv(sock, nl_pid, seq, __dump_class_nlmsg,
parent = OPTS_GET(hook, parent, 0); dump_class_nlmsg, cookie);
attach_point = OPTS_GET(hook, attach_point, 0);
handle = OPTS_GET(opts, handle, 0);
priority = OPTS_GET(opts, priority, 0);
prog_fd = OPTS_GET(opts, prog_fd, 0);
prog_id = OPTS_GET(opts, prog_id, 0);
flags = OPTS_GET(opts, flags, 0);
if (ifindex <= 0 || flags || prog_fd || prog_id)
return -EINVAL;
if (priority > UINT16_MAX)
return -EINVAL;
if (!flush) {
if (!handle || !priority)
return -EINVAL;
protocol = ETH_P_ALL;
} else {
if (handle || priority)
return -EINVAL;
}
memset(&req, 0, sizeof(req));
req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
req.nh.nlmsg_type = RTM_DELTFILTER;
req.tc.tcm_family = AF_UNSPEC;
req.tc.tcm_ifindex = ifindex;
if (!flush) {
req.tc.tcm_handle = handle;
req.tc.tcm_info = TC_H_MAKE(priority << 16, htons(protocol));
}
ret = tc_get_tcm_parent(attach_point, &parent);
if (ret < 0)
return ret;
req.tc.tcm_parent = parent;
if (!flush) {
ret = nlattr_add(&req, TCA_KIND, "bpf", sizeof("bpf"));
if (ret < 0)
return ret;
}
return libbpf_netlink_send_recv(&req, NULL, NULL, NULL);
} }
int bpf_tc_detach(const struct bpf_tc_hook *hook, static int __dump_qdisc_nlmsg(struct nlmsghdr *nlh,
const struct bpf_tc_opts *opts) libbpf_dump_nlmsg_t dump_qdisc_nlmsg,
void *cookie)
{ {
int ret; struct nlattr *tb[TCA_MAX + 1], *attr;
struct tcmsg *t = NLMSG_DATA(nlh);
int len;
if (!opts) len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t));
return libbpf_err(-EINVAL); attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t)));
if (libbpf_nla_parse(tb, TCA_MAX, attr, len, NULL) != 0)
return -LIBBPF_ERRNO__NLPARSE;
ret = __bpf_tc_detach(hook, opts, false); return dump_qdisc_nlmsg(cookie, t, tb);
return libbpf_err(ret);
} }
int bpf_tc_query(const struct bpf_tc_hook *hook, struct bpf_tc_opts *opts) int libbpf_nl_get_qdisc(int sock, unsigned int nl_pid, int ifindex,
libbpf_dump_nlmsg_t dump_qdisc_nlmsg, void *cookie)
{ {
__u32 protocol, handle, priority, parent, prog_id, flags; struct {
int ret, ifindex, attach_point, prog_fd; struct nlmsghdr nlh;
struct bpf_cb_ctx info = {}; struct tcmsg t;
struct libbpf_nla_req req; } req = {
.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)),
.nlh.nlmsg_type = RTM_GETQDISC,
.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
.t.tcm_family = AF_UNSPEC,
.t.tcm_ifindex = ifindex,
};
int seq = time(NULL);
if (!hook || !opts || req.nlh.nlmsg_seq = seq;
!OPTS_VALID(hook, bpf_tc_hook) || if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0)
!OPTS_VALID(opts, bpf_tc_opts)) return -errno;
return libbpf_err(-EINVAL);
ifindex = OPTS_GET(hook, ifindex, 0); return bpf_netlink_recv(sock, nl_pid, seq, __dump_qdisc_nlmsg,
parent = OPTS_GET(hook, parent, 0); dump_qdisc_nlmsg, cookie);
attach_point = OPTS_GET(hook, attach_point, 0); }
handle = OPTS_GET(opts, handle, 0); static int __dump_filter_nlmsg(struct nlmsghdr *nlh,
priority = OPTS_GET(opts, priority, 0); libbpf_dump_nlmsg_t dump_filter_nlmsg,
prog_fd = OPTS_GET(opts, prog_fd, 0); void *cookie)
prog_id = OPTS_GET(opts, prog_id, 0); {
flags = OPTS_GET(opts, flags, 0); struct nlattr *tb[TCA_MAX + 1], *attr;
struct tcmsg *t = NLMSG_DATA(nlh);
if (ifindex <= 0 || flags || prog_fd || prog_id || int len;
!handle || !priority)
return libbpf_err(-EINVAL); len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t));
if (priority > UINT16_MAX) attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t)));
return libbpf_err(-EINVAL); if (libbpf_nla_parse(tb, TCA_MAX, attr, len, NULL) != 0)
return -LIBBPF_ERRNO__NLPARSE;
protocol = ETH_P_ALL;
return dump_filter_nlmsg(cookie, t, tb);
memset(&req, 0, sizeof(req)); }
req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
req.nh.nlmsg_flags = NLM_F_REQUEST; int libbpf_nl_get_filter(int sock, unsigned int nl_pid, int ifindex, int handle,
req.nh.nlmsg_type = RTM_GETTFILTER; libbpf_dump_nlmsg_t dump_filter_nlmsg, void *cookie)
req.tc.tcm_family = AF_UNSPEC; {
req.tc.tcm_ifindex = ifindex; struct {
req.tc.tcm_handle = handle; struct nlmsghdr nlh;
req.tc.tcm_info = TC_H_MAKE(priority << 16, htons(protocol)); struct tcmsg t;
} req = {
ret = tc_get_tcm_parent(attach_point, &parent); .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)),
if (ret < 0) .nlh.nlmsg_type = RTM_GETTFILTER,
return libbpf_err(ret); .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
req.tc.tcm_parent = parent; .t.tcm_family = AF_UNSPEC,
.t.tcm_ifindex = ifindex,
ret = nlattr_add(&req, TCA_KIND, "bpf", sizeof("bpf")); .t.tcm_parent = handle,
if (ret < 0) };
return libbpf_err(ret); int seq = time(NULL);
info.opts = opts; req.nlh.nlmsg_seq = seq;
if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0)
ret = libbpf_netlink_send_recv(&req, get_tc_info, NULL, &info); return -errno;
if (ret < 0)
return libbpf_err(ret); return bpf_netlink_recv(sock, nl_pid, seq, __dump_filter_nlmsg,
if (!info.processed) dump_filter_nlmsg, cookie);
return libbpf_err(-ENOENT);
return ret;
} }

View File

@@ -7,11 +7,14 @@
*/ */
#include <errno.h> #include <errno.h>
#include <string.h>
#include <stdio.h>
#include <linux/rtnetlink.h>
#include "nlattr.h" #include "nlattr.h"
#include "libbpf_internal.h" #include "libbpf_internal.h"
#include <linux/rtnetlink.h>
#include <string.h>
#include <stdio.h>
/* make sure libbpf doesn't use kernel-only integer typedefs */
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
static uint16_t nla_attr_minlen[LIBBPF_NLA_TYPE_MAX+1] = { static uint16_t nla_attr_minlen[LIBBPF_NLA_TYPE_MAX+1] = {
[LIBBPF_NLA_U8] = sizeof(uint8_t), [LIBBPF_NLA_U8] = sizeof(uint8_t),
@@ -27,7 +30,7 @@ static struct nlattr *nla_next(const struct nlattr *nla, int *remaining)
int totlen = NLA_ALIGN(nla->nla_len); int totlen = NLA_ALIGN(nla->nla_len);
*remaining -= totlen; *remaining -= totlen;
return (struct nlattr *)((void *)nla + totlen); return (struct nlattr *) ((char *) nla + totlen);
} }
static int nla_ok(const struct nlattr *nla, int remaining) static int nla_ok(const struct nlattr *nla, int remaining)

View File

@@ -10,11 +10,7 @@
#define __LIBBPF_NLATTR_H #define __LIBBPF_NLATTR_H
#include <stdint.h> #include <stdint.h>
#include <string.h>
#include <errno.h>
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/rtnetlink.h>
/* avoid multiple definition of netlink features */ /* avoid multiple definition of netlink features */
#define __LINUX_NETLINK_H #define __LINUX_NETLINK_H
@@ -53,15 +49,6 @@ struct libbpf_nla_policy {
uint16_t maxlen; uint16_t maxlen;
}; };
struct libbpf_nla_req {
struct nlmsghdr nh;
union {
struct ifinfomsg ifinfo;
struct tcmsg tc;
};
char buf[128];
};
/** /**
* @ingroup attr * @ingroup attr
* Iterate over a stream of attributes * Iterate over a stream of attributes
@@ -81,7 +68,7 @@ struct libbpf_nla_req {
*/ */
static inline void *libbpf_nla_data(const struct nlattr *nla) static inline void *libbpf_nla_data(const struct nlattr *nla)
{ {
return (void *)nla + NLA_HDRLEN; return (char *) nla + NLA_HDRLEN;
} }
static inline uint8_t libbpf_nla_getattr_u8(const struct nlattr *nla) static inline uint8_t libbpf_nla_getattr_u8(const struct nlattr *nla)
@@ -116,49 +103,4 @@ int libbpf_nla_parse_nested(struct nlattr *tb[], int maxtype,
int libbpf_nla_dump_errormsg(struct nlmsghdr *nlh); int libbpf_nla_dump_errormsg(struct nlmsghdr *nlh);
static inline struct nlattr *nla_data(struct nlattr *nla)
{
return (struct nlattr *)((void *)nla + NLA_HDRLEN);
}
static inline struct nlattr *req_tail(struct libbpf_nla_req *req)
{
return (struct nlattr *)((void *)req + NLMSG_ALIGN(req->nh.nlmsg_len));
}
static inline int nlattr_add(struct libbpf_nla_req *req, int type,
const void *data, int len)
{
struct nlattr *nla;
if (NLMSG_ALIGN(req->nh.nlmsg_len) + NLA_ALIGN(NLA_HDRLEN + len) > sizeof(*req))
return -EMSGSIZE;
if (!!data != !!len)
return -EINVAL;
nla = req_tail(req);
nla->nla_type = type;
nla->nla_len = NLA_HDRLEN + len;
if (data)
memcpy(nla_data(nla), data, len);
req->nh.nlmsg_len = NLMSG_ALIGN(req->nh.nlmsg_len) + NLA_ALIGN(nla->nla_len);
return 0;
}
static inline struct nlattr *nlattr_begin_nested(struct libbpf_nla_req *req, int type)
{
struct nlattr *tail;
tail = req_tail(req);
if (nlattr_add(req, type | NLA_F_NESTED, NULL, 0))
return NULL;
return tail;
}
static inline void nlattr_end_nested(struct libbpf_nla_req *req,
struct nlattr *tail)
{
tail->nla_len = (void *)req_tail(req) - (void *)tail;
}
#endif /* __LIBBPF_NLATTR_H */ #endif /* __LIBBPF_NLATTR_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,100 +0,0 @@
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
/* Copyright (c) 2019 Facebook */
#ifndef __RELO_CORE_H
#define __RELO_CORE_H
/* bpf_core_relo_kind encodes which aspect of captured field/type/enum value
* has to be adjusted by relocations.
*/
enum bpf_core_relo_kind {
BPF_FIELD_BYTE_OFFSET = 0, /* field byte offset */
BPF_FIELD_BYTE_SIZE = 1, /* field size in bytes */
BPF_FIELD_EXISTS = 2, /* field existence in target kernel */
BPF_FIELD_SIGNED = 3, /* field signedness (0 - unsigned, 1 - signed) */
BPF_FIELD_LSHIFT_U64 = 4, /* bitfield-specific left bitshift */
BPF_FIELD_RSHIFT_U64 = 5, /* bitfield-specific right bitshift */
BPF_TYPE_ID_LOCAL = 6, /* type ID in local BPF object */
BPF_TYPE_ID_TARGET = 7, /* type ID in target kernel */
BPF_TYPE_EXISTS = 8, /* type existence in target kernel */
BPF_TYPE_SIZE = 9, /* type size in bytes */
BPF_ENUMVAL_EXISTS = 10, /* enum value existence in target kernel */
BPF_ENUMVAL_VALUE = 11, /* enum value integer value */
};
/* The minimum bpf_core_relo checked by the loader
*
* CO-RE relocation captures the following data:
* - insn_off - instruction offset (in bytes) within a BPF program that needs
* its insn->imm field to be relocated with actual field info;
* - type_id - BTF type ID of the "root" (containing) entity of a relocatable
* type or field;
* - access_str_off - offset into corresponding .BTF string section. String
* interpretation depends on specific relocation kind:
* - for field-based relocations, string encodes an accessed field using
* a sequence of field and array indices, separated by colon (:). It's
* conceptually very close to LLVM's getelementptr ([0]) instruction's
* arguments for identifying offset to a field.
* - for type-based relocations, strings is expected to be just "0";
* - for enum value-based relocations, string contains an index of enum
* value within its enum type;
*
* Example to provide a better feel.
*
* struct sample {
* int a;
* struct {
* int b[10];
* };
* };
*
* struct sample *s = ...;
* int x = &s->a; // encoded as "0:0" (a is field #0)
* int y = &s->b[5]; // encoded as "0:1:0:5" (anon struct is field #1,
* // b is field #0 inside anon struct, accessing elem #5)
* int z = &s[10]->b; // encoded as "10:1" (ptr is used as an array)
*
* type_id for all relocs in this example will capture BTF type id of
* `struct sample`.
*
* Such relocation is emitted when using __builtin_preserve_access_index()
* Clang built-in, passing expression that captures field address, e.g.:
*
* bpf_probe_read(&dst, sizeof(dst),
* __builtin_preserve_access_index(&src->a.b.c));
*
* In this case Clang will emit field relocation recording necessary data to
* be able to find offset of embedded `a.b.c` field within `src` struct.
*
* [0] https://llvm.org/docs/LangRef.html#getelementptr-instruction
*/
struct bpf_core_relo {
__u32 insn_off;
__u32 type_id;
__u32 access_str_off;
enum bpf_core_relo_kind kind;
};
struct bpf_core_cand {
const struct btf *btf;
const struct btf_type *t;
const char *name;
__u32 id;
};
/* dynamically sized list of type IDs and its associated struct btf */
struct bpf_core_cand_list {
struct bpf_core_cand *cands;
int len;
};
int bpf_core_apply_relo_insn(const char *prog_name,
struct bpf_insn *insn, int insn_idx,
const struct bpf_core_relo *relo, int relo_idx,
const struct btf *local_btf,
struct bpf_core_cand_list *cands);
int bpf_core_types_are_compat(const struct btf *local_btf, __u32 local_id,
const struct btf *targ_btf, __u32 targ_id);
size_t bpf_core_essential_name_len(const char *name);
#endif

View File

@@ -16,11 +16,15 @@
#include <asm/barrier.h> #include <asm/barrier.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/epoll.h> #include <sys/epoll.h>
#include <tools/libc_compat.h>
#include "libbpf.h" #include "libbpf.h"
#include "libbpf_internal.h" #include "libbpf_internal.h"
#include "bpf.h" #include "bpf.h"
/* make sure libbpf doesn't use kernel-only integer typedefs */
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
struct ring { struct ring {
ring_buffer_sample_fn sample_cb; ring_buffer_sample_fn sample_cb;
void *ctx; void *ctx;
@@ -69,23 +73,23 @@ int ring_buffer__add(struct ring_buffer *rb, int map_fd,
err = -errno; err = -errno;
pr_warn("ringbuf: failed to get map info for fd=%d: %d\n", pr_warn("ringbuf: failed to get map info for fd=%d: %d\n",
map_fd, err); map_fd, err);
return libbpf_err(err); return err;
} }
if (info.type != BPF_MAP_TYPE_RINGBUF) { if (info.type != BPF_MAP_TYPE_RINGBUF) {
pr_warn("ringbuf: map fd=%d is not BPF_MAP_TYPE_RINGBUF\n", pr_warn("ringbuf: map fd=%d is not BPF_MAP_TYPE_RINGBUF\n",
map_fd); map_fd);
return libbpf_err(-EINVAL); return -EINVAL;
} }
tmp = libbpf_reallocarray(rb->rings, rb->ring_cnt + 1, sizeof(*rb->rings)); tmp = reallocarray(rb->rings, rb->ring_cnt + 1, sizeof(*rb->rings));
if (!tmp) if (!tmp)
return libbpf_err(-ENOMEM); return -ENOMEM;
rb->rings = tmp; rb->rings = tmp;
tmp = libbpf_reallocarray(rb->events, rb->ring_cnt + 1, sizeof(*rb->events)); tmp = reallocarray(rb->events, rb->ring_cnt + 1, sizeof(*rb->events));
if (!tmp) if (!tmp)
return libbpf_err(-ENOMEM); return -ENOMEM;
rb->events = tmp; rb->events = tmp;
r = &rb->rings[rb->ring_cnt]; r = &rb->rings[rb->ring_cnt];
@@ -103,7 +107,7 @@ int ring_buffer__add(struct ring_buffer *rb, int map_fd,
err = -errno; err = -errno;
pr_warn("ringbuf: failed to mmap consumer page for map fd=%d: %d\n", pr_warn("ringbuf: failed to mmap consumer page for map fd=%d: %d\n",
map_fd, err); map_fd, err);
return libbpf_err(err); return err;
} }
r->consumer_pos = tmp; r->consumer_pos = tmp;
@@ -118,7 +122,7 @@ int ring_buffer__add(struct ring_buffer *rb, int map_fd,
ringbuf_unmap_ring(rb, r); ringbuf_unmap_ring(rb, r);
pr_warn("ringbuf: failed to mmap data pages for map fd=%d: %d\n", pr_warn("ringbuf: failed to mmap data pages for map fd=%d: %d\n",
map_fd, err); map_fd, err);
return libbpf_err(err); return err;
} }
r->producer_pos = tmp; r->producer_pos = tmp;
r->data = tmp + rb->page_size; r->data = tmp + rb->page_size;
@@ -133,7 +137,7 @@ int ring_buffer__add(struct ring_buffer *rb, int map_fd,
ringbuf_unmap_ring(rb, r); ringbuf_unmap_ring(rb, r);
pr_warn("ringbuf: failed to epoll add map fd=%d: %d\n", pr_warn("ringbuf: failed to epoll add map fd=%d: %d\n",
map_fd, err); map_fd, err);
return libbpf_err(err); return err;
} }
rb->ring_cnt++; rb->ring_cnt++;
@@ -165,11 +169,11 @@ ring_buffer__new(int map_fd, ring_buffer_sample_fn sample_cb, void *ctx,
int err; int err;
if (!OPTS_VALID(opts, ring_buffer_opts)) if (!OPTS_VALID(opts, ring_buffer_opts))
return errno = EINVAL, NULL; return NULL;
rb = calloc(1, sizeof(*rb)); rb = calloc(1, sizeof(*rb));
if (!rb) if (!rb)
return errno = ENOMEM, NULL; return NULL;
rb->page_size = getpagesize(); rb->page_size = getpagesize();
@@ -188,7 +192,7 @@ ring_buffer__new(int map_fd, ring_buffer_sample_fn sample_cb, void *ctx,
err_out: err_out:
ring_buffer__free(rb); ring_buffer__free(rb);
return errno = -err, NULL; return NULL;
} }
static inline int roundup_len(__u32 len) static inline int roundup_len(__u32 len)
@@ -202,11 +206,9 @@ static inline int roundup_len(__u32 len)
return (len + 7) / 8 * 8; return (len + 7) / 8 * 8;
} }
static int64_t ringbuf_process_ring(struct ring* r) static int ringbuf_process_ring(struct ring* r)
{ {
int *len_ptr, len, err; int *len_ptr, len, err, cnt = 0;
/* 64-bit to avoid overflow in case of extreme application behavior */
int64_t cnt = 0;
unsigned long cons_pos, prod_pos; unsigned long cons_pos, prod_pos;
bool got_new_data; bool got_new_data;
void *sample; void *sample;
@@ -229,7 +231,7 @@ static int64_t ringbuf_process_ring(struct ring* r)
if ((len & BPF_RINGBUF_DISCARD_BIT) == 0) { if ((len & BPF_RINGBUF_DISCARD_BIT) == 0) {
sample = (void *)len_ptr + BPF_RINGBUF_HDR_SZ; sample = (void *)len_ptr + BPF_RINGBUF_HDR_SZ;
err = r->sample_cb(r->ctx, sample, len); err = r->sample_cb(r->ctx, sample, len);
if (err < 0) { if (err) {
/* update consumer pos and bail out */ /* update consumer pos and bail out */
smp_store_release(r->consumer_pos, smp_store_release(r->consumer_pos,
cons_pos); cons_pos);
@@ -246,57 +248,41 @@ done:
} }
/* Consume available ring buffer(s) data without event polling. /* Consume available ring buffer(s) data without event polling.
* Returns number of records consumed across all registered ring buffers (or * Returns number of records consumed across all registered ring buffers, or
* INT_MAX, whichever is less), or negative number if any of the callbacks * negative number if any of the callbacks return error.
* return error.
*/ */
int ring_buffer__consume(struct ring_buffer *rb) int ring_buffer__consume(struct ring_buffer *rb)
{ {
int64_t err, res = 0; int i, err, res = 0;
int i;
for (i = 0; i < rb->ring_cnt; i++) { for (i = 0; i < rb->ring_cnt; i++) {
struct ring *ring = &rb->rings[i]; struct ring *ring = &rb->rings[i];
err = ringbuf_process_ring(ring); err = ringbuf_process_ring(ring);
if (err < 0) if (err < 0)
return libbpf_err(err); return err;
res += err; res += err;
} }
if (res > INT_MAX)
return INT_MAX;
return res; return res;
} }
/* Poll for available data and consume records, if any are available. /* Poll for available data and consume records, if any are available.
* Returns number of records consumed (or INT_MAX, whichever is less), or * Returns number of records consumed, or negative number, if any of the
* negative number, if any of the registered callbacks returned error. * registered callbacks returned error.
*/ */
int ring_buffer__poll(struct ring_buffer *rb, int timeout_ms) int ring_buffer__poll(struct ring_buffer *rb, int timeout_ms)
{ {
int i, cnt; int i, cnt, err, res = 0;
int64_t err, res = 0;
cnt = epoll_wait(rb->epoll_fd, rb->events, rb->ring_cnt, timeout_ms); cnt = epoll_wait(rb->epoll_fd, rb->events, rb->ring_cnt, timeout_ms);
if (cnt < 0)
return libbpf_err(-errno);
for (i = 0; i < cnt; i++) { for (i = 0; i < cnt; i++) {
__u32 ring_id = rb->events[i].data.fd; __u32 ring_id = rb->events[i].data.fd;
struct ring *ring = &rb->rings[ring_id]; struct ring *ring = &rb->rings[ring_id];
err = ringbuf_process_ring(ring); err = ringbuf_process_ring(ring);
if (err < 0) if (err < 0)
return libbpf_err(err); return err;
res += err; res += cnt;
} }
if (res > INT_MAX) return cnt < 0 ? -errno : res;
return INT_MAX;
return res;
}
/* Get an fd that can be used to sleep until data is available in the ring(s) */
int ring_buffer__epoll_fd(const struct ring_buffer *rb)
{
return rb->epoll_fd;
} }

View File

@@ -1,125 +0,0 @@
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
/* Copyright (c) 2021 Facebook */
#ifndef __SKEL_INTERNAL_H
#define __SKEL_INTERNAL_H
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/mman.h>
/* This file is a base header for auto-generated *.lskel.h files.
* Its contents will change and may become part of auto-generation in the future.
*
* The layout of bpf_[map|prog]_desc and bpf_loader_ctx is feature dependent
* and will change from one version of libbpf to another and features
* requested during loader program generation.
*/
struct bpf_map_desc {
union {
/* input for the loader prog */
struct {
__aligned_u64 initial_value;
__u32 max_entries;
};
/* output of the loader prog */
struct {
int map_fd;
};
};
};
struct bpf_prog_desc {
int prog_fd;
};
struct bpf_loader_ctx {
size_t sz;
__u32 log_level;
__u32 log_size;
__u64 log_buf;
};
struct bpf_load_and_run_opts {
struct bpf_loader_ctx *ctx;
const void *data;
const void *insns;
__u32 data_sz;
__u32 insns_sz;
const char *errstr;
};
static inline int skel_sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
unsigned int size)
{
return syscall(__NR_bpf, cmd, attr, size);
}
static inline int skel_closenz(int fd)
{
if (fd > 0)
return close(fd);
return -EINVAL;
}
static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts)
{
int map_fd = -1, prog_fd = -1, key = 0, err;
union bpf_attr attr;
map_fd = bpf_create_map_name(BPF_MAP_TYPE_ARRAY, "__loader.map", 4,
opts->data_sz, 1, 0);
if (map_fd < 0) {
opts->errstr = "failed to create loader map";
err = -errno;
goto out;
}
err = bpf_map_update_elem(map_fd, &key, opts->data, 0);
if (err < 0) {
opts->errstr = "failed to update loader map";
err = -errno;
goto out;
}
memset(&attr, 0, sizeof(attr));
attr.prog_type = BPF_PROG_TYPE_SYSCALL;
attr.insns = (long) opts->insns;
attr.insn_cnt = opts->insns_sz / sizeof(struct bpf_insn);
attr.license = (long) "Dual BSD/GPL";
memcpy(attr.prog_name, "__loader.prog", sizeof("__loader.prog"));
attr.fd_array = (long) &map_fd;
attr.log_level = opts->ctx->log_level;
attr.log_size = opts->ctx->log_size;
attr.log_buf = opts->ctx->log_buf;
attr.prog_flags = BPF_F_SLEEPABLE;
prog_fd = skel_sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
if (prog_fd < 0) {
opts->errstr = "failed to load loader prog";
err = -errno;
goto out;
}
memset(&attr, 0, sizeof(attr));
attr.test.prog_fd = prog_fd;
attr.test.ctx_in = (long) opts->ctx;
attr.test.ctx_size_in = opts->ctx->sz;
err = skel_sys_bpf(BPF_PROG_RUN, &attr, sizeof(attr));
if (err < 0 || (int)attr.test.retval < 0) {
opts->errstr = "failed to execute loader prog";
if (err < 0) {
err = -errno;
} else {
err = (int)attr.test.retval;
errno = -err;
}
goto out;
}
err = 0;
out:
if (map_fd >= 0)
close(map_fd);
if (prog_fd >= 0)
close(prog_fd);
return err;
}
#endif

View File

@@ -1,177 +0,0 @@
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
/* Copyright (c) 2021 Facebook */
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <linux/err.h>
#include "hashmap.h"
#include "libbpf_internal.h"
#include "strset.h"
struct strset {
void *strs_data;
size_t strs_data_len;
size_t strs_data_cap;
size_t strs_data_max_len;
/* lookup index for each unique string in strings set */
struct hashmap *strs_hash;
};
static size_t strset_hash_fn(const void *key, void *ctx)
{
const struct strset *s = ctx;
const char *str = s->strs_data + (long)key;
return str_hash(str);
}
static bool strset_equal_fn(const void *key1, const void *key2, void *ctx)
{
const struct strset *s = ctx;
const char *str1 = s->strs_data + (long)key1;
const char *str2 = s->strs_data + (long)key2;
return strcmp(str1, str2) == 0;
}
struct strset *strset__new(size_t max_data_sz, const char *init_data, size_t init_data_sz)
{
struct strset *set = calloc(1, sizeof(*set));
struct hashmap *hash;
int err = -ENOMEM;
if (!set)
return ERR_PTR(-ENOMEM);
hash = hashmap__new(strset_hash_fn, strset_equal_fn, set);
if (IS_ERR(hash))
goto err_out;
set->strs_data_max_len = max_data_sz;
set->strs_hash = hash;
if (init_data) {
long off;
set->strs_data = malloc(init_data_sz);
if (!set->strs_data)
goto err_out;
memcpy(set->strs_data, init_data, init_data_sz);
set->strs_data_len = init_data_sz;
set->strs_data_cap = init_data_sz;
for (off = 0; off < set->strs_data_len; off += strlen(set->strs_data + off) + 1) {
/* hashmap__add() returns EEXIST if string with the same
* content already is in the hash map
*/
err = hashmap__add(hash, (void *)off, (void *)off);
if (err == -EEXIST)
continue; /* duplicate */
if (err)
goto err_out;
}
}
return set;
err_out:
strset__free(set);
return ERR_PTR(err);
}
void strset__free(struct strset *set)
{
if (IS_ERR_OR_NULL(set))
return;
hashmap__free(set->strs_hash);
free(set->strs_data);
free(set);
}
size_t strset__data_size(const struct strset *set)
{
return set->strs_data_len;
}
const char *strset__data(const struct strset *set)
{
return set->strs_data;
}
static void *strset_add_str_mem(struct strset *set, size_t add_sz)
{
return libbpf_add_mem(&set->strs_data, &set->strs_data_cap, 1,
set->strs_data_len, set->strs_data_max_len, add_sz);
}
/* Find string offset that corresponds to a given string *s*.
* Returns:
* - >0 offset into string data, if string is found;
* - -ENOENT, if string is not in the string data;
* - <0, on any other error.
*/
int strset__find_str(struct strset *set, const char *s)
{
long old_off, new_off, len;
void *p;
/* see strset__add_str() for why we do this */
len = strlen(s) + 1;
p = strset_add_str_mem(set, len);
if (!p)
return -ENOMEM;
new_off = set->strs_data_len;
memcpy(p, s, len);
if (hashmap__find(set->strs_hash, (void *)new_off, (void **)&old_off))
return old_off;
return -ENOENT;
}
/* Add a string s to the string data. If the string already exists, return its
* offset within string data.
* Returns:
* - > 0 offset into string data, on success;
* - < 0, on error.
*/
int strset__add_str(struct strset *set, const char *s)
{
long old_off, new_off, len;
void *p;
int err;
/* Hashmap keys are always offsets within set->strs_data, so to even
* look up some string from the "outside", we need to first append it
* at the end, so that it can be addressed with an offset. Luckily,
* until set->strs_data_len is incremented, that string is just a piece
* of garbage for the rest of the code, so no harm, no foul. On the
* other hand, if the string is unique, it's already appended and
* ready to be used, only a simple set->strs_data_len increment away.
*/
len = strlen(s) + 1;
p = strset_add_str_mem(set, len);
if (!p)
return -ENOMEM;
new_off = set->strs_data_len;
memcpy(p, s, len);
/* Now attempt to add the string, but only if the string with the same
* contents doesn't exist already (HASHMAP_ADD strategy). If such
* string exists, we'll get its offset in old_off (that's old_key).
*/
err = hashmap__insert(set->strs_hash, (void *)new_off, (void *)new_off,
HASHMAP_ADD, (const void **)&old_off, NULL);
if (err == -EEXIST)
return old_off; /* duplicated string, return existing offset */
if (err)
return err;
set->strs_data_len += len; /* new unique string, adjust data length */
return new_off;
}

View File

@@ -1,21 +0,0 @@
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
/* Copyright (c) 2021 Facebook */
#ifndef __LIBBPF_STRSET_H
#define __LIBBPF_STRSET_H
#include <stdbool.h>
#include <stddef.h>
struct strset;
struct strset *strset__new(size_t max_data_sz, const char *init_data, size_t init_data_sz);
void strset__free(struct strset *set);
const char *strset__data(const struct strset *set);
size_t strset__data_size(const struct strset *set);
int strset__find_str(struct strset *set, const char *s);
int strset__add_str(struct strset *set, const char *s);
#endif /* __LIBBPF_STRSET_H */

800
src/xsk.c

File diff suppressed because it is too large Load Diff

118
src/xsk.h
View File

@@ -3,8 +3,7 @@
/* /*
* AF_XDP user-space access library. * AF_XDP user-space access library.
* *
* Copyright (c) 2018 - 2019 Intel Corporation. * Copyright(c) 2018 - 2019 Intel Corporation.
* Copyright (c) 2019 Facebook
* *
* Author(s): Magnus Karlsson <magnus.karlsson@intel.com> * Author(s): Magnus Karlsson <magnus.karlsson@intel.com>
*/ */
@@ -14,80 +13,15 @@
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <linux/if_xdp.h> #include <linux/if_xdp.h>
#include "libbpf.h" #include "libbpf.h"
#include "libbpf_util.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* Load-Acquire Store-Release barriers used by the XDP socket
* library. The following macros should *NOT* be considered part of
* the xsk.h API, and is subject to change anytime.
*
* LIBRARY INTERNAL
*/
#define __XSK_READ_ONCE(x) (*(volatile typeof(x) *)&x)
#define __XSK_WRITE_ONCE(x, v) (*(volatile typeof(x) *)&x) = (v)
#if defined(__i386__) || defined(__x86_64__)
# define libbpf_smp_store_release(p, v) \
do { \
asm volatile("" : : : "memory"); \
__XSK_WRITE_ONCE(*p, v); \
} while (0)
# define libbpf_smp_load_acquire(p) \
({ \
typeof(*p) ___p1 = __XSK_READ_ONCE(*p); \
asm volatile("" : : : "memory"); \
___p1; \
})
#elif defined(__aarch64__)
# define libbpf_smp_store_release(p, v) \
asm volatile ("stlr %w1, %0" : "=Q" (*p) : "r" (v) : "memory")
# define libbpf_smp_load_acquire(p) \
({ \
typeof(*p) ___p1; \
asm volatile ("ldar %w0, %1" \
: "=r" (___p1) : "Q" (*p) : "memory"); \
___p1; \
})
#elif defined(__riscv)
# define libbpf_smp_store_release(p, v) \
do { \
asm volatile ("fence rw,w" : : : "memory"); \
__XSK_WRITE_ONCE(*p, v); \
} while (0)
# define libbpf_smp_load_acquire(p) \
({ \
typeof(*p) ___p1 = __XSK_READ_ONCE(*p); \
asm volatile ("fence r,rw" : : : "memory"); \
___p1; \
})
#endif
#ifndef libbpf_smp_store_release
#define libbpf_smp_store_release(p, v) \
do { \
__sync_synchronize(); \
__XSK_WRITE_ONCE(*p, v); \
} while (0)
#endif
#ifndef libbpf_smp_load_acquire
#define libbpf_smp_load_acquire(p) \
({ \
typeof(*p) ___p1 = __XSK_READ_ONCE(*p); \
__sync_synchronize(); \
___p1; \
})
#endif
/* LIBRARY INTERNAL -- END */
/* Do not access these members directly. Use the functions below. */ /* Do not access these members directly. Use the functions below. */
#define DEFINE_XSK_RING(name) \ #define DEFINE_XSK_RING(name) \
struct name { \ struct name { \
@@ -162,8 +96,7 @@ static inline __u32 xsk_prod_nb_free(struct xsk_ring_prod *r, __u32 nb)
* this function. Without this optimization it whould have been * this function. Without this optimization it whould have been
* free_entries = r->cached_prod - r->cached_cons + r->size. * free_entries = r->cached_prod - r->cached_cons + r->size.
*/ */
r->cached_cons = libbpf_smp_load_acquire(r->consumer); r->cached_cons = *r->consumer + r->size;
r->cached_cons += r->size;
return r->cached_cons - r->cached_prod; return r->cached_cons - r->cached_prod;
} }
@@ -173,14 +106,15 @@ static inline __u32 xsk_cons_nb_avail(struct xsk_ring_cons *r, __u32 nb)
__u32 entries = r->cached_prod - r->cached_cons; __u32 entries = r->cached_prod - r->cached_cons;
if (entries == 0) { if (entries == 0) {
r->cached_prod = libbpf_smp_load_acquire(r->producer); r->cached_prod = *r->producer;
entries = r->cached_prod - r->cached_cons; entries = r->cached_prod - r->cached_cons;
} }
return (entries > nb) ? nb : entries; return (entries > nb) ? nb : entries;
} }
static inline __u32 xsk_ring_prod__reserve(struct xsk_ring_prod *prod, __u32 nb, __u32 *idx) static inline size_t xsk_ring_prod__reserve(struct xsk_ring_prod *prod,
size_t nb, __u32 *idx)
{ {
if (xsk_prod_nb_free(prod, nb) < nb) if (xsk_prod_nb_free(prod, nb) < nb)
return 0; return 0;
@@ -191,19 +125,27 @@ static inline __u32 xsk_ring_prod__reserve(struct xsk_ring_prod *prod, __u32 nb,
return nb; return nb;
} }
static inline void xsk_ring_prod__submit(struct xsk_ring_prod *prod, __u32 nb) static inline void xsk_ring_prod__submit(struct xsk_ring_prod *prod, size_t nb)
{ {
/* Make sure everything has been written to the ring before indicating /* Make sure everything has been written to the ring before indicating
* this to the kernel by writing the producer pointer. * this to the kernel by writing the producer pointer.
*/ */
libbpf_smp_store_release(prod->producer, *prod->producer + nb); libbpf_smp_wmb();
*prod->producer += nb;
} }
static inline __u32 xsk_ring_cons__peek(struct xsk_ring_cons *cons, __u32 nb, __u32 *idx) static inline size_t xsk_ring_cons__peek(struct xsk_ring_cons *cons,
size_t nb, __u32 *idx)
{ {
__u32 entries = xsk_cons_nb_avail(cons, nb); size_t entries = xsk_cons_nb_avail(cons, nb);
if (entries > 0) { if (entries > 0) {
/* Make sure we do not speculatively read the data before
* we have received the packet buffers from the ring.
*/
libbpf_smp_rmb();
*idx = cons->cached_cons; *idx = cons->cached_cons;
cons->cached_cons += entries; cons->cached_cons += entries;
} }
@@ -211,18 +153,14 @@ static inline __u32 xsk_ring_cons__peek(struct xsk_ring_cons *cons, __u32 nb, __
return entries; return entries;
} }
static inline void xsk_ring_cons__cancel(struct xsk_ring_cons *cons, __u32 nb) static inline void xsk_ring_cons__release(struct xsk_ring_cons *cons, size_t nb)
{
cons->cached_cons -= nb;
}
static inline void xsk_ring_cons__release(struct xsk_ring_cons *cons, __u32 nb)
{ {
/* Make sure data has been read before indicating we are done /* Make sure data has been read before indicating we are done
* with the entries by updating the consumer pointer. * with the entries by updating the consumer pointer.
*/ */
libbpf_smp_store_release(cons->consumer, *cons->consumer + nb); libbpf_smp_rwmb();
*cons->consumer += nb;
} }
static inline void *xsk_umem__get_data(void *umem_area, __u64 addr) static inline void *xsk_umem__get_data(void *umem_area, __u64 addr)
@@ -263,11 +201,6 @@ struct xsk_umem_config {
__u32 flags; __u32 flags;
}; };
LIBBPF_API int xsk_setup_xdp_prog(int ifindex,
int *xsks_map_fd);
LIBBPF_API int xsk_socket__update_xskmap(struct xsk_socket *xsk,
int xsks_map_fd);
/* Flags for the libbpf_flags field. */ /* Flags for the libbpf_flags field. */
#define XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD (1 << 0) #define XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD (1 << 0)
@@ -301,15 +234,6 @@ LIBBPF_API int xsk_socket__create(struct xsk_socket **xsk,
struct xsk_ring_cons *rx, struct xsk_ring_cons *rx,
struct xsk_ring_prod *tx, struct xsk_ring_prod *tx,
const struct xsk_socket_config *config); const struct xsk_socket_config *config);
LIBBPF_API int
xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
const char *ifname,
__u32 queue_id, struct xsk_umem *umem,
struct xsk_ring_cons *rx,
struct xsk_ring_prod *tx,
struct xsk_ring_prod *fill,
struct xsk_ring_cons *comp,
const struct xsk_socket_config *config);
/* Returns 0 for success and -EBUSY if the umem is still in use. */ /* Returns 0 for success and -EBUSY if the umem is still in use. */
LIBBPF_API int xsk_umem__delete(struct xsk_umem *umem); LIBBPF_API int xsk_umem__delete(struct xsk_umem *umem);

View File

@@ -6,7 +6,7 @@ CONT_NAME="${CONT_NAME:-libbpf-debian-$DEBIAN_RELEASE}"
ENV_VARS="${ENV_VARS:-}" ENV_VARS="${ENV_VARS:-}"
DOCKER_RUN="${DOCKER_RUN:-docker run}" DOCKER_RUN="${DOCKER_RUN:-docker run}"
REPO_ROOT="${REPO_ROOT:-$PWD}" REPO_ROOT="${REPO_ROOT:-$PWD}"
ADDITIONAL_DEPS=(clang pkg-config gcc-10) ADDITIONAL_DEPS=(clang pkg-config gcc-8)
CFLAGS="-g -O2 -Werror -Wall" CFLAGS="-g -O2 -Werror -Wall"
function info() { function info() {
@@ -18,10 +18,10 @@ function error() {
} }
function docker_exec() { function docker_exec() {
docker exec $ENV_VARS $CONT_NAME "$@" docker exec $ENV_VARS -it $CONT_NAME "$@"
} }
set -eu set -e
source "$(dirname $0)/travis_wait.bash" source "$(dirname $0)/travis_wait.bash"
@@ -31,6 +31,7 @@ for phase in "${PHASES[@]}"; do
info "Setup phase" info "Setup phase"
info "Using Debian $DEBIAN_RELEASE" info "Using Debian $DEBIAN_RELEASE"
sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
docker --version docker --version
docker pull debian:$DEBIAN_RELEASE docker pull debian:$DEBIAN_RELEASE
@@ -38,24 +39,19 @@ for phase in "${PHASES[@]}"; do
$DOCKER_RUN -v $REPO_ROOT:/build:rw \ $DOCKER_RUN -v $REPO_ROOT:/build:rw \
-w /build --privileged=true --name $CONT_NAME \ -w /build --privileged=true --name $CONT_NAME \
-dit --net=host debian:$DEBIAN_RELEASE /bin/bash -dit --net=host debian:$DEBIAN_RELEASE /bin/bash
echo -e "::group::Build Env Setup"
docker_exec bash -c "echo deb-src http://deb.debian.org/debian $DEBIAN_RELEASE main >>/etc/apt/sources.list" docker_exec bash -c "echo deb-src http://deb.debian.org/debian $DEBIAN_RELEASE main >>/etc/apt/sources.list"
docker_exec apt-get -y update docker_exec apt-get -y update
docker_exec apt-get -y install aptitude docker_exec apt-get -y build-dep libelf-dev
docker_exec aptitude -y build-dep libelf-dev docker_exec apt-get -y install libelf-dev
docker_exec aptitude -y install libelf-dev docker_exec apt-get -y install "${ADDITIONAL_DEPS[@]}"
docker_exec aptitude -y install "${ADDITIONAL_DEPS[@]}"
echo -e "::endgroup::"
;; ;;
RUN|RUN_CLANG|RUN_GCC10|RUN_ASAN|RUN_CLANG_ASAN|RUN_GCC10_ASAN) RUN|RUN_CLANG|RUN_GCC8|RUN_ASAN|RUN_CLANG_ASAN|RUN_GCC8_ASAN)
CC="cc"
if [[ "$phase" = *"CLANG"* ]]; then if [[ "$phase" = *"CLANG"* ]]; then
ENV_VARS="-e CC=clang -e CXX=clang++" ENV_VARS="-e CC=clang -e CXX=clang++"
CC="clang" CC="clang"
elif [[ "$phase" = *"GCC10"* ]]; then elif [[ "$phase" = *"GCC8"* ]]; then
ENV_VARS="-e CC=gcc-10 -e CXX=g++-10" ENV_VARS="-e CC=gcc-8 -e CXX=g++-8"
CC="gcc-10" CC="gcc-8"
CFLAGS="${CFLAGS} -Wno-stringop-truncation"
else else
CFLAGS="${CFLAGS} -Wno-stringop-truncation" CFLAGS="${CFLAGS} -Wno-stringop-truncation"
fi fi
@@ -63,9 +59,9 @@ for phase in "${PHASES[@]}"; do
CFLAGS="${CFLAGS} -fsanitize=address,undefined" CFLAGS="${CFLAGS} -fsanitize=address,undefined"
fi fi
docker_exec mkdir build install docker_exec mkdir build install
docker_exec ${CC} --version docker_exec ${CC:-cc} --version
info "build" info "build"
docker_exec make -j$((4*$(nproc))) CFLAGS="${CFLAGS}" -C ./src -B OBJDIR=../build docker_exec make -j$((4*$(nproc))) CFLAGS="${CFLAGS}" -C ./src -B OBJDIR=../build
info "ldd build/libbpf.so:" info "ldd build/libbpf.so:"
docker_exec ldd build/libbpf.so docker_exec ldd build/libbpf.so
if ! docker_exec ldd build/libbpf.so | grep -q libelf; then if ! docker_exec ldd build/libbpf.so | grep -q libelf; then
@@ -74,8 +70,7 @@ for phase in "${PHASES[@]}"; do
fi fi
info "install" info "install"
docker_exec make -j$((4*$(nproc))) -C src OBJDIR=../build DESTDIR=../install install docker_exec make -j$((4*$(nproc))) -C src OBJDIR=../build DESTDIR=../install install
info "link binary" docker_exec rm -rf build install
docker_exec bash -c "CFLAGS=\"${CFLAGS}\" ./travis-ci/managers/test_compile.sh"
;; ;;
CLEANUP) CLEANUP)
info "Cleanup phase" info "Cleanup phase"

View File

@@ -1,14 +0,0 @@
#!/bin/bash
set -euox pipefail
CFLAGS=${CFLAGS:-}
cat << EOF > main.c
#include <bpf/libbpf.h>
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

View File

@@ -1,16 +1,20 @@
#!/bin/bash #!/bin/bash
set -eux set -e
set -x
RELEASE="focal" RELEASE="bionic"
echo "deb-src http://archive.ubuntu.com/ubuntu/ $RELEASE main restricted universe multiverse" >>/etc/apt/sources.list
apt-get update apt-get update
apt-get install -y pkg-config apt-get -y build-dep libelf-dev
apt-get install -y libelf-dev pkg-config
source "$(dirname $0)/travis_wait.bash" source "$(dirname $0)/travis_wait.bash"
cd $REPO_ROOT cd $REPO_ROOT
CFLAGS="-g -O2 -Werror -Wall -fsanitize=address,undefined -Wno-stringop-truncation" CFLAGS="-g -O2 -Werror -Wall -fsanitize=address,undefined"
mkdir build install mkdir build install
cc --version cc --version
make -j$((4*$(nproc))) CFLAGS="${CFLAGS}" -C ./src -B OBJDIR=../build make -j$((4*$(nproc))) CFLAGS="${CFLAGS}" -C ./src -B OBJDIR=../build
@@ -20,4 +24,4 @@ if ! ldd build/libbpf.so | grep -q libelf; then
exit 1 exit 1
fi fi
make -j$((4*$(nproc))) -C src OBJDIR=../build DESTDIR=../install install make -j$((4*$(nproc))) -C src OBJDIR=../build DESTDIR=../install install
CFLAGS=${CFLAGS} $(dirname $0)/test_compile.sh rm -rf build install

View File

@@ -1,25 +1,17 @@
#!/bin/bash #!/bin/bash
set -eu set -eux
source $(cd $(dirname $0) && pwd)/helpers.sh
CWD=$(pwd) CWD=$(pwd)
REPO_PATH=$1 REPO_PATH=$1
PAHOLE_ORIGIN=${PAHOLE_ORIGIN:-https://git.kernel.org/pub/scm/devel/pahole/pahole.git} PAHOLE_ORIGIN=https://git.kernel.org/pub/scm/devel/pahole/pahole.git
PAHOLE_BRANCH=${PAHOLE_BRANCH:-master}
travis_fold start build_pahole "Building pahole ${PAHOLE_ORIGIN} ${PAHOLE_BRANCH}"
mkdir -p ${REPO_PATH} mkdir -p ${REPO_PATH}
cd ${REPO_PATH} cd ${REPO_PATH}
git init git init
git remote add origin ${PAHOLE_ORIGIN} git remote add origin ${PAHOLE_ORIGIN}
git fetch origin git fetch origin
git checkout ${PAHOLE_BRANCH} git checkout master
# temporary work-around to bump pahole to 1.22 before it is officially released
sed -i 's/DDWARVES_MINOR_VERSION=21/DDWARVES_MINOR_VERSION=22/' CMakeLists.txt
mkdir -p build mkdir -p build
cd build cd build
@@ -31,4 +23,3 @@ export LD_LIBRARY_PATH=${LD_LIBRARY_PATH:-}:/usr/local/lib
ldd $(which pahole) ldd $(which pahole)
pahole --version pahole --version
travis_fold end build_pahole

View File

@@ -1,35 +1,23 @@
#!/bin/bash #!/bin/bash
set -euo pipefail set -euxo pipefail
source $(cd $(dirname $0) && pwd)/helpers.sh LLVM_VER=11
travis_fold start prepare_selftests "Building selftests"
sudo apt-get -y install python-docutils # for rst2man
LLVM_VER=14
LIBBPF_PATH="${REPO_ROOT}" LIBBPF_PATH="${REPO_ROOT}"
REPO_PATH="travis-ci/vmtest/bpf-next"
PREPARE_SELFTESTS_SCRIPT=${VMTEST_ROOT}/prepare_selftests-${KERNEL}.sh PREPARE_SELFTESTS_SCRIPT=${VMTEST_ROOT}/prepare_selftests-${KERNEL}.sh
if [ -f "${PREPARE_SELFTESTS_SCRIPT}" ]; then if [ -f "${PREPARE_SELFTESTS_SCRIPT}" ]; then
(cd "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" && ${PREPARE_SELFTESTS_SCRIPT}) (cd "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" && ${PREPARE_SELFTESTS_SCRIPT})
fi fi
if [[ "${KERNEL}" = 'LATEST' ]]; then
VMLINUX_H=
else
VMLINUX_H=${VMTEST_ROOT}/vmlinux.h
fi
make \ make \
CLANG=clang-${LLVM_VER} \ CLANG=clang-${LLVM_VER} \
LLC=llc-${LLVM_VER} \ LLC=llc-${LLVM_VER} \
LLVM_STRIP=llvm-strip-${LLVM_VER} \ LLVM_STRIP=llvm-strip-${LLVM_VER} \
VMLINUX_BTF="${VMLINUX_BTF}" \ VMLINUX_BTF="${VMLINUX_BTF}" \
VMLINUX_H=${VMLINUX_H} \
-C "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" \ -C "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" \
-j $((4*$(nproc))) >/dev/null -j $((4*$(nproc)))
mkdir ${LIBBPF_PATH}/selftests mkdir ${LIBBPF_PATH}/selftests
cp -R "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" \ cp -R "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" \
${LIBBPF_PATH}/selftests ${LIBBPF_PATH}/selftests
@@ -38,5 +26,3 @@ rm selftests/bpf/.gitignore
git add selftests git add selftests
git add "${VMTEST_ROOT}/configs/blacklist" git add "${VMTEST_ROOT}/configs/blacklist"
travis_fold end prepare_selftests

View File

@@ -1,54 +1,24 @@
#!/bin/bash #!/bin/bash
set -eu set -eux
source $(cd $(dirname $0) && pwd)/helpers.sh
CWD=$(pwd) CWD=$(pwd)
LIBBPF_PATH=$(pwd) LIBBPF_PATH=$(pwd)
REPO_PATH=$1 REPO_PATH=$1
KERNEL_ORIGIN=${KERNEL_ORIGIN:-https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git} BPF_NEXT_ORIGIN=https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git
KERNEL_BRANCH=${KERNEL_BRANCH:-CHECKPOINT} LINUX_SHA=$(cat ${LIBBPF_PATH}/CHECKPOINT-COMMIT)
if [[ "${KERNEL_BRANCH}" = 'CHECKPOINT' ]]; then
echo "using CHECKPOINT sha1"
LINUX_SHA=$(cat ${LIBBPF_PATH}/CHECKPOINT-COMMIT)
else
echo "using ${KERNEL_BRANCH} sha1"
LINUX_SHA=$(git ls-remote ${KERNEL_ORIGIN} ${KERNEL_BRANCH} | awk '{print $1}')
fi
SNAPSHOT_URL=${KERNEL_ORIGIN}/snapshot/bpf-next-${LINUX_SHA}.tar.gz
echo REPO_PATH = ${REPO_PATH} echo REPO_PATH = ${REPO_PATH}
echo KERNEL_ORIGIN = ${KERNEL_ORIGIN}
echo LINUX_SHA = ${LINUX_SHA} echo LINUX_SHA = ${LINUX_SHA}
echo SNAPSHOT_URL = ${SNAPSHOT_URL}
if [ ! -d "${REPO_PATH}" ]; then if [ ! -d "${REPO_PATH}" ]; then
echo mkdir -p ${REPO_PATH}
travis_fold start pull_kernel_srcs "Fetching kernel sources" cd ${REPO_PATH}
git init
mkdir -p $(dirname "${REPO_PATH}") git remote add bpf-next ${BPF_NEXT_ORIGIN}
cd $(dirname "${REPO_PATH}") for depth in 32 64 128; do
# attempt to fetch desired bpf-next repo snapshot git fetch --depth ${depth} bpf-next
if wget -nv ${SNAPSHOT_URL} && tar xf bpf-next-${LINUX_SHA}.tar.gz --totals ; then git reset --hard ${LINUX_SHA} && break
mv bpf-next-${LINUX_SHA} $(basename ${REPO_PATH}) done
else
# but fallback to git fetch approach if that fails
mkdir -p $(basename ${REPO_PATH})
cd $(basename ${REPO_PATH})
git init
git remote add bpf-next ${KERNEL_ORIGIN}
# try shallow clone first
git fetch --depth 32 bpf-next
# check if desired SHA exists
if ! git cat-file -e ${LINUX_SHA}^{commit} ; then
# if not, fetch all of bpf-next; slow and painful
git fetch bpf-next
fi
git reset --hard ${LINUX_SHA}
fi
travis_fold end pull_kernel_srcs
fi fi

View File

@@ -1,8 +1,6 @@
INDEX https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/INDEX INDEX https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/INDEX
libbpf-vmtest-rootfs-2020.09.27.tar.zst https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/libbpf-vmtest-rootfs-2020.09.27.tar.zst libbpf-vmtest-rootfs-2020.03.11.tar.zst https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/libbpf-vmtest-rootfs-2020.03.11.tar.zst
vmlinux-4.9.0.zst https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinux-4.9.0.zst
vmlinux-5.5.0-rc6.zst https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinux-5.5.0-rc6.zst vmlinux-5.5.0-rc6.zst https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinux-5.5.0-rc6.zst
vmlinux-5.5.0.zst https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinux-5.5.0.zst vmlinux-5.5.0.zst https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinux-5.5.0.zst
vmlinuz-5.5.0-rc6 https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinuz-5.5.0-rc6 vmlinuz-5.5.0-rc6 https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinuz-5.5.0-rc6
vmlinuz-5.5.0 https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinuz-5.5.0 vmlinuz-5.5.0 https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinuz-5.5.0
vmlinuz-4.9.0 https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinuz-4.9.0

View File

@@ -1,60 +1,33 @@
# PERMANENTLY DISABLED # PERMANENTLY DISABLED
align # verifier output format changed 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_iter # bpf_iter support is missing
bpf_obj_id # bpf_link support missing for GET_OBJ_INFO, GET_FD_BY_ID, etc bpf_obj_id # bpf_link support missing for GET_OBJ_INFO, GET_FD_BY_ID, etc
bpf_tcp_ca # STRUCT_OPS is missing bpf_tcp_ca # STRUCT_OPS is missing
btf_map_in_map # inner map leak fixed in 5.8
btf_skc_cls_ingress # v5.10+ functionality # latest Clang generates code that fails to verify
cg_storage_multi # v5.9+ functionality bpf_verif_scale
#bpf_verif_scale/strobemeta.o
#bpf_verif_scale/strobemeta_nounroll1.o
#bpf_verif_scale/strobemeta_nounroll2.o
cgroup_attach_multi # BPF_F_REPLACE_PROG missing cgroup_attach_multi # BPF_F_REPLACE_PROG missing
cgroup_link # LINK_CREATE is missing cgroup_link # LINK_CREATE is missing
cgroup_skb_sk_lookup # bpf_sk_lookup_tcp() helper is missing cgroup_skb_sk_lookup # bpf_sk_lookup_tcp() helper is missing
check_mtu # missing BPF helper (v5.12+)
cls_redirect # bpf_csum_level() helper is missing
connect_force_port # cgroup/get{peer,sock}name{4,6} support is missing connect_force_port # cgroup/get{peer,sock}name{4,6} support is missing
d_path # v5.10+ feature
enable_stats # BPF_ENABLE_STATS support is missing enable_stats # BPF_ENABLE_STATS support is missing
fentry_fexit # bpf_prog_test_tracing missing fentry_fexit # bpf_prog_test_tracing missing
fentry_test # bpf_prog_test_tracing missing fentry_test # bpf_prog_test_tracing missing
fexit_bpf2bpf # freplace is missing fexit_bpf2bpf # freplace is missing
fexit_sleep # relies on bpf_trampoline fix in 5.12+
fexit_test # bpf_prog_test_tracing missing fexit_test # bpf_prog_test_tracing missing
flow_dissector # bpf_link-based flow dissector is in 5.8+ flow_dissector # bpf_link-based flow dissector is in 5.8+
flow_dissector_reattach flow_dissector_reattach
for_each # v5.12+
get_func_ip_test # v5.15+
get_stack_raw_tp # exercising BPF verifier bug causing infinite loop get_stack_raw_tp # exercising BPF verifier bug causing infinite loop
hash_large_key # v5.11+
ima # v5.11+
kfree_skb # 32-bit pointer arith in test_pkt_access
ksyms # __start_BTF has different name
kfunc_call # v5.13+
link_pinning # bpf_link is missing link_pinning # bpf_link is missing
linked_vars # v5.13+
load_bytes_relative # new functionality in 5.8 load_bytes_relative # new functionality in 5.8
lookup_and_delete # v5.14+
map_init # per-CPU LRU missing
map_ptr # test uses BPF_MAP_TYPE_RINGBUF, added in 5.8
metadata # v5.10+
migrate_reuseport # v5.14+
mmap # 5.5 kernel is too permissive with re-mmaping mmap # 5.5 kernel is too permissive with re-mmaping
modify_return # fmod_ret support is missing modify_return # fmod_ret support is missing
module_attach # module BTF support missing (v5.11+)
netcnt
netns_cookie # v5.15+
ns_current_pid_tgid # bpf_get_ns_current_pid_tgid() helper is missing 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_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
raw_tp_test_run # v5.10+
recursion # v5.12+
ringbuf # BPF_MAP_TYPE_RINGBUF is supported in 5.8+ ringbuf # BPF_MAP_TYPE_RINGBUF is supported in 5.8+
# bug in verifier w/ tracking references # bug in verifier w/ tracking references
@@ -62,53 +35,19 @@ ringbuf # BPF_MAP_TYPE_RINGBUF is supported in 5.8+
reference_tracking reference_tracking
select_reuseport # UDP support is missing select_reuseport # UDP support is missing
send_signal # bpf_send_signal_thread() helper is missing
sk_assign # bpf_sk_assign helper missing sk_assign # bpf_sk_assign helper missing
sk_lookup # v5.9+
sk_storage_tracing # missing bpf_sk_storage_get() helper
skb_ctx # ctx_{size, }_{in, out} in BPF_PROG_TEST_RUN is missing
skb_helpers # helpers added in 5.8+ skb_helpers # helpers added in 5.8+
snprintf # v5.13+
snprintf_btf # v5.10+
sock_fields # v5.10+
socket_cookie # v5.12+
sockmap_basic # uses new socket fields, 5.8+
sockmap_listen # no listen socket supportin SOCKMAP sockmap_listen # no listen socket supportin SOCKMAP
sockopt_sk skb_ctx # ctx_{size, }_{in, out} in BPF_PROG_TEST_RUN is missing
sockopt_qos_to_cc # v5.15+
stacktrace_build_id # v5.9+
stack_var_off # v5.12+
syscall # v5.14+
task_local_storage # v5.12+
task_pt_regs # v5.15+
tcp_hdr_options # v5.10+, new TCP header options feature in BPF
tcpbpf_user # LINK_CREATE is missing
tc_redirect # v5.14+
test_bpffs # v5.10+, new CONFIG_BPF_PRELOAD=y and CONFIG_BPF_PRELOAD_UMG=y|m
test_bprm_opts # v5.11+
test_global_funcs # kernel doesn't support BTF linkage=global on FUNCs test_global_funcs # kernel doesn't support BTF linkage=global on FUNCs
test_local_storage # v5.10+ feature
test_lsm # no BPF_LSM support test_lsm # no BPF_LSM support
test_overhead # no fmod_ret support test_overhead # no fmod_ret support
test_profiler # needs verifier logic improvements from v5.10+
test_skb_pkt_end # v5.11+
timer # v5.15+
timer_mim # v5.15+
trace_ext # v5.10+
trace_printk # v5.14+
trampoline_count # v5.12+ have lower allowed limits
udp_limit # no cgroup/sock_release BPF program type (5.9+)
varlen # verifier bug fixed in later kernels
vmlinux # hrtimer_nanosleep() signature changed incompatibly vmlinux # hrtimer_nanosleep() signature changed incompatibly
xdp_adjust_tail # new XDP functionality added in 5.8 xdp_adjust_tail # new XDP functionality added in 5.8
xdp_attach # IFLA_XDP_EXPECTED_FD support is missing xdp_attach # IFLA_XDP_EXPECTED_FD support is missing
xdp_bonding # v5.15+
xdp_bpf2bpf # freplace is missing xdp_bpf2bpf # freplace is missing
xdp_context_test_run # v5.15+
xdp_cpumap_attach # v5.9+
xdp_devmap_attach # new feature in 5.8
xdp_link # v5.9+
# SUBTESTS FAILING (block entire test until blocking subtests works properly)
btf # "size check test", "func (Non zero vlen)" # TEMPORARILY DISABLED
tailcalls # tailcall_bpf2bpf_1, tailcall_bpf2bpf_2, tailcall_bpf2bpf_3 send_signal # flaky
cls_redirect # latest Clang breaks BPF verification

View File

@@ -1,5 +1,5 @@
# TEMPORARY # TEMPORARILY DISABLED
get_stack_raw_tp # spams with kernel warnings until next bpf -> bpf-next merge send_signal # flaky
stacktrace_build_id_nmi test_lsm # semi-working
stacktrace_build_id sk_assign # needs better setup in Travis CI
task_fd_query_rawtp core_reloc # temporary test breakage

View File

@@ -1,15 +1,18 @@
# #
# Automatically generated file; DO NOT EDIT. # Automatically generated file; DO NOT EDIT.
# Linux/x86 5.9.0-rc1 Kernel Configuration # Linux/x86 5.6.0-rc3 Kernel Configuration
#
#
# Compiler: gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36)
# #
CONFIG_CC_VERSION_TEXT="gcc (GCC) 8.2.1 20180801 (Red Hat 8.2.1-2)"
CONFIG_CC_IS_GCC=y CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=80201 CONFIG_GCC_VERSION=40805
CONFIG_LD_VERSION=230000000
CONFIG_CLANG_VERSION=0 CONFIG_CLANG_VERSION=0
CONFIG_CC_CAN_LINK=y CONFIG_CC_CAN_LINK=y
CONFIG_CC_CAN_LINK_STATIC=y
CONFIG_CC_HAS_ASM_GOTO=y CONFIG_CC_HAS_ASM_GOTO=y
CONFIG_CC_HAS_WARN_MAYBE_UNINITIALIZED=y
CONFIG_CC_DISABLE_WARN_MAYBE_UNINITIALIZED=y
CONFIG_IRQ_WORK=y CONFIG_IRQ_WORK=y
CONFIG_BUILDTIME_TABLE_SORT=y CONFIG_BUILDTIME_TABLE_SORT=y
CONFIG_THREAD_INFO_IN_TASK=y CONFIG_THREAD_INFO_IN_TASK=y
@@ -28,27 +31,22 @@ CONFIG_HAVE_KERNEL_LZMA=y
CONFIG_HAVE_KERNEL_XZ=y CONFIG_HAVE_KERNEL_XZ=y
CONFIG_HAVE_KERNEL_LZO=y CONFIG_HAVE_KERNEL_LZO=y
CONFIG_HAVE_KERNEL_LZ4=y CONFIG_HAVE_KERNEL_LZ4=y
CONFIG_HAVE_KERNEL_ZSTD=y
CONFIG_KERNEL_GZIP=y CONFIG_KERNEL_GZIP=y
# CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_BZIP2 is not set
# CONFIG_KERNEL_LZMA is not set # CONFIG_KERNEL_LZMA is not set
# CONFIG_KERNEL_XZ is not set # CONFIG_KERNEL_XZ is not set
# CONFIG_KERNEL_LZO is not set # CONFIG_KERNEL_LZO is not set
# CONFIG_KERNEL_LZ4 is not set # CONFIG_KERNEL_LZ4 is not set
# CONFIG_KERNEL_ZSTD is not set
CONFIG_DEFAULT_INIT=""
CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_DEFAULT_HOSTNAME="(none)"
CONFIG_SWAP=y CONFIG_SWAP=y
CONFIG_SYSVIPC=y CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y CONFIG_POSIX_MQUEUE=y
CONFIG_POSIX_MQUEUE_SYSCTL=y CONFIG_POSIX_MQUEUE_SYSCTL=y
# CONFIG_WATCH_QUEUE is not set
CONFIG_CROSS_MEMORY_ATTACH=y CONFIG_CROSS_MEMORY_ATTACH=y
# CONFIG_USELIB is not set # CONFIG_USELIB is not set
CONFIG_AUDIT=y # CONFIG_AUDIT is not set
CONFIG_HAVE_ARCH_AUDITSYSCALL=y CONFIG_HAVE_ARCH_AUDITSYSCALL=y
CONFIG_AUDITSYSCALL=y
# #
# IRQ subsystem # IRQ subsystem
@@ -58,7 +56,6 @@ CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
CONFIG_GENERIC_PENDING_IRQ=y CONFIG_GENERIC_PENDING_IRQ=y
CONFIG_GENERIC_IRQ_MIGRATION=y CONFIG_GENERIC_IRQ_MIGRATION=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_IRQ_DOMAIN=y CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_DOMAIN_HIERARCHY=y CONFIG_IRQ_DOMAIN_HIERARCHY=y
CONFIG_GENERIC_MSI_IRQ=y CONFIG_GENERIC_MSI_IRQ=y
@@ -71,6 +68,7 @@ CONFIG_SPARSE_IRQ=y
# end of IRQ subsystem # end of IRQ subsystem
CONFIG_CLOCKSOURCE_WATCHDOG=y CONFIG_CLOCKSOURCE_WATCHDOG=y
CONFIG_ARCH_CLOCKSOURCE_DATA=y
CONFIG_ARCH_CLOCKSOURCE_INIT=y CONFIG_ARCH_CLOCKSOURCE_INIT=y
CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y
CONFIG_GENERIC_TIME_VSYSCALL=y CONFIG_GENERIC_TIME_VSYSCALL=y
@@ -78,8 +76,6 @@ CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y
CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_HAVE_POSIX_CPU_TIMERS_TASK_WORK=y
CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y
# #
# Timers subsystem # Timers subsystem
@@ -124,9 +120,7 @@ CONFIG_PREEMPT_RCU=y
# CONFIG_RCU_EXPERT is not set # CONFIG_RCU_EXPERT is not set
CONFIG_SRCU=y CONFIG_SRCU=y
CONFIG_TREE_SRCU=y CONFIG_TREE_SRCU=y
CONFIG_TASKS_RCU_GENERIC=y
CONFIG_TASKS_RCU=y CONFIG_TASKS_RCU=y
CONFIG_TASKS_RUDE_RCU=y
CONFIG_RCU_STALL_COMMON=y CONFIG_RCU_STALL_COMMON=y
CONFIG_RCU_NEED_SEGCBLIST=y CONFIG_RCU_NEED_SEGCBLIST=y
# end of RCU Subsystem # end of RCU Subsystem
@@ -142,7 +136,6 @@ CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
# #
# Scheduler features # Scheduler features
# #
# CONFIG_UCLAMP_TASK is not set
# end of Scheduler features # end of Scheduler features
CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y
@@ -155,6 +148,7 @@ CONFIG_CGROUPS=y
CONFIG_PAGE_COUNTER=y CONFIG_PAGE_COUNTER=y
CONFIG_MEMCG=y CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y CONFIG_MEMCG_SWAP=y
CONFIG_MEMCG_SWAP_ENABLED=y
CONFIG_MEMCG_KMEM=y CONFIG_MEMCG_KMEM=y
CONFIG_BLK_CGROUP=y CONFIG_BLK_CGROUP=y
CONFIG_CGROUP_WRITEBACK=y CONFIG_CGROUP_WRITEBACK=y
@@ -193,7 +187,6 @@ CONFIG_RD_LZMA=y
CONFIG_RD_XZ=y CONFIG_RD_XZ=y
CONFIG_RD_LZO=y CONFIG_RD_LZO=y
CONFIG_RD_LZ4=y CONFIG_RD_LZ4=y
CONFIG_RD_ZSTD=y
CONFIG_BOOT_CONFIG=y CONFIG_BOOT_CONFIG=y
CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -228,14 +221,10 @@ CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y CONFIG_KALLSYMS_ALL=y
CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y
CONFIG_KALLSYMS_BASE_RELATIVE=y CONFIG_KALLSYMS_BASE_RELATIVE=y
CONFIG_BPF_LSM=y
CONFIG_BPF_SYSCALL=y CONFIG_BPF_SYSCALL=y
CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y
CONFIG_BPF_JIT_ALWAYS_ON=y CONFIG_BPF_JIT_ALWAYS_ON=y
CONFIG_BPF_JIT_DEFAULT_ON=y CONFIG_BPF_JIT_DEFAULT_ON=y
CONFIG_USERMODE_DRIVER=y
CONFIG_BPF_PRELOAD=y
CONFIG_BPF_PRELOAD_UMD=y
# CONFIG_USERFAULTFD is not set # CONFIG_USERFAULTFD is not set
CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y
CONFIG_RSEQ=y CONFIG_RSEQ=y
@@ -272,6 +261,7 @@ CONFIG_X86_64=y
CONFIG_X86=y CONFIG_X86=y
CONFIG_INSTRUCTION_DECODER=y CONFIG_INSTRUCTION_DECODER=y
CONFIG_OUTPUT_FORMAT="elf64-x86-64" CONFIG_OUTPUT_FORMAT="elf64-x86-64"
CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
CONFIG_LOCKDEP_SUPPORT=y CONFIG_LOCKDEP_SUPPORT=y
CONFIG_STACKTRACE_SUPPORT=y CONFIG_STACKTRACE_SUPPORT=y
CONFIG_MMU=y CONFIG_MMU=y
@@ -389,6 +379,7 @@ CONFIG_X86_DIRECT_GBPAGES=y
CONFIG_NUMA=y CONFIG_NUMA=y
CONFIG_AMD_NUMA=y CONFIG_AMD_NUMA=y
CONFIG_X86_64_ACPI_NUMA=y CONFIG_X86_64_ACPI_NUMA=y
CONFIG_NODES_SPAN_OTHER_NODES=y
# CONFIG_NUMA_EMU is not set # CONFIG_NUMA_EMU is not set
CONFIG_NODES_SHIFT=6 CONFIG_NODES_SHIFT=6
CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_ENABLE=y
@@ -461,12 +452,12 @@ CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y
# CONFIG_ACPI_DEBUGGER is not set # CONFIG_ACPI_DEBUGGER is not set
# CONFIG_ACPI_SPCR_TABLE is not set # CONFIG_ACPI_SPCR_TABLE is not set
CONFIG_ACPI_LPIT=y CONFIG_ACPI_LPIT=y
# CONFIG_ACPI_PROCFS_POWER is not set
# CONFIG_ACPI_REV_OVERRIDE_POSSIBLE is not set # CONFIG_ACPI_REV_OVERRIDE_POSSIBLE is not set
# CONFIG_ACPI_EC_DEBUGFS is not set # CONFIG_ACPI_EC_DEBUGFS is not set
# CONFIG_ACPI_AC is not set # CONFIG_ACPI_AC is not set
# CONFIG_ACPI_BATTERY is not set # CONFIG_ACPI_BATTERY is not set
# CONFIG_ACPI_BUTTON is not set # CONFIG_ACPI_BUTTON is not set
# CONFIG_ACPI_TINY_POWER_BUTTON is not set
# CONFIG_ACPI_VIDEO is not set # CONFIG_ACPI_VIDEO is not set
# CONFIG_ACPI_FAN is not set # CONFIG_ACPI_FAN is not set
# CONFIG_ACPI_DOCK is not set # CONFIG_ACPI_DOCK is not set
@@ -519,7 +510,7 @@ CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y # CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set
# #
# CPU frequency scaling drivers # CPU frequency scaling drivers
@@ -589,7 +580,6 @@ CONFIG_EFI_ESRT=y
CONFIG_EFI_RUNTIME_MAP=y CONFIG_EFI_RUNTIME_MAP=y
# CONFIG_EFI_FAKE_MEMMAP is not set # CONFIG_EFI_FAKE_MEMMAP is not set
CONFIG_EFI_RUNTIME_WRAPPERS=y CONFIG_EFI_RUNTIME_WRAPPERS=y
CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER=y
# CONFIG_EFI_CAPSULE_LOADER is not set # CONFIG_EFI_CAPSULE_LOADER is not set
# CONFIG_EFI_TEST is not set # CONFIG_EFI_TEST is not set
# CONFIG_APPLE_PROPERTIES is not set # CONFIG_APPLE_PROPERTIES is not set
@@ -609,10 +599,8 @@ CONFIG_EFI_EARLYCON=y
CONFIG_HAVE_KVM=y CONFIG_HAVE_KVM=y
CONFIG_VIRTUALIZATION=y CONFIG_VIRTUALIZATION=y
# CONFIG_KVM is not set # CONFIG_KVM is not set
CONFIG_KVM_WERROR=y # CONFIG_VHOST_NET is not set
CONFIG_AS_AVX512=y # CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set
CONFIG_AS_SHA1_NI=y
CONFIG_AS_SHA256_NI=y
# #
# General architecture-dependent options # General architecture-dependent options
@@ -620,7 +608,6 @@ CONFIG_AS_SHA256_NI=y
CONFIG_CRASH_CORE=y CONFIG_CRASH_CORE=y
CONFIG_KEXEC_CORE=y CONFIG_KEXEC_CORE=y
CONFIG_HOTPLUG_SMT=y CONFIG_HOTPLUG_SMT=y
CONFIG_GENERIC_ENTRY=y
# CONFIG_OPROFILE is not set # CONFIG_OPROFILE is not set
CONFIG_HAVE_OPROFILE=y CONFIG_HAVE_OPROFILE=y
CONFIG_OPROFILE_NMI_TIMER=y CONFIG_OPROFILE_NMI_TIMER=y
@@ -652,6 +639,7 @@ CONFIG_HAVE_ASM_MODVERSIONS=y
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
CONFIG_HAVE_RSEQ=y CONFIG_HAVE_RSEQ=y
CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_HW_BREAKPOINT=y CONFIG_HAVE_HW_BREAKPOINT=y
CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
CONFIG_HAVE_USER_RETURN_NOTIFIER=y CONFIG_HAVE_USER_RETURN_NOTIFIER=y
@@ -669,6 +657,7 @@ CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
CONFIG_SECCOMP_FILTER=y CONFIG_SECCOMP_FILTER=y
CONFIG_HAVE_ARCH_STACKLEAK=y CONFIG_HAVE_ARCH_STACKLEAK=y
CONFIG_HAVE_STACKPROTECTOR=y CONFIG_HAVE_STACKPROTECTOR=y
CONFIG_CC_HAS_STACKPROTECTOR_NONE=y
# CONFIG_STACKPROTECTOR is not set # CONFIG_STACKPROTECTOR is not set
CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=y CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=y
CONFIG_HAVE_CONTEXT_TRACKING=y CONFIG_HAVE_CONTEXT_TRACKING=y
@@ -682,10 +671,12 @@ CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
CONFIG_HAVE_ARCH_SOFT_DIRTY=y CONFIG_HAVE_ARCH_SOFT_DIRTY=y
CONFIG_HAVE_MOD_ARCH_SPECIFIC=y CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
CONFIG_MODULES_USE_ELF_RELA=y CONFIG_MODULES_USE_ELF_RELA=y
CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y
CONFIG_ARCH_HAS_ELF_RANDOMIZE=y CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
CONFIG_HAVE_ARCH_MMAP_RND_BITS=y CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
CONFIG_HAVE_EXIT_THREAD=y CONFIG_HAVE_EXIT_THREAD=y
CONFIG_ARCH_MMAP_RND_BITS=28 CONFIG_ARCH_MMAP_RND_BITS=28
CONFIG_HAVE_COPY_THREAD_TLS=y
CONFIG_HAVE_STACK_VALIDATION=y CONFIG_HAVE_STACK_VALIDATION=y
CONFIG_HAVE_RELIABLE_STACKTRACE=y CONFIG_HAVE_RELIABLE_STACKTRACE=y
CONFIG_COMPAT_32BIT_TIME=y CONFIG_COMPAT_32BIT_TIME=y
@@ -707,6 +698,7 @@ CONFIG_ARCH_HAS_MEM_ENCRYPT=y
CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
# end of GCOV-based kernel profiling # end of GCOV-based kernel profiling
CONFIG_PLUGIN_HOSTCC=""
CONFIG_HAVE_GCC_PLUGINS=y CONFIG_HAVE_GCC_PLUGINS=y
# end of General architecture-dependent options # end of General architecture-dependent options
@@ -740,7 +732,6 @@ CONFIG_BLK_CGROUP_IOLATENCY=y
# CONFIG_BLK_CGROUP_IOCOST is not set # CONFIG_BLK_CGROUP_IOCOST is not set
CONFIG_BLK_DEBUG_FS=y CONFIG_BLK_DEBUG_FS=y
# CONFIG_BLK_SED_OPAL is not set # CONFIG_BLK_SED_OPAL is not set
# CONFIG_BLK_INLINE_ENCRYPTION is not set
# #
# Partition Types # Partition Types
@@ -788,7 +779,6 @@ CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
CONFIG_QUEUED_SPINLOCKS=y CONFIG_QUEUED_SPINLOCKS=y
CONFIG_ARCH_USE_QUEUED_RWLOCKS=y CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
CONFIG_QUEUED_RWLOCKS=y CONFIG_QUEUED_RWLOCKS=y
CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE=y
CONFIG_ARCH_HAS_SYNC_CORE_BEFORE_USERMODE=y CONFIG_ARCH_HAS_SYNC_CORE_BEFORE_USERMODE=y
CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y
CONFIG_FREEZER=y CONFIG_FREEZER=y
@@ -811,9 +801,11 @@ CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_SPARSEMEM_MANUAL=y CONFIG_SPARSEMEM_MANUAL=y
CONFIG_SPARSEMEM=y CONFIG_SPARSEMEM=y
CONFIG_NEED_MULTIPLE_NODES=y CONFIG_NEED_MULTIPLE_NODES=y
CONFIG_HAVE_MEMORY_PRESENT=y
CONFIG_SPARSEMEM_EXTREME=y CONFIG_SPARSEMEM_EXTREME=y
CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
CONFIG_SPARSEMEM_VMEMMAP=y CONFIG_SPARSEMEM_VMEMMAP=y
CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
CONFIG_HAVE_FAST_GUP=y CONFIG_HAVE_FAST_GUP=y
CONFIG_MEMORY_ISOLATION=y CONFIG_MEMORY_ISOLATION=y
# CONFIG_MEMORY_HOTPLUG is not set # CONFIG_MEMORY_HOTPLUG is not set
@@ -821,7 +813,6 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MEMORY_BALLOON=y CONFIG_MEMORY_BALLOON=y
CONFIG_BALLOON_COMPACTION=y CONFIG_BALLOON_COMPACTION=y
CONFIG_COMPACTION=y CONFIG_COMPACTION=y
CONFIG_PAGE_REPORTING=y
CONFIG_MIGRATION=y CONFIG_MIGRATION=y
CONFIG_CONTIG_ALLOC=y CONFIG_CONTIG_ALLOC=y
CONFIG_PHYS_ADDR_T_64BIT=y CONFIG_PHYS_ADDR_T_64BIT=y
@@ -837,6 +828,7 @@ CONFIG_TRANSPARENT_HUGEPAGE=y
CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
CONFIG_ARCH_WANTS_THP_SWAP=y CONFIG_ARCH_WANTS_THP_SWAP=y
CONFIG_THP_SWAP=y CONFIG_THP_SWAP=y
CONFIG_TRANSPARENT_HUGE_PAGECACHE=y
# CONFIG_CLEANCACHE is not set # CONFIG_CLEANCACHE is not set
# CONFIG_FRONTSWAP is not set # CONFIG_FRONTSWAP is not set
CONFIG_CMA=y CONFIG_CMA=y
@@ -957,7 +949,6 @@ CONFIG_IPV6_SUBTREES=y
CONFIG_IPV6_SEG6_LWTUNNEL=y CONFIG_IPV6_SEG6_LWTUNNEL=y
# CONFIG_IPV6_SEG6_HMAC is not set # CONFIG_IPV6_SEG6_HMAC is not set
CONFIG_IPV6_SEG6_BPF=y CONFIG_IPV6_SEG6_BPF=y
# CONFIG_IPV6_RPL_LWTUNNEL is not set
CONFIG_NETLABEL=y CONFIG_NETLABEL=y
# CONFIG_MPTCP is not set # CONFIG_MPTCP is not set
CONFIG_NETWORK_SECMARK=y CONFIG_NETWORK_SECMARK=y
@@ -988,7 +979,6 @@ CONFIG_NETFILTER_XTABLES=y
# #
# Xtables targets # Xtables targets
# #
# CONFIG_NETFILTER_XT_TARGET_AUDIT is not set
# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set # CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
# CONFIG_NETFILTER_XT_TARGET_HMARK is not set # CONFIG_NETFILTER_XT_TARGET_HMARK is not set
# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set # CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
@@ -1192,7 +1182,6 @@ CONFIG_NET_ACT_BPF=y
# CONFIG_NET_ACT_SKBMOD is not set # CONFIG_NET_ACT_SKBMOD is not set
# CONFIG_NET_ACT_IFE is not set # CONFIG_NET_ACT_IFE is not set
# CONFIG_NET_ACT_TUNNEL_KEY is not set # CONFIG_NET_ACT_TUNNEL_KEY is not set
# CONFIG_NET_ACT_GATE is not set
CONFIG_NET_TC_SKB_EXT=y CONFIG_NET_TC_SKB_EXT=y
CONFIG_NET_SCH_FIFO=y CONFIG_NET_SCH_FIFO=y
CONFIG_DCB=y CONFIG_DCB=y
@@ -1208,7 +1197,6 @@ CONFIG_MPLS=y
# CONFIG_HSR is not set # CONFIG_HSR is not set
# CONFIG_NET_SWITCHDEV is not set # CONFIG_NET_SWITCHDEV is not set
# CONFIG_NET_L3_MASTER_DEV is not set # CONFIG_NET_L3_MASTER_DEV is not set
# CONFIG_QRTR is not set
# CONFIG_NET_NCSI is not set # CONFIG_NET_NCSI is not set
CONFIG_RPS=y CONFIG_RPS=y
CONFIG_RFS_ACCEL=y CONFIG_RFS_ACCEL=y
@@ -1307,11 +1295,6 @@ CONFIG_PCI_LABEL=y
# CONFIG_PCI_MESON is not set # CONFIG_PCI_MESON is not set
# end of DesignWare PCI Core Support # end of DesignWare PCI Core Support
#
# Mobiveil PCIe Core Support
#
# end of Mobiveil PCIe Core Support
# #
# Cadence PCIe controllers support # Cadence PCIe controllers support
# #
@@ -1367,7 +1350,6 @@ CONFIG_DMA_SHARED_BUFFER=y
# #
# Bus devices # Bus devices
# #
# CONFIG_MHI_BUS is not set
# end of Bus devices # end of Bus devices
# CONFIG_CONNECTOR is not set # CONFIG_CONNECTOR is not set
@@ -1388,7 +1370,7 @@ CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set # CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set
# CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_UMEM is not set
CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_DRBD is not set # CONFIG_BLK_DEV_DRBD is not set
# CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SKD is not set # CONFIG_BLK_DEV_SKD is not set
@@ -1486,7 +1468,7 @@ CONFIG_SCSI_MOD=y
# CONFIG_MACINTOSH_DRIVERS is not set # CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y CONFIG_NETDEVICES=y
CONFIG_NET_CORE=y CONFIG_NET_CORE=y
CONFIG_BONDING=y # CONFIG_BONDING is not set
# CONFIG_DUMMY is not set # CONFIG_DUMMY is not set
# CONFIG_WIREGUARD is not set # CONFIG_WIREGUARD is not set
# CONFIG_EQUALIZER is not set # CONFIG_EQUALIZER is not set
@@ -1595,7 +1577,23 @@ CONFIG_HW_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y CONFIG_VT_HW_CONSOLE_BINDING=y
CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set # CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_ROCKETPORT is not set
# CONFIG_CYCLADES is not set
# CONFIG_MOXA_INTELLIO is not set
# CONFIG_MOXA_SMARTIO is not set
# CONFIG_SYNCLINK is not set
# CONFIG_SYNCLINKMP is not set
# CONFIG_SYNCLINK_GT is not set
# CONFIG_NOZOMI is not set
# CONFIG_ISI is not set
# CONFIG_N_HDLC is not set
# CONFIG_N_GSM is not set
# CONFIG_TRACE_SINK is not set
# CONFIG_NULL_TTY is not set
CONFIG_LDISC_AUTOLOAD=y CONFIG_LDISC_AUTOLOAD=y
CONFIG_DEVMEM=y
CONFIG_DEVKMEM=y
# #
# Serial drivers # Serial drivers
@@ -1628,7 +1626,6 @@ CONFIG_SERIAL_8250_RSA=y
CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set # CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_LANTIQ is not set
# CONFIG_SERIAL_SCCNXP is not set # CONFIG_SERIAL_SCCNXP is not set
# CONFIG_SERIAL_ALTERA_JTAGUART is not set # CONFIG_SERIAL_ALTERA_JTAGUART is not set
# CONFIG_SERIAL_ALTERA_UART is not set # CONFIG_SERIAL_ALTERA_UART is not set
@@ -1636,36 +1633,18 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_RP2 is not set # CONFIG_SERIAL_RP2 is not set
# CONFIG_SERIAL_FSL_LPUART is not set # CONFIG_SERIAL_FSL_LPUART is not set
# CONFIG_SERIAL_FSL_LINFLEXUART is not set # CONFIG_SERIAL_FSL_LINFLEXUART is not set
# CONFIG_SERIAL_SPRD is not set
# end of Serial drivers # end of Serial drivers
CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_ROCKETPORT is not set
# CONFIG_CYCLADES is not set
# CONFIG_MOXA_INTELLIO is not set
# CONFIG_MOXA_SMARTIO is not set
# CONFIG_SYNCLINK is not set
# CONFIG_SYNCLINKMP is not set
# CONFIG_SYNCLINK_GT is not set
# CONFIG_ISI is not set
# CONFIG_N_HDLC is not set
# CONFIG_N_GSM is not set
# CONFIG_NOZOMI is not set
# CONFIG_NULL_TTY is not set
# CONFIG_TRACE_SINK is not set
CONFIG_HVC_DRIVER=y
# CONFIG_SERIAL_DEV_BUS is not set # CONFIG_SERIAL_DEV_BUS is not set
# CONFIG_TTY_PRINTK is not set # CONFIG_TTY_PRINTK is not set
CONFIG_HVC_DRIVER=y
CONFIG_VIRTIO_CONSOLE=y CONFIG_VIRTIO_CONSOLE=y
# CONFIG_IPMI_HANDLER is not set # CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set # CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
# CONFIG_APPLICOM is not set # CONFIG_APPLICOM is not set
# CONFIG_MWAVE is not set # CONFIG_MWAVE is not set
CONFIG_DEVMEM=y
CONFIG_DEVKMEM=y
# CONFIG_NVRAM is not set
# CONFIG_RAW_DRIVER is not set # CONFIG_RAW_DRIVER is not set
CONFIG_DEVPORT=y
CONFIG_HPET=y CONFIG_HPET=y
# CONFIG_HPET_MMAP is not set # CONFIG_HPET_MMAP is not set
# CONFIG_HANGCHECK_TIMER is not set # CONFIG_HANGCHECK_TIMER is not set
@@ -1678,6 +1657,7 @@ CONFIG_TCG_TIS=y
CONFIG_TCG_CRB=y CONFIG_TCG_CRB=y
# CONFIG_TCG_VTPM_PROXY is not set # CONFIG_TCG_VTPM_PROXY is not set
# CONFIG_TELCLOCK is not set # CONFIG_TELCLOCK is not set
CONFIG_DEVPORT=y
# CONFIG_XILLYBUS is not set # CONFIG_XILLYBUS is not set
# end of Character devices # end of Character devices
@@ -1733,7 +1713,6 @@ CONFIG_POWER_SUPPLY=y
# CONFIG_CHARGER_MAX8903 is not set # CONFIG_CHARGER_MAX8903 is not set
# CONFIG_HWMON is not set # CONFIG_HWMON is not set
CONFIG_THERMAL=y CONFIG_THERMAL=y
# CONFIG_THERMAL_NETLINK is not set
# CONFIG_THERMAL_STATISTICS is not set # CONFIG_THERMAL_STATISTICS is not set
CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
CONFIG_THERMAL_WRITABLE_TRIPS=y CONFIG_THERMAL_WRITABLE_TRIPS=y
@@ -1792,7 +1771,6 @@ CONFIG_BCMA_POSSIBLE=y
# CONFIG_REGULATOR is not set # CONFIG_REGULATOR is not set
# CONFIG_RC_CORE is not set # CONFIG_RC_CORE is not set
# CONFIG_MEDIA_CEC_SUPPORT is not set
# CONFIG_MEDIA_SUPPORT is not set # CONFIG_MEDIA_SUPPORT is not set
# #
@@ -1814,6 +1792,11 @@ CONFIG_VGA_ARB_MAX_GPUS=16
# #
# end of ARM devices # end of ARM devices
#
# ACP (Audio CoProcessor) Configuration
#
# end of ACP (Audio CoProcessor) Configuration
# #
# Frame buffer Devices # Frame buffer Devices
# #
@@ -1879,6 +1862,7 @@ CONFIG_FB_VESA=y
# #
# CONFIG_LCD_CLASS_DEVICE is not set # CONFIG_LCD_CLASS_DEVICE is not set
CONFIG_BACKLIGHT_CLASS_DEVICE=y CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_BACKLIGHT_GENERIC=y
# CONFIG_BACKLIGHT_APPLE is not set # CONFIG_BACKLIGHT_APPLE is not set
# CONFIG_BACKLIGHT_QCOM_WLED is not set # CONFIG_BACKLIGHT_QCOM_WLED is not set
# CONFIG_BACKLIGHT_SAHARA is not set # CONFIG_BACKLIGHT_SAHARA is not set
@@ -1938,7 +1922,6 @@ CONFIG_HID_DRAGONRISE=y
CONFIG_HID_EZKEY=y CONFIG_HID_EZKEY=y
# CONFIG_HID_GEMBIRD is not set # CONFIG_HID_GEMBIRD is not set
# CONFIG_HID_GFRM is not set # CONFIG_HID_GFRM is not set
# CONFIG_HID_GLORIOUS is not set
# CONFIG_HID_KEYTOUCH is not set # CONFIG_HID_KEYTOUCH is not set
CONFIG_HID_KYE=y CONFIG_HID_KYE=y
# CONFIG_HID_WALTOP is not set # CONFIG_HID_WALTOP is not set
@@ -2018,7 +2001,6 @@ CONFIG_RTC_MC146818_LIB=y
CONFIG_SYNC_FILE=y CONFIG_SYNC_FILE=y
# CONFIG_SW_SYNC is not set # CONFIG_SW_SYNC is not set
# CONFIG_UDMABUF is not set # CONFIG_UDMABUF is not set
# CONFIG_DMABUF_MOVE_NOTIFY is not set
# CONFIG_DMABUF_SELFTESTS is not set # CONFIG_DMABUF_SELFTESTS is not set
# CONFIG_DMABUF_HEAPS is not set # CONFIG_DMABUF_HEAPS is not set
# end of DMABUF options # end of DMABUF options
@@ -2034,10 +2016,6 @@ CONFIG_VIRTIO_PCI_LEGACY=y
CONFIG_VIRTIO_BALLOON=y CONFIG_VIRTIO_BALLOON=y
# CONFIG_VIRTIO_INPUT is not set # CONFIG_VIRTIO_INPUT is not set
# CONFIG_VIRTIO_MMIO is not set # CONFIG_VIRTIO_MMIO is not set
# CONFIG_VDPA is not set
CONFIG_VHOST_MENU=y
# CONFIG_VHOST_NET is not set
# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set
# #
# Microsoft Hyper-V guest support # Microsoft Hyper-V guest support
@@ -2051,10 +2029,15 @@ CONFIG_PMC_ATOM=y
# CONFIG_MFD_CROS_EC is not set # CONFIG_MFD_CROS_EC is not set
# CONFIG_CHROME_PLATFORMS is not set # CONFIG_CHROME_PLATFORMS is not set
# CONFIG_MELLANOX_PLATFORM is not set # CONFIG_MELLANOX_PLATFORM is not set
CONFIG_HAVE_CLK=y
CONFIG_CLKDEV_LOOKUP=y CONFIG_CLKDEV_LOOKUP=y
CONFIG_HAVE_CLK_PREPARE=y CONFIG_HAVE_CLK_PREPARE=y
CONFIG_COMMON_CLK=y CONFIG_COMMON_CLK=y
#
# Common Clock Framework
#
# end of Common Clock Framework
# CONFIG_HWSPINLOCK is not set # CONFIG_HWSPINLOCK is not set
# #
@@ -2248,13 +2231,12 @@ CONFIG_INOTIFY_USER=y
# end of CD-ROM/DVD Filesystems # end of CD-ROM/DVD Filesystems
# #
# DOS/FAT/EXFAT/NT Filesystems # DOS/FAT/NT Filesystems
# #
# CONFIG_MSDOS_FS is not set # CONFIG_MSDOS_FS is not set
# CONFIG_VFAT_FS is not set # CONFIG_VFAT_FS is not set
# CONFIG_EXFAT_FS is not set
# CONFIG_NTFS_FS is not set # CONFIG_NTFS_FS is not set
# end of DOS/FAT/EXFAT/NT Filesystems # end of DOS/FAT/NT Filesystems
# #
# Pseudo filesystems # Pseudo filesystems
@@ -2270,7 +2252,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y CONFIG_TMPFS_POSIX_ACL=y
CONFIG_TMPFS_XATTR=y CONFIG_TMPFS_XATTR=y
# CONFIG_TMPFS_INODE64 is not set
CONFIG_HUGETLBFS=y CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y CONFIG_HUGETLB_PAGE=y
CONFIG_MEMFD_CREATE=y CONFIG_MEMFD_CREATE=y
@@ -2351,6 +2332,7 @@ CONFIG_IO_WQ=y
CONFIG_KEYS=y CONFIG_KEYS=y
# CONFIG_KEYS_REQUEST_CACHE is not set # CONFIG_KEYS_REQUEST_CACHE is not set
# CONFIG_PERSISTENT_KEYRINGS is not set # CONFIG_PERSISTENT_KEYRINGS is not set
# CONFIG_BIG_KEYS is not set
# CONFIG_TRUSTED_KEYS is not set # CONFIG_TRUSTED_KEYS is not set
# CONFIG_ENCRYPTED_KEYS is not set # CONFIG_ENCRYPTED_KEYS is not set
# CONFIG_KEY_DH_OPERATIONS is not set # CONFIG_KEY_DH_OPERATIONS is not set
@@ -2361,19 +2343,10 @@ CONFIG_SECURITY_NETWORK=y
CONFIG_PAGE_TABLE_ISOLATION=y CONFIG_PAGE_TABLE_ISOLATION=y
# CONFIG_SECURITY_NETWORK_XFRM is not set # CONFIG_SECURITY_NETWORK_XFRM is not set
# CONFIG_SECURITY_PATH is not set # CONFIG_SECURITY_PATH is not set
CONFIG_LSM_MMAP_MIN_ADDR=65536
CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
# CONFIG_HARDENED_USERCOPY is not set # CONFIG_HARDENED_USERCOPY is not set
# CONFIG_FORTIFY_SOURCE is not set # CONFIG_FORTIFY_SOURCE is not set
# CONFIG_STATIC_USERMODEHELPER is not set # CONFIG_STATIC_USERMODEHELPER is not set
CONFIG_SECURITY_SELINUX=y
# CONFIG_SECURITY_SELINUX_BOOTPARAM is not set
# CONFIG_SECURITY_SELINUX_DISABLE is not set
CONFIG_SECURITY_SELINUX_DEVELOP=y
CONFIG_SECURITY_SELINUX_AVC_STATS=y
CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=0
CONFIG_SECURITY_SELINUX_SIDTAB_HASH_BITS=9
CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE=256
# CONFIG_SECURITY_SMACK is not set # CONFIG_SECURITY_SMACK is not set
# CONFIG_SECURITY_TOMOYO is not set # CONFIG_SECURITY_TOMOYO is not set
# CONFIG_SECURITY_APPARMOR is not set # CONFIG_SECURITY_APPARMOR is not set
@@ -2383,10 +2356,8 @@ CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE=256
# CONFIG_SECURITY_LOCKDOWN_LSM is not set # CONFIG_SECURITY_LOCKDOWN_LSM is not set
CONFIG_INTEGRITY=y CONFIG_INTEGRITY=y
# CONFIG_INTEGRITY_SIGNATURE is not set # CONFIG_INTEGRITY_SIGNATURE is not set
CONFIG_INTEGRITY_AUDIT=y
CONFIG_IMA=y CONFIG_IMA=y
CONFIG_IMA_MEASURE_PCR_IDX=10 CONFIG_IMA_MEASURE_PCR_IDX=10
CONFIG_IMA_LSM_RULES=y
# CONFIG_IMA_TEMPLATE is not set # CONFIG_IMA_TEMPLATE is not set
CONFIG_IMA_NG_TEMPLATE=y CONFIG_IMA_NG_TEMPLATE=y
# CONFIG_IMA_SIG_TEMPLATE is not set # CONFIG_IMA_SIG_TEMPLATE is not set
@@ -2394,16 +2365,17 @@ CONFIG_IMA_DEFAULT_TEMPLATE="ima-ng"
CONFIG_IMA_DEFAULT_HASH_SHA1=y CONFIG_IMA_DEFAULT_HASH_SHA1=y
# CONFIG_IMA_DEFAULT_HASH_SHA256 is not set # CONFIG_IMA_DEFAULT_HASH_SHA256 is not set
CONFIG_IMA_DEFAULT_HASH="sha1" CONFIG_IMA_DEFAULT_HASH="sha1"
CONFIG_IMA_WRITE_POLICY=y # CONFIG_IMA_WRITE_POLICY is not set
CONFIG_IMA_READ_POLICY=y # CONFIG_IMA_READ_POLICY is not set
# CONFIG_IMA_APPRAISE is not set # CONFIG_IMA_APPRAISE is not set
CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS=y CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS=y
CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS=y CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS=y
# CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT is not set
# CONFIG_EVM is not set # CONFIG_EVM is not set
# CONFIG_DEFAULT_SECURITY_SELINUX is not set
CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_DEFAULT_SECURITY_DAC=y
CONFIG_LSM="selinux,bpf,integrity" CONFIG_LSM="selinux,bpf"
CONFIG_BPF_LSM=y
CONFIG_AUDIT=y
CONFIG_SECURITY_SELINUX=y
# #
# Kernel hardening options # Kernel hardening options
@@ -2651,13 +2623,11 @@ CONFIG_GENERIC_STRNLEN_USER=y
CONFIG_GENERIC_NET_UTILS=y CONFIG_GENERIC_NET_UTILS=y
CONFIG_GENERIC_FIND_FIRST_BIT=y CONFIG_GENERIC_FIND_FIRST_BIT=y
# CONFIG_CORDIC is not set # CONFIG_CORDIC is not set
# CONFIG_PRIME_NUMBERS is not set
CONFIG_RATIONAL=y CONFIG_RATIONAL=y
CONFIG_GENERIC_PCI_IOMAP=y CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_IOMAP=y CONFIG_GENERIC_IOMAP=y
CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
CONFIG_ARCH_HAS_FAST_MULTIPLIER=y CONFIG_ARCH_HAS_FAST_MULTIPLIER=y
CONFIG_ARCH_USE_SYM_ANNOTATIONS=y
CONFIG_CRC_CCITT=y CONFIG_CRC_CCITT=y
CONFIG_CRC16=y CONFIG_CRC16=y
CONFIG_CRC_T10DIF=y CONFIG_CRC_T10DIF=y
@@ -2678,7 +2648,6 @@ CONFIG_XXHASH=y
CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_INFLATE=y
CONFIG_LZO_DECOMPRESS=y CONFIG_LZO_DECOMPRESS=y
CONFIG_LZ4_DECOMPRESS=y CONFIG_LZ4_DECOMPRESS=y
CONFIG_ZSTD_DECOMPRESS=y
CONFIG_XZ_DEC=y CONFIG_XZ_DEC=y
CONFIG_XZ_DEC_X86=y CONFIG_XZ_DEC_X86=y
# CONFIG_XZ_DEC_POWERPC is not set # CONFIG_XZ_DEC_POWERPC is not set
@@ -2694,14 +2663,12 @@ CONFIG_DECOMPRESS_LZMA=y
CONFIG_DECOMPRESS_XZ=y CONFIG_DECOMPRESS_XZ=y
CONFIG_DECOMPRESS_LZO=y CONFIG_DECOMPRESS_LZO=y
CONFIG_DECOMPRESS_LZ4=y CONFIG_DECOMPRESS_LZ4=y
CONFIG_DECOMPRESS_ZSTD=y
CONFIG_GENERIC_ALLOCATOR=y CONFIG_GENERIC_ALLOCATOR=y
CONFIG_XARRAY_MULTI=y CONFIG_XARRAY_MULTI=y
CONFIG_ASSOCIATIVE_ARRAY=y CONFIG_ASSOCIATIVE_ARRAY=y
CONFIG_HAS_IOMEM=y CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT_MAP=y CONFIG_HAS_IOPORT_MAP=y
CONFIG_HAS_DMA=y CONFIG_HAS_DMA=y
CONFIG_DMA_OPS=y
CONFIG_NEED_SG_DMA_LENGTH=y CONFIG_NEED_SG_DMA_LENGTH=y
CONFIG_NEED_DMA_MAP_STATE=y CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_ARCH_DMA_ADDR_T_64BIT=y CONFIG_ARCH_DMA_ADDR_T_64BIT=y
@@ -2769,7 +2736,6 @@ CONFIG_CONSOLE_LOGLEVEL_QUIET=4
CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
# CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_DYNAMIC_DEBUG is not set # CONFIG_DYNAMIC_DEBUG is not set
# CONFIG_DYNAMIC_DEBUG_CORE is not set
CONFIG_SYMBOLIC_ERRNAME=y CONFIG_SYMBOLIC_ERRNAME=y
CONFIG_DEBUG_BUGVERBOSE=y CONFIG_DEBUG_BUGVERBOSE=y
# end of printk and dmesg options # end of printk and dmesg options
@@ -2779,7 +2745,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
# #
CONFIG_DEBUG_INFO=y CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_INFO_REDUCED is not set # CONFIG_DEBUG_INFO_REDUCED is not set
# CONFIG_DEBUG_INFO_COMPRESSED is not set
# CONFIG_DEBUG_INFO_SPLIT is not set # CONFIG_DEBUG_INFO_SPLIT is not set
# CONFIG_DEBUG_INFO_DWARF4 is not set # CONFIG_DEBUG_INFO_DWARF4 is not set
CONFIG_DEBUG_INFO_BTF=y CONFIG_DEBUG_INFO_BTF=y
@@ -2789,9 +2754,9 @@ CONFIG_FRAME_WARN=2048
# CONFIG_STRIP_ASM_SYMS is not set # CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_READABLE_ASM is not set # CONFIG_READABLE_ASM is not set
# CONFIG_HEADERS_INSTALL is not set # CONFIG_HEADERS_INSTALL is not set
CONFIG_OPTIMIZE_INLINING=y
# CONFIG_DEBUG_SECTION_MISMATCH is not set # CONFIG_DEBUG_SECTION_MISMATCH is not set
CONFIG_SECTION_MISMATCH_WARN_ONLY=y CONFIG_SECTION_MISMATCH_WARN_ONLY=y
# CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_32B is not set
CONFIG_STACK_VALIDATION=y CONFIG_STACK_VALIDATION=y
# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
# end of Compile-time checks and compiler options # end of Compile-time checks and compiler options
@@ -2802,15 +2767,12 @@ CONFIG_STACK_VALIDATION=y
CONFIG_MAGIC_SYSRQ=y CONFIG_MAGIC_SYSRQ=y
CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
CONFIG_MAGIC_SYSRQ_SERIAL=y CONFIG_MAGIC_SYSRQ_SERIAL=y
CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE=""
CONFIG_DEBUG_FS=y CONFIG_DEBUG_FS=y
CONFIG_DEBUG_FS_ALLOW_ALL=y
# CONFIG_DEBUG_FS_DISALLOW_MOUNT is not set
# CONFIG_DEBUG_FS_ALLOW_NONE is not set
CONFIG_HAVE_ARCH_KGDB=y CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set # CONFIG_KGDB is not set
CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y
# CONFIG_UBSAN is not set # CONFIG_UBSAN is not set
CONFIG_UBSAN_ALIGNMENT=y
# end of Generic Kernel Debugging Instruments # end of Generic Kernel Debugging Instruments
CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_KERNEL=y
@@ -2825,8 +2787,6 @@ CONFIG_DEBUG_MISC=y
# CONFIG_PAGE_POISONING is not set # CONFIG_PAGE_POISONING is not set
# CONFIG_DEBUG_PAGE_REF is not set # CONFIG_DEBUG_PAGE_REF is not set
# CONFIG_DEBUG_RODATA_TEST is not set # CONFIG_DEBUG_RODATA_TEST is not set
CONFIG_ARCH_HAS_DEBUG_WX=y
# CONFIG_DEBUG_WX is not set
CONFIG_GENERIC_PTDUMP=y CONFIG_GENERIC_PTDUMP=y
# CONFIG_PTDUMP_DEBUGFS is not set # CONFIG_PTDUMP_DEBUGFS is not set
# CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_OBJECTS is not set
@@ -2836,16 +2796,14 @@ CONFIG_HAVE_DEBUG_KMEMLEAK=y
# CONFIG_DEBUG_KMEMLEAK is not set # CONFIG_DEBUG_KMEMLEAK is not set
# CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_STACK_USAGE is not set
CONFIG_SCHED_STACK_END_CHECK=y CONFIG_SCHED_STACK_END_CHECK=y
CONFIG_ARCH_HAS_DEBUG_VM_PGTABLE=y
# CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_VM_PGTABLE is not set
CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
# CONFIG_DEBUG_VIRTUAL is not set # CONFIG_DEBUG_VIRTUAL is not set
CONFIG_DEBUG_MEMORY_INIT=y CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_DEBUG_PER_CPU_MAPS is not set # CONFIG_DEBUG_PER_CPU_MAPS is not set
CONFIG_HAVE_ARCH_KASAN=y CONFIG_HAVE_ARCH_KASAN=y
CONFIG_HAVE_ARCH_KASAN_VMALLOC=y CONFIG_HAVE_ARCH_KASAN_VMALLOC=y
CONFIG_CC_HAS_KASAN_GENERIC=y CONFIG_KASAN_STACK=1
# end of Memory Debugging # end of Memory Debugging
# CONFIG_DEBUG_SHIRQ is not set # CONFIG_DEBUG_SHIRQ is not set
@@ -2870,7 +2828,6 @@ CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120
# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
# CONFIG_WQ_WATCHDOG is not set # CONFIG_WQ_WATCHDOG is not set
# CONFIG_TEST_LOCKUP is not set
# end of Debug Oops, Lockups and Hangs # end of Debug Oops, Lockups and Hangs
# #
@@ -2889,7 +2846,6 @@ CONFIG_DEBUG_PREEMPT=y
# #
CONFIG_LOCK_DEBUGGING_SUPPORT=y CONFIG_LOCK_DEBUGGING_SUPPORT=y
CONFIG_PROVE_LOCKING=y CONFIG_PROVE_LOCKING=y
# CONFIG_PROVE_RAW_LOCK_NESTING is not set
# CONFIG_LOCK_STAT is not set # CONFIG_LOCK_STAT is not set
CONFIG_DEBUG_RT_MUTEXES=y CONFIG_DEBUG_RT_MUTEXES=y
CONFIG_DEBUG_SPINLOCK=y CONFIG_DEBUG_SPINLOCK=y
@@ -2906,7 +2862,6 @@ CONFIG_DEBUG_ATOMIC_SLEEP=y
# end of Lock Debugging (spinlocks, mutexes, etc...) # end of Lock Debugging (spinlocks, mutexes, etc...)
CONFIG_TRACE_IRQFLAGS=y CONFIG_TRACE_IRQFLAGS=y
CONFIG_TRACE_IRQFLAGS_NMI=y
CONFIG_STACKTRACE=y CONFIG_STACKTRACE=y
# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set # CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set
# CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_KOBJECT is not set
@@ -2929,7 +2884,6 @@ CONFIG_DEBUG_CREDENTIALS=y
CONFIG_PROVE_RCU=y CONFIG_PROVE_RCU=y
# CONFIG_RCU_PERF_TEST is not set # CONFIG_RCU_PERF_TEST is not set
# CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_REF_SCALE_TEST is not set
CONFIG_RCU_CPU_STALL_TIMEOUT=60 CONFIG_RCU_CPU_STALL_TIMEOUT=60
# CONFIG_RCU_TRACE is not set # CONFIG_RCU_TRACE is not set
# CONFIG_RCU_EQS_DEBUG is not set # CONFIG_RCU_EQS_DEBUG is not set
@@ -2967,6 +2921,7 @@ CONFIG_DYNAMIC_FTRACE_WITH_REGS=y
CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y
# CONFIG_FUNCTION_PROFILER is not set # CONFIG_FUNCTION_PROFILER is not set
# CONFIG_STACK_TRACER is not set # CONFIG_STACK_TRACER is not set
# CONFIG_PREEMPTIRQ_EVENTS is not set
# CONFIG_IRQSOFF_TRACER is not set # CONFIG_IRQSOFF_TRACER is not set
# CONFIG_PREEMPT_TRACER is not set # CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set # CONFIG_SCHED_TRACER is not set
@@ -2986,7 +2941,6 @@ CONFIG_DYNAMIC_EVENTS=y
CONFIG_PROBE_EVENTS=y CONFIG_PROBE_EVENTS=y
CONFIG_BPF_KPROBE_OVERRIDE=y CONFIG_BPF_KPROBE_OVERRIDE=y
CONFIG_FTRACE_MCOUNT_RECORD=y CONFIG_FTRACE_MCOUNT_RECORD=y
# CONFIG_SYNTH_EVENTS is not set
# CONFIG_HIST_TRIGGERS is not set # CONFIG_HIST_TRIGGERS is not set
# CONFIG_TRACE_EVENT_INJECT is not set # CONFIG_TRACE_EVENT_INJECT is not set
# CONFIG_TRACEPOINT_BENCHMARK is not set # CONFIG_TRACEPOINT_BENCHMARK is not set
@@ -2998,7 +2952,6 @@ CONFIG_FTRACE_MCOUNT_RECORD=y
# CONFIG_KPROBE_EVENT_GEN_TEST is not set # CONFIG_KPROBE_EVENT_GEN_TEST is not set
# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set # CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
# CONFIG_SAMPLES is not set # CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KCSAN=y
CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
# CONFIG_STRICT_DEVMEM is not set # CONFIG_STRICT_DEVMEM is not set
@@ -3006,12 +2959,13 @@ CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
# x86 Debugging # x86 Debugging
# #
CONFIG_TRACE_IRQFLAGS_SUPPORT=y CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y
CONFIG_X86_VERBOSE_BOOTUP=y CONFIG_X86_VERBOSE_BOOTUP=y
CONFIG_EARLY_PRINTK=y CONFIG_EARLY_PRINTK=y
# CONFIG_EARLY_PRINTK_DBGP is not set # CONFIG_EARLY_PRINTK_DBGP is not set
# CONFIG_EARLY_PRINTK_USB_XDBC is not set # CONFIG_EARLY_PRINTK_USB_XDBC is not set
# CONFIG_EFI_PGT_DUMP is not set # CONFIG_EFI_PGT_DUMP is not set
# CONFIG_DEBUG_WX is not set
CONFIG_DOUBLEFAULT=y
# CONFIG_DEBUG_TLBFLUSH is not set # CONFIG_DEBUG_TLBFLUSH is not set
# CONFIG_IOMMU_DEBUG is not set # CONFIG_IOMMU_DEBUG is not set
CONFIG_HAVE_MMIOTRACE_SUPPORT=y CONFIG_HAVE_MMIOTRACE_SUPPORT=y
@@ -3038,16 +2992,9 @@ CONFIG_UNWINDER_ORC=y
# CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_NOTIFIER_ERROR_INJECTION is not set
CONFIG_FUNCTION_ERROR_INJECTION=y CONFIG_FUNCTION_ERROR_INJECTION=y
CONFIG_FAULT_INJECTION=y CONFIG_FAULT_INJECTION=y
# CONFIG_FAILSLAB is not set
# CONFIG_FAIL_PAGE_ALLOC is not set
# CONFIG_FAIL_MAKE_REQUEST is not set
# CONFIG_FAIL_IO_TIMEOUT is not set
# CONFIG_FAIL_FUTEX is not set
CONFIG_FAULT_INJECTION_DEBUG_FS=y CONFIG_FAULT_INJECTION_DEBUG_FS=y
CONFIG_FAIL_FUNCTION=y CONFIG_FAIL_FUNCTION=y
CONFIG_ARCH_HAS_KCOV=y CONFIG_ARCH_HAS_KCOV=y
CONFIG_CC_HAS_SANCOV_TRACE_PC=y
# CONFIG_KCOV is not set
# CONFIG_RUNTIME_TESTING_MENU is not set # CONFIG_RUNTIME_TESTING_MENU is not set
# CONFIG_MEMTEST is not set # CONFIG_MEMTEST is not set
# end of Kernel Testing and Coverage # end of Kernel Testing and Coverage

View File

@@ -1,7 +0,0 @@
# btf_dump -- need to disable data dump sub-tests
core_retro
cpu_mask
hashmap
perf_buffer
section_names

View File

@@ -1,55 +0,0 @@
attach_probe
autoload
bpf_verif_scale
cgroup_attach_autodetach
cgroup_attach_override
core_autosize
core_extern
core_read_macros
core_reloc
core_retro
cpu_mask
endian
fexit_stress
get_branch_snapshot
get_stackid_cannot_attach
global_data
global_data_init
global_func_args
hashmap
l4lb_all
linked_funcs
linked_maps
map_lock
obj_name
perf_buffer
perf_event_stackmap
pinning
pkt_md_access
probe_user
queue_stack_map
raw_tp_writable_reject_nbd_invalid
raw_tp_writable_test_run
rdonly_maps
section_names
signal_pending
skeleton
sockmap_ktls
sockopt
sockopt_inherit
sockopt_multi
spinlock
stacktrace_map
stacktrace_map_raw_tp
static_linked
subprogs
task_fd_query_rawtp
task_fd_query_tp
tc_bpf
tcp_estats
tcp_rtt
tp_attach_query
xdp
xdp_info
xdp_noinline
xdp_perf

View File

@@ -1,24 +0,0 @@
# $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
}

View File

@@ -81,7 +81,6 @@ packages=(
binutils binutils
elfutils elfutils
glibc glibc
iproute2
# selftests test_verifier dependencies. # selftests test_verifier dependencies.
libcap libcap
) )
@@ -102,6 +101,15 @@ rm -rf "$root/usr/share/{doc,help,man,texinfo}"
chroot "${root}" /bin/busybox --install chroot "${root}" /bin/busybox --install
cat > "$root/etc/fstab" << "EOF"
dev /dev devtmpfs rw,nosuid 0 0
proc /proc proc rw,nosuid,nodev,noexec 0 0
sys /sys sysfs rw,nosuid,nodev,noexec 0 0
debugfs /sys/kernel/debug debugfs mode=755,realtime 0 0
bpffs /sys/fs/bpf bpf realtime 0 0
EOF
chmod 644 "$root/etc/fstab"
cat > "$root/etc/inittab" << "EOF" cat > "$root/etc/inittab" << "EOF"
::sysinit:/etc/init.d/rcS ::sysinit:/etc/init.d/rcS
::ctrlaltdel:/sbin/reboot ::ctrlaltdel:/sbin/reboot
@@ -115,29 +123,13 @@ mkdir -m 755 "$root/etc/init.d" "$root/etc/rcS.d"
cat > "$root/etc/rcS.d/S10-mount" << "EOF" cat > "$root/etc/rcS.d/S10-mount" << "EOF"
#!/bin/sh #!/bin/sh
set -eux /bin/mount -a
/bin/mount proc /proc -t proc
# Mount devtmpfs if not mounted
if [[ -z $(/bin/mount -l -t devtmpfs) ]]; then
/bin/mount devtmpfs /dev -t devtmpfs
fi
/bin/mount sysfs /sys -t sysfs
/bin/mount bpffs /sys/fs/bpf -t bpf
/bin/mount debugfs /sys/kernel/debug -t debugfs
echo 'Listing currently mounted file systems'
/bin/mount
EOF EOF
chmod 755 "$root/etc/rcS.d/S10-mount" chmod 755 "$root/etc/rcS.d/S10-mount"
cat > "$root/etc/rcS.d/S40-network" << "EOF" cat > "$root/etc/rcS.d/S40-network" << "EOF"
#!/bin/sh #!/bin/sh
set -eux
ip link set lo up ip link set lo up
EOF EOF
chmod 755 "$root/etc/rcS.d/S40-network" chmod 755 "$root/etc/rcS.d/S40-network"
@@ -145,8 +137,6 @@ chmod 755 "$root/etc/rcS.d/S40-network"
cat > "$root/etc/init.d/rcS" << "EOF" cat > "$root/etc/init.d/rcS" << "EOF"
#!/bin/sh #!/bin/sh
set -eux
for path in /etc/rcS.d/S*; do for path in /etc/rcS.d/S*; do
[ -x "$path" ] && "$path" [ -x "$path" ] && "$path"
done done

View File

@@ -1,3 +0,0 @@
#!/bin/bash
printf "all:\n\ttouch bpf_testmod.ko\n\nclean:\n" > bpf_testmod/Makefile

View File

@@ -1,3 +1,12 @@
#!/bin/bash #!/bin/bash
printf "all:\n\ttouch bpf_testmod.ko\n\nclean:\n" > bpf_testmod/Makefile set -euxo pipefail
# these tests expect vmlinux.h to have latest defiition of bpf_devmap_val xdp_md->egress_ifindex
rm progs/test_xdp_with_devmap_helpers.c
rm progs/test_xdp_devmap_helpers.c
rm prog_tests/xdp_devmap_attach.c
# no BPF_F_NO_PREALLOC in BTF and no sk_msg_md->sk field
rm progs/test_skmsg_load_helpers.c
rm prog_tests/sockmap_basic.c

View File

@@ -1,21 +1,14 @@
#!/bin/bash #!/bin/bash
set -eu set -eux
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 if [[ "${KERNEL}" = 'LATEST' ]]; then
travis_fold start build_kernel "Kernel build"
cp ${VMTEST_ROOT}/configs/latest.config .config cp ${VMTEST_ROOT}/configs/latest.config .config
make -j $((4*$(nproc))) olddefconfig all >/dev/null make -j $((4*$(nproc))) olddefconfig all
travis_fold end build_kernel
fi fi

View File

@@ -3,8 +3,6 @@
set -uo pipefail set -uo pipefail
trap 'exit 2' ERR trap 'exit 2' ERR
source $(cd $(dirname $0) && pwd)/helpers.sh
usage () { usage () {
USAGE_STRING="usage: $0 [-k KERNELRELEASE|-b DIR] [[-r ROOTFSVERSION] [-fo]|-I] [-Si] [-d DIR] IMG USAGE_STRING="usage: $0 [-k KERNELRELEASE|-b DIR] [[-r ROOTFSVERSION] [-fo]|-I] [-Si] [-d DIR] IMG
$0 [-k KERNELRELEASE] -l $0 [-k KERNELRELEASE] -l
@@ -92,12 +90,6 @@ SKIPSOURCE=0
APPEND="" APPEND=""
DIR="$PWD" DIR="$PWD"
LIST=0 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 while true; do
case "$1" in case "$1" in
-k|--kernel) -k|--kernel)
@@ -283,10 +275,6 @@ if [[ $SKIPIMG -eq 0 && ! -v ROOTFSVERSION ]]; then
fi fi
echo "Kernel release: $KERNELRELEASE" >&2 echo "Kernel release: $KERNELRELEASE" >&2
echo
travis_fold start vmlinux_setup "Preparing Linux image"
if (( SKIPIMG )); then if (( SKIPIMG )); then
echo "Not extracting root filesystem" >&2 echo "Not extracting root filesystem" >&2
else else
@@ -378,40 +366,25 @@ else
sudo chmod 644 "$vmlinux" sudo chmod 644 "$vmlinux"
fi fi
travis_fold end vmlinux_setup
REPO_PATH="${SELFTEST_REPO_PATH:-travis-ci/vmtest/bpf-next}"
LIBBPF_PATH="${REPO_ROOT}" \ LIBBPF_PATH="${REPO_ROOT}" \
REPO_PATH="travis-ci/vmtest/bpf-next" \
VMTEST_ROOT="${VMTEST_ROOT}" \ VMTEST_ROOT="${VMTEST_ROOT}" \
REPO_PATH="${REPO_PATH}" \
VMLINUX_BTF=${vmlinux} ${VMTEST_ROOT}/build_selftests.sh 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 if (( SKIPSOURCE )); then
echo "Not copying source files..." >&2 echo "Not copying source files..." >&2
else else
echo "Copying source files..." >&2 echo "Copying source files..." >&2
# Copy the source files in. # Copy the source files in.
sudo mkdir -p -m 0755 "$mnt/${PROJECT_NAME}" sudo mkdir -p -m 0755 "$mnt/${PROJECT_NAME}"
if [[ "${SOURCE_FULLCOPY}" == "1" ]]; then {
git ls-files -z | sudo rsync --files-from=- -0cpt . "$mnt/${PROJECT_NAME}" if [[ -e .git ]]; then
git ls-files -z
else else
sudo mkdir -p -m 0755 ${mnt}/${PROJECT_NAME}/{selftests,travis-ci} tr '\n' '\0' < "${PROJECT_NAME}.egg-info/SOURCES.txt"
tree --du -shaC "${REPO_ROOT}/selftests/bpf" fi
sudo rsync -avm "${REPO_ROOT}/selftests/bpf" "$mnt/${PROJECT_NAME}/selftests/" } | sudo rsync --files-from=- -0cpt . "$mnt/${PROJECT_NAME}"
sudo rsync -avm "${REPO_ROOT}/travis-ci/vmtest" "$mnt/${PROJECT_NAME}/travis-ci/"
fi
fi fi
setup_script="#!/bin/sh setup_script="#!/bin/sh
@@ -428,41 +401,32 @@ if [[ ! -z SETUPCMD ]]; then
if [[ -v BUILDDIR ]]; then kernel='latest'; fi if [[ -v BUILDDIR ]]; then kernel='latest'; fi
setup_envvars="export KERNEL=${kernel}" setup_envvars="export KERNEL=${kernel}"
setup_script=$(printf "#!/bin/sh setup_script=$(printf "#!/bin/sh
set -eux set -e
echo 'Running setup commands' echo 'Running setup commands'
%s %s
set +e; %s; exitstatus=\$?; set -e %s
echo \$exitstatus > /exitstatus echo $? > /exitstatus
chmod 644 /exitstatus" "${setup_envvars}" "${setup_cmd}") chmod 644 /exitstatus" "${setup_envvars}" "${setup_cmd}")
fi fi
echo "${setup_script}" | sudo tee "$mnt/etc/rcS.d/S50-run-tests" > /dev/null echo "${setup_script}" | sudo tee "$mnt/etc/rcS.d/S50-run-tests" > /dev/null
sudo chmod 755 "$mnt/etc/rcS.d/S50-run-tests" sudo chmod 755 "$mnt/etc/rcS.d/S50-run-tests"
fold_shutdown="$(travis_fold start shutdown)"
poweroff_script="#!/bin/sh poweroff_script="#!/bin/sh
echo ${fold_shutdown}
echo -e '\033[1;33mShutdown\033[0m\n'
poweroff" poweroff"
echo "${poweroff_script}" | sudo tee "$mnt/etc/rcS.d/S99-poweroff" > /dev/null echo "${poweroff_script}" | sudo tee "$mnt/etc/rcS.d/S99-poweroff" > /dev/null
sudo chmod 755 "$mnt/etc/rcS.d/S99-poweroff" sudo chmod 755 "$mnt/etc/rcS.d/S99-poweroff"
sudo umount "$mnt" sudo umount "$mnt"
echo "Starting VM with $(nproc) CPUs..." echo "Starting virtual machine..." >&2
qemu-system-x86_64 -nodefaults -display none -serial mon:stdio \
-cpu kvm64 -enable-kvm -smp "$(nproc)" -m 2G \
-drive file="$IMG",format=raw,index=1,media=disk,if=virtio,cache=none \
-kernel "$vmlinuz" -append "root=/dev/vda rw console=ttyS0,115200$APPEND"
if kvm-ok ; then
accel="-cpu kvm64 -enable-kvm"
else
accel="-cpu qemu64 -machine accel=tcg"
fi
qemu-system-x86_64 -nodefaults -display none -serial mon:stdio -no-reboot \
${accel} -smp "$(nproc)" -m 4G \
-drive file="$IMG",format=raw,index=1,media=disk,if=virtio,cache=none \
-kernel "$vmlinuz" -append "root=/dev/vda rw console=ttyS0,115200 kernel.panic=-1 $APPEND"
sudo mount -o loop "$IMG" "$mnt" sudo mount -o loop "$IMG" "$mnt"
if exitstatus="$(cat "$mnt/exitstatus" 2>/dev/null)"; then if exitstatus="$(cat "$mnt/exitstatus" 2>/dev/null)"; then
printf '\nTests exit status: %s\n' "$exitstatus" >&2 printf '\nTests exit status: %s\n' "$exitstatus" >&2
@@ -471,7 +435,4 @@ else
exitstatus=1 exitstatus=1
fi fi
sudo umount "$mnt" sudo umount "$mnt"
travis_fold end shutdown
exit "$exitstatus" exit "$exitstatus"

View File

@@ -1,35 +1,23 @@
#!/bin/bash #!/bin/bash
set -euo pipefail set -euxo pipefail
source $(cd $(dirname $0) && pwd)/helpers.sh
test_progs() { test_progs() {
if [[ "${KERNEL}" != '4.9.0' ]]; then echo TEST_PROGS
travis_fold start test_progs "Testing test_progs" ./test_progs ${BLACKLIST:+-b$BLACKLIST} ${WHITELIST:+-t$WHITELIST}
./test_progs ${BLACKLIST:+-d$BLACKLIST} ${WHITELIST:+-a$WHITELIST}
travis_fold end test_progs
fi
travis_fold start test_progs-no_alu32 "Testing test_progs-no_alu32"
./test_progs-no_alu32 ${BLACKLIST:+-d$BLACKLIST} ${WHITELIST:+-a$WHITELIST}
travis_fold end test_progs-no_alu32
} }
test_maps() { test_maps() {
travis_fold start test_maps "Testing test_maps" echo TEST_MAPS
# Allow failing on older kernels.
./test_maps ./test_maps
travis_fold end test_maps
} }
test_verifier() { test_verifier() {
travis_fold start test_verifier "Testing test_verifier" echo TEST_VERIFIER
./test_verifier ./test_verifier
travis_fold end test_verifier
} }
travis_fold end vm_init
configs_path='libbpf/travis-ci/vmtest/configs' configs_path='libbpf/travis-ci/vmtest/configs'
blacklist_path="$configs_path/blacklist/BLACKLIST-${KERNEL}" blacklist_path="$configs_path/blacklist/BLACKLIST-${KERNEL}"
if [[ -s "${blacklist_path}" ]]; then if [[ -s "${blacklist_path}" ]]; then
@@ -46,6 +34,6 @@ cd libbpf/selftests/bpf
test_progs test_progs
if [[ "${KERNEL}" == 'latest' ]]; then if [[ "${KERNEL}" == 'latest' ]]; then
# test_maps test_maps
test_verifier test_verifier
fi fi

View File

@@ -1,39 +1,22 @@
#!/bin/bash #!/bin/bash
set -eu set -eux
source $(cd $(dirname $0) && pwd)/helpers.sh VMTEST_SETUPCMD="PROJECT_NAME=${PROJECT_NAME} ./${PROJECT_NAME}/travis-ci/vmtest/run_selftests.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 "KERNEL: $KERNEL"
echo
# Build latest pahole # Build latest pahole
${VMTEST_ROOT}/build_pahole.sh travis-ci/vmtest/pahole ${VMTEST_ROOT}/build_pahole.sh travis-ci/vmtest/pahole
travis_fold start install_clang "Installing Clang/LLVM" # Install required packages
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo add-apt-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal main" echo "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main" | sudo tee -a /etc/apt/sources.list
sudo apt-get update sudo apt-get -qq update
sudo apt-get install --allow-downgrades -y libc6=2.31-0ubuntu9.2 sudo apt-get -qq -y install clang lld llvm
sudo aptitude install -y g++ libelf-dev
sudo aptitude install -y clang-14 lld-14 llvm-14
travis_fold end install_clang
# Build selftests (and latest kernel, if necessary) # Build selftests (and latest kernel, if necessary)
KERNEL="${KERNEL}" ${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. # Escape whitespace characters.
setup_cmd=$(sed 's/\([[:space:]]\)/\\\1/g' <<< "${VMTEST_SETUPCMD}") setup_cmd=$(sed 's/\([[:space:]]\)/\\\1/g' <<< "${VMTEST_SETUPCMD}")
@@ -41,11 +24,7 @@ setup_cmd=$(sed 's/\([[:space:]]\)/\\\1/g' <<< "${VMTEST_SETUPCMD}")
sudo adduser "${USER}" kvm sudo adduser "${USER}" kvm
if [[ "${KERNEL}" = 'LATEST' ]]; then if [[ "${KERNEL}" = 'LATEST' ]]; then
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;
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 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 fi

File diff suppressed because it is too large Load Diff