mirror of
https://github.com/netdata/libbpf.git
synced 2026-03-20 00:09:06 +08:00
Compare commits
289 Commits
detached
...
netdata_pa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
85d9be97eb | ||
|
|
fddf93d20b | ||
|
|
ed6bb65cf1 | ||
|
|
5ee8863eaf | ||
|
|
adde4f55b7 | ||
|
|
977b1f820c | ||
|
|
5d02120e10 | ||
|
|
8a090ef1e5 | ||
|
|
ad9c763445 | ||
|
|
1c96b72cb0 | ||
|
|
b7c6c02b5f | ||
|
|
2c5038dcf4 | ||
|
|
dc8673b28b | ||
|
|
a6d7ceaaeb | ||
|
|
e64e125ef6 | ||
|
|
9dd6fda504 | ||
|
|
2c7fe6ec5d | ||
|
|
160423d498 | ||
|
|
afb8b17bc5 | ||
|
|
fda2bfcb7a | ||
|
|
5635185147 | ||
|
|
1a41b12b4f | ||
|
|
8ffe064aed | ||
|
|
7ac4e3a670 | ||
|
|
cd173d0ea3 | ||
|
|
3fe0a72123 | ||
|
|
f561c42074 | ||
|
|
370271441c | ||
|
|
8cc0f2c095 | ||
|
|
9905b35d8a | ||
|
|
8d178bd7b6 | ||
|
|
530f40421a | ||
|
|
4f10610ae5 | ||
|
|
d65dbb412d | ||
|
|
befbf010d7 | ||
|
|
a00b10df8c | ||
|
|
24a89cb35d | ||
|
|
349b78117b | ||
|
|
9d159773c5 | ||
|
|
0e14a12a1d | ||
|
|
813fbe13ab | ||
|
|
fd00fd999f | ||
|
|
f4b32db745 | ||
|
|
99bf90957a | ||
|
|
98b6e51fc6 | ||
|
|
bc3b400e06 | ||
|
|
665ad8c7f7 | ||
|
|
42995c95b9 | ||
|
|
49c5e0eef4 | ||
|
|
30599e72bf | ||
|
|
3d451d916f | ||
|
|
02b3ec9ffc | ||
|
|
c7f77de09d | ||
|
|
2719a398b0 | ||
|
|
7e9d669550 | ||
|
|
e4dc2acd35 | ||
|
|
2b940bcde1 | ||
|
|
379ac32f2c | ||
|
|
eca524d5a6 | ||
|
|
50d1b8e6b4 | ||
|
|
84aad03545 | ||
|
|
6fcb2c1963 | ||
|
|
ce015f0184 | ||
|
|
33021bb9dd | ||
|
|
97fbf1d106 | ||
|
|
017c96d6e1 | ||
|
|
1f098bc568 | ||
|
|
367798a9cf | ||
|
|
f9369ca839 | ||
|
|
70619ad135 | ||
|
|
56cc32b5e3 | ||
|
|
986d033976 | ||
|
|
decfae3a5d | ||
|
|
a6bb074359 | ||
|
|
59ed98f687 | ||
|
|
1202ada5c1 | ||
|
|
8347a49c62 | ||
|
|
fcc06c3da4 | ||
|
|
9236e137e9 | ||
|
|
2d769c3bc5 | ||
|
|
9705048c0e | ||
|
|
6920913226 | ||
|
|
519d65b564 | ||
|
|
3f077472ee | ||
|
|
0c33cc07f1 | ||
|
|
289e4a2160 | ||
|
|
67901a67cb | ||
|
|
5acba1722d | ||
|
|
72f3e4fd8e | ||
|
|
83fe1f4494 | ||
|
|
9f8984fba5 | ||
|
|
04a23358c7 | ||
|
|
fc687b8ee9 | ||
|
|
a3e0234f49 | ||
|
|
8ce18b6b73 | ||
|
|
df60ff2a29 | ||
|
|
a547f98fbb | ||
|
|
4c853bf66f | ||
|
|
77af22f93d | ||
|
|
58dd1f58b5 | ||
|
|
dac1ec64a3 | ||
|
|
9823ef295d | ||
|
|
cb15da45c2 | ||
|
|
8e59f80a93 | ||
|
|
fb66fb4948 | ||
|
|
a9dbcc32fd | ||
|
|
a3dadc5a42 | ||
|
|
2b39ea081f | ||
|
|
da08818f4f | ||
|
|
5f4a34c606 | ||
|
|
c2850a3840 | ||
|
|
9bb5c46da4 | ||
|
|
ae131a0b7c | ||
|
|
7a6e6b484d | ||
|
|
dc031df06a | ||
|
|
b58f5a3e77 | ||
|
|
de1d0a25a8 | ||
|
|
95a9035e8b | ||
|
|
0e2ac81b00 | ||
|
|
fdb04dd485 | ||
|
|
f6284bb875 | ||
|
|
7356be641d | ||
|
|
d3d933ac9b | ||
|
|
161752932b | ||
|
|
ae67e5966a | ||
|
|
553676e8f5 | ||
|
|
15dfc869f8 | ||
|
|
439433a909 | ||
|
|
224ea3ec50 | ||
|
|
b73864fc10 | ||
|
|
01dd871a20 | ||
|
|
8df8d67f63 | ||
|
|
31bb8f7936 | ||
|
|
f580871b42 | ||
|
|
52b9b38a22 | ||
|
|
bae6a269ca | ||
|
|
9b06cd15e0 | ||
|
|
346532d711 | ||
|
|
15c5317b6c | ||
|
|
02bdeb7a2c | ||
|
|
453601a65a | ||
|
|
8e34ca4e8f | ||
|
|
eda0e4ca46 | ||
|
|
5ee9fbf7d7 | ||
|
|
d88ca95133 | ||
|
|
28deee2663 | ||
|
|
374f7807e1 | ||
|
|
27dc274f68 | ||
|
|
c8a28812fb | ||
|
|
88ae865423 | ||
|
|
a2dc135196 | ||
|
|
715808d3e2 | ||
|
|
02bc656f90 | ||
|
|
806b4e0a9f | ||
|
|
0c85f5a154 | ||
|
|
7de6a44a0f | ||
|
|
abdb15bedd | ||
|
|
7a1388d55f | ||
|
|
4687560af9 | ||
|
|
732d6c011f | ||
|
|
4659eaafa4 | ||
|
|
2a228c7885 | ||
|
|
90844e28dc | ||
|
|
009a8cb452 | ||
|
|
89cad6a160 | ||
|
|
5cbd13ee02 | ||
|
|
79e19bb62b | ||
|
|
253b5ce758 | ||
|
|
d855493df1 | ||
|
|
7ea10cfba8 | ||
|
|
43b6c2cd70 | ||
|
|
b1cb441916 | ||
|
|
01500813ad | ||
|
|
59171f49e9 | ||
|
|
1b8768339f | ||
|
|
374036c9f1 | ||
|
|
bf62e0dcfd | ||
|
|
855a5d7904 | ||
|
|
16c58c33c8 | ||
|
|
e14bb3629f | ||
|
|
fbda5d7d2f | ||
|
|
be18fdb16a | ||
|
|
82f60c9b5e | ||
|
|
4c893341f5 | ||
|
|
42a6ef6316 | ||
|
|
041d5948f3 | ||
|
|
39a589c74e | ||
|
|
d7a4ab1548 | ||
|
|
4eed43c229 | ||
|
|
cc278ff7c0 | ||
|
|
2b8b896bca | ||
|
|
32bda80136 | ||
|
|
71208c3362 | ||
|
|
9544a909f1 | ||
|
|
d4a841a32b | ||
|
|
324f3c3846 | ||
|
|
63528b7a4d | ||
|
|
7abfe520df | ||
|
|
d76c770473 | ||
|
|
444f3c0e7a | ||
|
|
719aeb7a6e | ||
|
|
a7edf4aec8 | ||
|
|
32792ec66c | ||
|
|
c924f8d3dd | ||
|
|
0ff2f8e0ee | ||
|
|
f468e83c85 | ||
|
|
48c771c4ce | ||
|
|
266da73237 | ||
|
|
d2f1f4490b | ||
|
|
f00fad0951 | ||
|
|
984dcc97ae | ||
|
|
3ed57f68e5 | ||
|
|
69d85c5fb3 | ||
|
|
0d822312fa | ||
|
|
ba2ba19f6d | ||
|
|
c9a728c329 | ||
|
|
adf7973417 | ||
|
|
4f5f2597ce | ||
|
|
114881acba | ||
|
|
b1f223b5b8 | ||
|
|
05333afec1 | ||
|
|
d22e0d8721 | ||
|
|
c5f22aca0f | ||
|
|
bfc9770b24 | ||
|
|
cd73a17321 | ||
|
|
39e4e86263 | ||
|
|
c1f8925561 | ||
|
|
c7bf7b8977 | ||
|
|
e0687f9f54 | ||
|
|
dcf6ad6c70 | ||
|
|
a453ffb7ea | ||
|
|
779cb2b65b | ||
|
|
244485ce72 | ||
|
|
713f5b0779 | ||
|
|
6c25f7dcb5 | ||
|
|
8576598d64 | ||
|
|
db73e46709 | ||
|
|
da7d63a690 | ||
|
|
6d8af6175e | ||
|
|
8232da46d6 | ||
|
|
c975e02612 | ||
|
|
183d84803a | ||
|
|
6210515c78 | ||
|
|
94610d4c27 | ||
|
|
09b9e83102 | ||
|
|
891438c086 | ||
|
|
2d7a79a984 | ||
|
|
ee92f521ab | ||
|
|
2dea4b86ee | ||
|
|
fdbdbb6b8a | ||
|
|
fc064eb41e | ||
|
|
db8a210964 | ||
|
|
f69995d909 | ||
|
|
ac9ced9eb3 | ||
|
|
ba8bd24bbb | ||
|
|
8ea6e12372 | ||
|
|
0e3971339f | ||
|
|
ecf998ed8f | ||
|
|
89df6536bf | ||
|
|
8244006267 | ||
|
|
6ac8762ecd | ||
|
|
628b21dbcd | ||
|
|
5ae8432d15 | ||
|
|
f2668a0a71 | ||
|
|
5060f172cc | ||
|
|
ceeb7211c9 | ||
|
|
3fb92e63e0 | ||
|
|
ad633fb142 | ||
|
|
3ea36843b3 | ||
|
|
80b16457cb | ||
|
|
7827ca87d1 | ||
|
|
91ccd57ca9 | ||
|
|
f0a307f61c | ||
|
|
80b97bd0b8 | ||
|
|
7c2f492a88 | ||
|
|
114f6ce2fd | ||
|
|
69671302df | ||
|
|
e1833cff9c | ||
|
|
81ac790dc8 | ||
|
|
3b301cf75d | ||
|
|
6c8dde3554 | ||
|
|
9045c3ab53 | ||
|
|
53a645402f | ||
|
|
6d01681b02 | ||
|
|
9a37057800 | ||
|
|
3578ab89fb | ||
|
|
178df3d885 | ||
|
|
1f98105e54 | ||
|
|
a4161e00f9 |
36
.github/actions/build-selftests/action.yml
vendored
36
.github/actions/build-selftests/action.yml
vendored
@@ -1,36 +0,0 @@
|
|||||||
name: 'build-selftests'
|
|
||||||
description: 'Build BPF selftests'
|
|
||||||
inputs:
|
|
||||||
repo-path:
|
|
||||||
description: 'where is the source code'
|
|
||||||
required: true
|
|
||||||
kernel:
|
|
||||||
description: 'kernel version or LATEST'
|
|
||||||
required: true
|
|
||||||
default: 'LATEST'
|
|
||||||
vmlinux:
|
|
||||||
description: 'where is vmlinux file'
|
|
||||||
required: true
|
|
||||||
default: '${{ github.workspace }}/vmlinux'
|
|
||||||
llvm-version:
|
|
||||||
description: 'llvm version'
|
|
||||||
required: true
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: "composite"
|
|
||||||
steps:
|
|
||||||
- shell: bash
|
|
||||||
run: |
|
|
||||||
source $GITHUB_ACTION_PATH/../../../ci/vmtest/helpers.sh
|
|
||||||
foldable start "Setup Env"
|
|
||||||
sudo apt-get install -y qemu-kvm zstd binutils-dev elfutils libcap-dev libelf-dev libdw-dev python3-docutils
|
|
||||||
foldable end
|
|
||||||
- shell: bash
|
|
||||||
run: |
|
|
||||||
export KERNEL=${{ inputs.kernel }}
|
|
||||||
export REPO_ROOT="${{ github.workspace }}"
|
|
||||||
export REPO_PATH="${{ inputs.repo-path }}"
|
|
||||||
export VMLINUX_BTF="${{ inputs.vmlinux }}"
|
|
||||||
export LLVM_VERSION="${{ inputs.llvm-version }}"
|
|
||||||
|
|
||||||
${{ github.action_path }}/build_selftests.sh
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
THISDIR="$(cd $(dirname $0) && pwd)"
|
|
||||||
|
|
||||||
source ${THISDIR}/helpers.sh
|
|
||||||
|
|
||||||
foldable start prepare_selftests "Building selftests"
|
|
||||||
|
|
||||||
LIBBPF_PATH="${REPO_ROOT}"
|
|
||||||
|
|
||||||
llvm_latest_version() {
|
|
||||||
echo "19"
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ "${LLVM_VERSION}" == $(llvm_latest_version) ]]; then
|
|
||||||
REPO_DISTRO_SUFFIX=""
|
|
||||||
else
|
|
||||||
REPO_DISTRO_SUFFIX="-${LLVM_VERSION}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
DISTRIB_CODENAME="noble"
|
|
||||||
test -f /etc/lsb-release && . /etc/lsb-release
|
|
||||||
echo "${DISTRIB_CODENAME}"
|
|
||||||
|
|
||||||
echo "deb https://apt.llvm.org/${DISTRIB_CODENAME}/ llvm-toolchain-${DISTRIB_CODENAME}${REPO_DISTRO_SUFFIX} main" \
|
|
||||||
| sudo tee /etc/apt/sources.list.d/llvm.list
|
|
||||||
|
|
||||||
PREPARE_SELFTESTS_SCRIPT=${THISDIR}/prepare_selftests-${KERNEL}.sh
|
|
||||||
if [ -f "${PREPARE_SELFTESTS_SCRIPT}" ]; then
|
|
||||||
(cd "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" && ${PREPARE_SELFTESTS_SCRIPT})
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${KERNEL}" = 'LATEST' ]]; then
|
|
||||||
VMLINUX_H=
|
|
||||||
else
|
|
||||||
VMLINUX_H=${THISDIR}/vmlinux.h
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd ${REPO_ROOT}/${REPO_PATH}
|
|
||||||
make headers
|
|
||||||
make \
|
|
||||||
CLANG=clang-${LLVM_VERSION} \
|
|
||||||
LLC=llc-${LLVM_VERSION} \
|
|
||||||
LLVM_STRIP=llvm-strip-${LLVM_VERSION} \
|
|
||||||
VMLINUX_BTF="${VMLINUX_BTF}" \
|
|
||||||
VMLINUX_H=${VMLINUX_H} \
|
|
||||||
-C "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" \
|
|
||||||
-j $((4*$(nproc))) > /dev/null
|
|
||||||
cd -
|
|
||||||
mkdir ${LIBBPF_PATH}/selftests
|
|
||||||
cp -R "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" \
|
|
||||||
${LIBBPF_PATH}/selftests
|
|
||||||
cd ${LIBBPF_PATH}
|
|
||||||
rm selftests/bpf/.gitignore
|
|
||||||
git add selftests
|
|
||||||
|
|
||||||
foldable end prepare_selftests
|
|
||||||
38
.github/actions/build-selftests/helpers.sh
vendored
38
.github/actions/build-selftests/helpers.sh
vendored
@@ -1,38 +0,0 @@
|
|||||||
# shellcheck shell=bash
|
|
||||||
|
|
||||||
# $1 - start or end
|
|
||||||
# $2 - fold identifier, no spaces
|
|
||||||
# $3 - fold section description
|
|
||||||
foldable() {
|
|
||||||
local YELLOW='\033[1;33m'
|
|
||||||
local NOCOLOR='\033[0m'
|
|
||||||
if [ $1 = "start" ]; then
|
|
||||||
line="::group::$2"
|
|
||||||
if [ ! -z "${3:-}" ]; then
|
|
||||||
line="$line - ${YELLOW}$3${NOCOLOR}"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
line="::endgroup::"
|
|
||||||
fi
|
|
||||||
echo -e "$line"
|
|
||||||
}
|
|
||||||
|
|
||||||
__print() {
|
|
||||||
local TITLE=""
|
|
||||||
if [[ -n $2 ]]; then
|
|
||||||
TITLE=" title=$2"
|
|
||||||
fi
|
|
||||||
echo "::$1${TITLE}::$3"
|
|
||||||
}
|
|
||||||
|
|
||||||
# $1 - title
|
|
||||||
# $2 - message
|
|
||||||
print_error() {
|
|
||||||
__print error $1 $2
|
|
||||||
}
|
|
||||||
|
|
||||||
# $1 - title
|
|
||||||
# $2 - message
|
|
||||||
print_notice() {
|
|
||||||
__print notice $1 $2
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
printf "all:\n\ttouch bpf_testmod.ko\n\nclean:\n" > bpf_testmod/Makefile
|
|
||||||
printf "all:\n\ttouch bpf_test_no_cfi.ko\n\nclean:\n" > bpf_test_no_cfi/Makefile
|
|
||||||
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
printf "all:\n\ttouch bpf_testmod.ko\n\nclean:\n" > bpf_testmod/Makefile
|
|
||||||
printf "all:\n\ttouch bpf_test_no_cfi.ko\n\nclean:\n" > bpf_test_no_cfi/Makefile
|
|
||||||
|
|
||||||
14704
.github/actions/build-selftests/vmlinux.h
vendored
14704
.github/actions/build-selftests/vmlinux.h
vendored
File diff suppressed because it is too large
Load Diff
124
.github/actions/vmtest/action.yml
vendored
124
.github/actions/vmtest/action.yml
vendored
@@ -1,124 +0,0 @@
|
|||||||
name: 'vmtest'
|
|
||||||
description: 'Build + run vmtest'
|
|
||||||
inputs:
|
|
||||||
kernel:
|
|
||||||
description: 'kernel version or LATEST'
|
|
||||||
required: true
|
|
||||||
default: 'LATEST'
|
|
||||||
arch:
|
|
||||||
description: 'what arch to test'
|
|
||||||
required: true
|
|
||||||
default: 'x86_64'
|
|
||||||
pahole:
|
|
||||||
description: 'pahole rev or master'
|
|
||||||
required: true
|
|
||||||
default: 'master'
|
|
||||||
llvm-version:
|
|
||||||
description: 'llvm version'
|
|
||||||
required: false
|
|
||||||
default: '17'
|
|
||||||
runs:
|
|
||||||
using: "composite"
|
|
||||||
steps:
|
|
||||||
# Allow CI user to access /dev/kvm (via qemu) w/o group change/relogin
|
|
||||||
# by changing permissions set by udev.
|
|
||||||
- name: Set /dev/kvm permissions
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
if [ -e /dev/kvm ]; then
|
|
||||||
echo "/dev/kvm exists"
|
|
||||||
if [ $(id -u) != 0 ]; then
|
|
||||||
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' \
|
|
||||||
| sudo tee /etc/udev/rules.d/99-kvm4all.rules > /dev/null
|
|
||||||
sudo udevadm control --reload-rules
|
|
||||||
sudo udevadm trigger --name-match=kvm
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "/dev/kvm does not exist"
|
|
||||||
fi
|
|
||||||
# setup environment
|
|
||||||
- name: Setup environment
|
|
||||||
uses: libbpf/ci/setup-build-env@main
|
|
||||||
with:
|
|
||||||
pahole: ${{ inputs.pahole }}
|
|
||||||
arch: ${{ inputs.arch }}
|
|
||||||
llvm-version: ${{ inputs.llvm-version }}
|
|
||||||
# 1. download CHECKPOINT kernel source
|
|
||||||
- name: Get checkpoint commit
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
cat CHECKPOINT-COMMIT
|
|
||||||
echo "CHECKPOINT=$(cat CHECKPOINT-COMMIT)" >> $GITHUB_ENV
|
|
||||||
- name: Get kernel source at checkpoint
|
|
||||||
uses: libbpf/ci/get-linux-source@main
|
|
||||||
with:
|
|
||||||
repo: 'https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git'
|
|
||||||
rev: ${{ env.CHECKPOINT }}
|
|
||||||
dest: '${{ github.workspace }}/.kernel'
|
|
||||||
- name: Patch kernel source
|
|
||||||
uses: libbpf/ci/patch-kernel@main
|
|
||||||
with:
|
|
||||||
patches-root: '${{ github.workspace }}/ci/diffs'
|
|
||||||
repo-root: '.kernel'
|
|
||||||
- name: Prepare to build BPF selftests
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
source $GITHUB_ACTION_PATH/../../../ci/vmtest/helpers.sh
|
|
||||||
foldable start "Prepare building selftest"
|
|
||||||
cd .kernel
|
|
||||||
cat tools/testing/selftests/bpf/config \
|
|
||||||
tools/testing/selftests/bpf/config.${{ inputs.arch }} > .config
|
|
||||||
# this file might or mihgt not exist depending on kernel version
|
|
||||||
cat tools/testing/selftests/bpf/config.vm >> .config || :
|
|
||||||
make olddefconfig && make prepare
|
|
||||||
cd -
|
|
||||||
foldable end
|
|
||||||
# 2. if kernel == LATEST, build kernel image from tree
|
|
||||||
- name: Build kernel image
|
|
||||||
if: ${{ inputs.kernel == 'LATEST' }}
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
source $GITHUB_ACTION_PATH/../../../ci/vmtest/helpers.sh
|
|
||||||
foldable start "Build Kernel Image"
|
|
||||||
cd .kernel
|
|
||||||
make -j $((4*$(nproc))) all > /dev/null
|
|
||||||
cp vmlinux ${{ github.workspace }}
|
|
||||||
cd -
|
|
||||||
foldable end
|
|
||||||
# else, just download prebuilt kernel image
|
|
||||||
- name: Download prebuilt kernel
|
|
||||||
if: ${{ inputs.kernel != 'LATEST' }}
|
|
||||||
uses: libbpf/ci/download-vmlinux@main
|
|
||||||
with:
|
|
||||||
kernel: ${{ inputs.kernel }}
|
|
||||||
arch: ${{ inputs.arch }}
|
|
||||||
# 3. build selftests
|
|
||||||
- name: Build BPF selftests
|
|
||||||
uses: ./.github/actions/build-selftests
|
|
||||||
with:
|
|
||||||
repo-path: '.kernel'
|
|
||||||
kernel: ${{ inputs.kernel }}
|
|
||||||
llvm-version: ${{ inputs.llvm-version }}
|
|
||||||
# 4. prepare rootfs
|
|
||||||
- name: prepare rootfs
|
|
||||||
uses: libbpf/ci/prepare-rootfs@main
|
|
||||||
env:
|
|
||||||
KBUILD_OUTPUT: '.kernel'
|
|
||||||
with:
|
|
||||||
project-name: 'libbpf'
|
|
||||||
arch: ${{ inputs.arch }}
|
|
||||||
kernel: ${{ inputs.kernel }}
|
|
||||||
kernel-root: '.kernel'
|
|
||||||
kbuild-output: ${{ env.KBUILD_OUTPUT }}
|
|
||||||
image-output: '/tmp/root.img'
|
|
||||||
# 5. run selftest in QEMU
|
|
||||||
- name: Run selftests
|
|
||||||
env:
|
|
||||||
KERNEL: ${{ inputs.kernel }}
|
|
||||||
REPO_ROOT: ${{ github.workspace }}
|
|
||||||
uses: libbpf/ci/run-qemu@main
|
|
||||||
with:
|
|
||||||
arch: ${{ inputs.arch }}
|
|
||||||
img: '/tmp/root.img'
|
|
||||||
vmlinuz: 'vmlinuz'
|
|
||||||
kernel-root: '.kernel'
|
|
||||||
43
.github/workflows/build.yml
vendored
43
.github/workflows/build.yml
vendored
@@ -61,31 +61,32 @@ jobs:
|
|||||||
- arch: aarch64
|
- arch: aarch64
|
||||||
- arch: ppc64le
|
- arch: ppc64le
|
||||||
- arch: s390x
|
- arch: s390x
|
||||||
- arch: x86
|
- arch: amd64
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
name: Checkout
|
name: Checkout
|
||||||
|
|
||||||
|
- name: Setup QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
with:
|
||||||
|
image: tonistiigi/binfmt:qemu-v8.1.5
|
||||||
|
|
||||||
- uses: ./.github/actions/setup
|
- uses: ./.github/actions/setup
|
||||||
name: Pre-Setup
|
name: Pre-Setup
|
||||||
|
|
||||||
- run: source /tmp/ci_setup && sudo -E $CI_ROOT/managers/ubuntu.sh
|
- run: source /tmp/ci_setup && sudo -E $CI_ROOT/managers/ubuntu.sh
|
||||||
if: matrix.arch == 'x86'
|
if: matrix.arch == 'amd64'
|
||||||
name: Setup
|
name: Setup
|
||||||
- uses: uraimo/run-on-arch-action@v2.7.1
|
|
||||||
name: Build in docker
|
- name: Build in docker
|
||||||
if: matrix.arch != 'x86'
|
if: matrix.arch != 'amd64'
|
||||||
with:
|
run: |
|
||||||
distro:
|
cp /tmp/ci_setup ${GITHUB_WORKSPACE}
|
||||||
ubuntu22.04
|
docker run --rm \
|
||||||
arch:
|
--platform linux/${{ matrix.arch }} \
|
||||||
${{ matrix.arch }}
|
-v ${GITHUB_WORKSPACE}:${GITHUB_WORKSPACE} \
|
||||||
setup:
|
-e GITHUB_WORKSPACE=${GITHUB_WORKSPACE} \
|
||||||
cp /tmp/ci_setup $GITHUB_WORKSPACE
|
-w /ci/workspace \
|
||||||
dockerRunArgs: |
|
ubuntu:noble \
|
||||||
--volume "${GITHUB_WORKSPACE}:${GITHUB_WORKSPACE}"
|
${GITHUB_WORKSPACE}/ci/build-in-docker.sh
|
||||||
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
|
|
||||||
|
|||||||
2
.github/workflows/cifuzz.yml
vendored
2
.github/workflows/cifuzz.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
|||||||
dry-run: false
|
dry-run: false
|
||||||
sanitizer: ${{ matrix.sanitizer }}
|
sanitizer: ${{ matrix.sanitizer }}
|
||||||
- name: Upload Crash
|
- name: Upload Crash
|
||||||
uses: actions/upload-artifact@v1
|
uses: actions/upload-artifact@v4
|
||||||
if: failure() && steps.build.outcome == 'success'
|
if: failure() && steps.build.outcome == 'success'
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.sanitizer }}-artifacts
|
name: ${{ matrix.sanitizer }}-artifacts
|
||||||
|
|||||||
12
.github/workflows/coverity.yml
vendored
12
.github/workflows/coverity.yml
vendored
@@ -1,30 +1,30 @@
|
|||||||
name: libbpf-ci-coverity
|
name: libbpf-ci-coverity
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 18 * * *'
|
- cron: '0 18 * * *'
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
coverity:
|
coverity:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.repository == 'libbpf/libbpf'
|
|
||||||
name: Coverity
|
name: Coverity
|
||||||
|
env:
|
||||||
|
COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: ./.github/actions/setup
|
- uses: ./.github/actions/setup
|
||||||
- name: Run coverity
|
- name: Run coverity
|
||||||
|
if: ${{ env.COVERITY_SCAN_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
source "${GITHUB_WORKSPACE}"/ci/vmtest/helpers.sh
|
|
||||||
foldable start "Setup CI env"
|
|
||||||
source /tmp/ci_setup
|
source /tmp/ci_setup
|
||||||
export COVERITY_SCAN_NOTIFICATION_EMAIL="${AUTHOR_EMAIL}"
|
export COVERITY_SCAN_NOTIFICATION_EMAIL="${AUTHOR_EMAIL}"
|
||||||
export COVERITY_SCAN_BRANCH_PATTERN=${GITHUB_REF##refs/*/}
|
export COVERITY_SCAN_BRANCH_PATTERN=${GITHUB_REF##refs/*/}
|
||||||
export TRAVIS_BRANCH=${COVERITY_SCAN_BRANCH_PATTERN}
|
export TRAVIS_BRANCH=${COVERITY_SCAN_BRANCH_PATTERN}
|
||||||
foldable end
|
|
||||||
scripts/coverity.sh
|
scripts/coverity.sh
|
||||||
env:
|
env:
|
||||||
COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
|
||||||
COVERITY_SCAN_PROJECT_NAME: libbpf
|
COVERITY_SCAN_PROJECT_NAME: libbpf
|
||||||
COVERITY_SCAN_BUILD_COMMAND_PREPEND: 'cd src/'
|
COVERITY_SCAN_BUILD_COMMAND_PREPEND: 'cd src/'
|
||||||
COVERITY_SCAN_BUILD_COMMAND: 'make'
|
COVERITY_SCAN_BUILD_COMMAND: 'make'
|
||||||
|
|||||||
43
.github/workflows/ondemand.yml
vendored
43
.github/workflows/ondemand.yml
vendored
@@ -3,34 +3,29 @@ name: ondemand
|
|||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
kernel-origin:
|
arch:
|
||||||
description: 'git repo for linux kernel'
|
default: 'x86_64'
|
||||||
default: 'https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git'
|
|
||||||
required: true
|
required: true
|
||||||
kernel-rev:
|
llvm-version:
|
||||||
description: 'rev/tag/branch for linux kernel'
|
default: '18'
|
||||||
|
required: true
|
||||||
|
kernel:
|
||||||
|
default: 'LATEST'
|
||||||
|
required: true
|
||||||
|
pahole:
|
||||||
default: "master"
|
default: "master"
|
||||||
required: true
|
required: true
|
||||||
pahole-origin:
|
runs-on:
|
||||||
description: 'git repo for pahole'
|
default: 'ubuntu-24.04'
|
||||||
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
|
required: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
vmtest:
|
vmtest:
|
||||||
runs-on: ubuntu-latest
|
name: ${{ inputs.kernel }} kernel llvm-${{ inputs.llvm-version }} pahole@${{ inputs.pahole }}
|
||||||
name: vmtest with customized pahole/Kernel
|
uses: ./.github/workflows/vmtest.yml
|
||||||
steps:
|
with:
|
||||||
- uses: actions/checkout@v4
|
runs_on: ${{ inputs.runs-on }}
|
||||||
- uses: ./.github/actions/setup
|
kernel: ${{ inputs.kernel }}
|
||||||
- uses: ./.github/actions/vmtest
|
arch: ${{ inputs.arch }}
|
||||||
with:
|
llvm-version: ${{ inputs.llvm-version }}
|
||||||
kernel: 'LATEST'
|
pahole: ${{ inputs.pahole }}
|
||||||
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 }}
|
|
||||||
|
|||||||
20
.github/workflows/pahole.yml
vendored
20
.github/workflows/pahole.yml
vendored
@@ -1,20 +0,0 @@
|
|||||||
name: pahole-staging
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 18 * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
vmtest:
|
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
name: Kernel LATEST + staging pahole
|
|
||||||
env:
|
|
||||||
STAGING: tmp.master
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: ./.github/actions/setup
|
|
||||||
- uses: ./.github/actions/vmtest
|
|
||||||
with:
|
|
||||||
kernel: LATEST
|
|
||||||
pahole: $STAGING
|
|
||||||
37
.github/workflows/test.yml
vendored
37
.github/workflows/test.yml
vendored
@@ -1,42 +1,31 @@
|
|||||||
name: libbpf-ci
|
name: libbpf-ci
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
push:
|
push:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 18 * * *'
|
- cron: '0 18 * * *'
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ci-test-${{ github.head_ref }}
|
group: ci-test-${{ github.head_ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
vmtest:
|
vmtest:
|
||||||
runs-on: ${{ matrix.runs_on }}
|
|
||||||
name: Kernel ${{ matrix.kernel }} on ${{ matrix.arch }} + selftests
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- kernel: 'LATEST'
|
- kernel: 'LATEST'
|
||||||
runs_on: ubuntu-24.04
|
runs_on: 'ubuntu-24.04'
|
||||||
arch: 'x86_64'
|
arch: 'x86_64'
|
||||||
- kernel: '5.5.0'
|
llvm-version: '21'
|
||||||
runs_on: ubuntu-24.04
|
pahole: 'master'
|
||||||
arch: 'x86_64'
|
name: Linux ${{ matrix.kernel }} llvm-${{ matrix.llvm-version }}
|
||||||
- kernel: '4.9.0'
|
uses: ./.github/workflows/vmtest.yml
|
||||||
runs_on: ubuntu-24.04
|
with:
|
||||||
arch: 'x86_64'
|
runs_on: ${{ matrix.runs_on }}
|
||||||
- kernel: 'LATEST'
|
kernel: ${{ matrix.kernel }}
|
||||||
runs_on: ["s390x", "docker-noble-main"]
|
arch: ${{ matrix.arch }}
|
||||||
arch: 's390x'
|
llvm-version: ${{ matrix.llvm-version }}
|
||||||
steps:
|
pahole: ${{ matrix.pahole }}
|
||||||
- uses: actions/checkout@v4
|
|
||||||
name: Checkout
|
|
||||||
- uses: ./.github/actions/setup
|
|
||||||
name: Setup
|
|
||||||
- uses: ./.github/actions/vmtest
|
|
||||||
name: vmtest
|
|
||||||
with:
|
|
||||||
kernel: ${{ matrix.kernel }}
|
|
||||||
arch: ${{ matrix.arch }}
|
|
||||||
|
|||||||
117
.github/workflows/vmtest.yml
vendored
Normal file
117
.github/workflows/vmtest.yml
vendored
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
name: 'Build kernel and selftests/bpf, run selftests via vmtest'
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
runs_on:
|
||||||
|
required: true
|
||||||
|
default: 'ubuntu-24.04'
|
||||||
|
type: string
|
||||||
|
arch:
|
||||||
|
description: 'what arch to test'
|
||||||
|
required: true
|
||||||
|
default: 'x86_64'
|
||||||
|
type: string
|
||||||
|
kernel:
|
||||||
|
description: 'kernel version or LATEST'
|
||||||
|
required: true
|
||||||
|
default: 'LATEST'
|
||||||
|
type: string
|
||||||
|
pahole:
|
||||||
|
description: 'pahole rev or branch'
|
||||||
|
required: false
|
||||||
|
default: 'master'
|
||||||
|
type: string
|
||||||
|
llvm-version:
|
||||||
|
description: 'llvm version'
|
||||||
|
required: false
|
||||||
|
default: '18'
|
||||||
|
type: string
|
||||||
|
jobs:
|
||||||
|
vmtest:
|
||||||
|
name: pahole@${{ inputs.pahole }}
|
||||||
|
runs-on: ${{ inputs.runs_on }}
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup environment
|
||||||
|
uses: libbpf/ci/setup-build-env@v3
|
||||||
|
with:
|
||||||
|
pahole: ${{ inputs.pahole }}
|
||||||
|
arch: ${{ inputs.arch }}
|
||||||
|
llvm-version: ${{ inputs.llvm-version }}
|
||||||
|
|
||||||
|
- name: Get checkpoint commit
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cat CHECKPOINT-COMMIT
|
||||||
|
echo "CHECKPOINT=$(cat CHECKPOINT-COMMIT)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Get kernel source at checkpoint
|
||||||
|
uses: libbpf/ci/get-linux-source@v3
|
||||||
|
with:
|
||||||
|
repo: 'https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git'
|
||||||
|
rev: ${{ env.CHECKPOINT }}
|
||||||
|
dest: '${{ github.workspace }}/.kernel'
|
||||||
|
|
||||||
|
- name: Patch kernel source
|
||||||
|
uses: libbpf/ci/patch-kernel@v3
|
||||||
|
with:
|
||||||
|
patches-root: '${{ github.workspace }}/ci/diffs'
|
||||||
|
repo-root: '.kernel'
|
||||||
|
|
||||||
|
- name: Configure kernel build
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cd .kernel
|
||||||
|
cat tools/testing/selftests/bpf/config \
|
||||||
|
tools/testing/selftests/bpf/config.${{ inputs.arch }} > .config
|
||||||
|
# this file might or might not exist depending on kernel version
|
||||||
|
cat tools/testing/selftests/bpf/config.vm >> .config || :
|
||||||
|
make olddefconfig && make prepare
|
||||||
|
cd -
|
||||||
|
|
||||||
|
- name: Build kernel image
|
||||||
|
if: ${{ inputs.kernel == 'LATEST' }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cd .kernel
|
||||||
|
make -j $((4*$(nproc))) all
|
||||||
|
cp vmlinux ${{ github.workspace }}
|
||||||
|
cd -
|
||||||
|
|
||||||
|
- name: Download prebuilt kernel
|
||||||
|
if: ${{ inputs.kernel != 'LATEST' }}
|
||||||
|
uses: libbpf/ci/download-vmlinux@v3
|
||||||
|
with:
|
||||||
|
kernel: ${{ inputs.kernel }}
|
||||||
|
arch: ${{ inputs.arch }}
|
||||||
|
|
||||||
|
- name: Build selftests/bpf
|
||||||
|
uses: libbpf/ci/build-selftests@v3
|
||||||
|
env:
|
||||||
|
MAX_MAKE_JOBS: 32
|
||||||
|
VMLINUX_BTF: ${{ github.workspace }}/vmlinux
|
||||||
|
VMLINUX_H: ${{ inputs.kernel != 'LATEST' && format('{0}/.github/actions/build-selftests/vmlinux.h', github.workspace) || '' }}
|
||||||
|
with:
|
||||||
|
arch: ${{ inputs.arch }}
|
||||||
|
kernel-root: ${{ github.workspace }}/.kernel
|
||||||
|
llvm-version: ${{ inputs.llvm-version }}
|
||||||
|
|
||||||
|
- name: Run selftests
|
||||||
|
env:
|
||||||
|
ALLOWLIST_FILE: /tmp/allowlist
|
||||||
|
DENYLIST_FILE: /tmp/denylist
|
||||||
|
KERNEL: ${{ inputs.kernel }}
|
||||||
|
VMLINUX: ${{ github.workspace }}/vmlinux
|
||||||
|
LLVM_VERSION: ${{ inputs.llvm-version }}
|
||||||
|
SELFTESTS_BPF: ${{ github.workspace }}/.kernel/tools/testing/selftests/bpf
|
||||||
|
VMTEST_CONFIGS: ${{ github.workspace }}/ci/vmtest/configs
|
||||||
|
uses: libbpf/ci/run-vmtest@v3
|
||||||
|
with:
|
||||||
|
arch: ${{ inputs.arch }}
|
||||||
|
kbuild-output: ${{ github.workspace }}/.kernel
|
||||||
|
kernel-root: ${{ github.workspace }}/.kernel
|
||||||
|
vmlinuz: ${{ inputs.arch }}/vmlinuz-${{ inputs.kernel }}
|
||||||
|
|
||||||
3
.mailmap
3
.mailmap
@@ -8,7 +8,10 @@ Dan Carpenter <error27@gmail.com> <dan.carpenter@oracle.com>
|
|||||||
Geliang Tang <geliang@kernel.org> <geliang.tang@suse.com>
|
Geliang Tang <geliang@kernel.org> <geliang.tang@suse.com>
|
||||||
Herbert Xu <herbert@gondor.apana.org.au>
|
Herbert Xu <herbert@gondor.apana.org.au>
|
||||||
Jakub Kicinski <kuba@kernel.org> <jakub.kicinski@netronome.com>
|
Jakub Kicinski <kuba@kernel.org> <jakub.kicinski@netronome.com>
|
||||||
|
Jean-Philippe Brucker <jpb@kernel.org> <jean-philippe@linaro.org>
|
||||||
|
Jesper Dangaard Brouer <hawk@kernel.org> <brouer@redhat.com>
|
||||||
Kees Cook <kees@kernel.org> <keescook@chromium.org>
|
Kees Cook <kees@kernel.org> <keescook@chromium.org>
|
||||||
|
Kuniyuki Iwashima <kuniyu@google.com> <kuniyu@amazon.co.jp>
|
||||||
Leo Yan <leo.yan@linux.dev> <leo.yan@linaro.org>
|
Leo Yan <leo.yan@linux.dev> <leo.yan@linaro.org>
|
||||||
Mark Starovoytov <mstarovo@pm.me> <mstarovoitov@marvell.com>
|
Mark Starovoytov <mstarovo@pm.me> <mstarovoitov@marvell.com>
|
||||||
Maxim Mikityanskiy <maxtram95@gmail.com> <maximmi@mellanox.com>
|
Maxim Mikityanskiy <maxtram95@gmail.com> <maximmi@mellanox.com>
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
b408473ea01b2e499d23503e2bf898416da9d7ac
|
22cc16c04b7893d8fc22810599f49a305d600b9e
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
2ad6d23f465a4f851e3bcf6d74c315ce7b2c205b
|
08a7491843224f8b96518fbe70d9e48163046054
|
||||||
|
|||||||
14
ci/build-in-docker.sh
Executable file
14
ci/build-in-docker.sh
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
export TZ="America/Los_Angeles"
|
||||||
|
|
||||||
|
apt-get update -y
|
||||||
|
apt-get install -y tzdata build-essential sudo
|
||||||
|
source ${GITHUB_WORKSPACE}/ci_setup
|
||||||
|
|
||||||
|
$CI_ROOT/managers/ubuntu.sh
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
From c71766e8ff7a7f950522d25896fba758585500df Mon Sep 17 00:00:00 2001
|
|
||||||
From: Song Liu <song@kernel.org>
|
|
||||||
Date: Mon, 22 Apr 2024 21:14:40 -0700
|
|
||||||
Subject: [PATCH] arch/Kconfig: Move SPECULATION_MITIGATIONS to arch/Kconfig
|
|
||||||
|
|
||||||
SPECULATION_MITIGATIONS is currently defined only for x86. As a result,
|
|
||||||
IS_ENABLED(CONFIG_SPECULATION_MITIGATIONS) is always false for other
|
|
||||||
archs. f337a6a21e2f effectively set "mitigations=off" by default on
|
|
||||||
non-x86 archs, which is not desired behavior. Jakub observed this
|
|
||||||
change when running bpf selftests on s390 and arm64.
|
|
||||||
|
|
||||||
Fix this by moving SPECULATION_MITIGATIONS to arch/Kconfig so that it is
|
|
||||||
available in all archs and thus can be used safely in kernel/cpu.c
|
|
||||||
|
|
||||||
Fixes: f337a6a21e2f ("x86/cpu: Actually turn off mitigations by default for SPECULATION_MITIGATIONS=n")
|
|
||||||
Cc: stable@vger.kernel.org
|
|
||||||
Cc: Sean Christopherson <seanjc@google.com>
|
|
||||||
Cc: Ingo Molnar <mingo@kernel.org>
|
|
||||||
Cc: Daniel Sneddon <daniel.sneddon@linux.intel.com>
|
|
||||||
Cc: Jakub Kicinski <kuba@kernel.org>
|
|
||||||
Signed-off-by: Song Liu <song@kernel.org>
|
|
||||||
---
|
|
||||||
arch/Kconfig | 10 ++++++++++
|
|
||||||
arch/x86/Kconfig | 10 ----------
|
|
||||||
2 files changed, 10 insertions(+), 10 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/arch/Kconfig b/arch/Kconfig
|
|
||||||
index 9f066785bb71..8f4af75005f8 100644
|
|
||||||
--- a/arch/Kconfig
|
|
||||||
+++ b/arch/Kconfig
|
|
||||||
@@ -1609,4 +1609,14 @@ config CC_HAS_SANE_FUNCTION_ALIGNMENT
|
|
||||||
# strict alignment always, even with -falign-functions.
|
|
||||||
def_bool CC_HAS_MIN_FUNCTION_ALIGNMENT || CC_IS_CLANG
|
|
||||||
|
|
||||||
+menuconfig SPECULATION_MITIGATIONS
|
|
||||||
+ bool "Mitigations for speculative execution vulnerabilities"
|
|
||||||
+ default y
|
|
||||||
+ help
|
|
||||||
+ Say Y here to enable options which enable mitigations for
|
|
||||||
+ speculative execution hardware vulnerabilities.
|
|
||||||
+
|
|
||||||
+ If you say N, all mitigations will be disabled. You really
|
|
||||||
+ should know what you are doing to say so.
|
|
||||||
+
|
|
||||||
endmenu
|
|
||||||
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
|
|
||||||
index 39886bab943a..50c890fce5e0 100644
|
|
||||||
--- a/arch/x86/Kconfig
|
|
||||||
+++ b/arch/x86/Kconfig
|
|
||||||
@@ -2486,16 +2486,6 @@ config PREFIX_SYMBOLS
|
|
||||||
def_bool y
|
|
||||||
depends on CALL_PADDING && !CFI_CLANG
|
|
||||||
|
|
||||||
-menuconfig SPECULATION_MITIGATIONS
|
|
||||||
- bool "Mitigations for speculative execution vulnerabilities"
|
|
||||||
- default y
|
|
||||||
- help
|
|
||||||
- Say Y here to enable options which enable mitigations for
|
|
||||||
- speculative execution hardware vulnerabilities.
|
|
||||||
-
|
|
||||||
- If you say N, all mitigations will be disabled. You really
|
|
||||||
- should know what you are doing to say so.
|
|
||||||
-
|
|
||||||
if SPECULATION_MITIGATIONS
|
|
||||||
|
|
||||||
config MITIGATION_PAGE_TABLE_ISOLATION
|
|
||||||
--
|
|
||||||
2.43.0
|
|
||||||
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
From 0daad0a615e687e1247230f3d0c31ae60ba32314 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Andrii Nakryiko <andrii@kernel.org>
|
|
||||||
Date: Tue, 28 May 2024 15:29:38 -0700
|
|
||||||
Subject: [PATCH bpf-next] selftests/bpf: fix inet_csk_accept prototype in
|
|
||||||
test_sk_storage_tracing.c
|
|
||||||
|
|
||||||
Recent kernel change ([0]) changed inet_csk_accept() prototype. Adapt
|
|
||||||
progs/test_sk_storage_tracing.c to take that into account.
|
|
||||||
|
|
||||||
[0] 92ef0fd55ac8 ("net: change proto and proto_ops accept type")
|
|
||||||
|
|
||||||
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
|
|
||||||
---
|
|
||||||
tools/testing/selftests/bpf/progs/test_sk_storage_tracing.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/tools/testing/selftests/bpf/progs/test_sk_storage_tracing.c b/tools/testing/selftests/bpf/progs/test_sk_storage_tracing.c
|
|
||||||
index 02e718f06e0f..40531e56776e 100644
|
|
||||||
--- a/tools/testing/selftests/bpf/progs/test_sk_storage_tracing.c
|
|
||||||
+++ b/tools/testing/selftests/bpf/progs/test_sk_storage_tracing.c
|
|
||||||
@@ -84,7 +84,7 @@ int BPF_PROG(trace_tcp_connect, struct sock *sk)
|
|
||||||
}
|
|
||||||
|
|
||||||
SEC("fexit/inet_csk_accept")
|
|
||||||
-int BPF_PROG(inet_csk_accept, struct sock *sk, int flags, int *err, bool kern,
|
|
||||||
+int BPF_PROG(inet_csk_accept, struct sock *sk, struct proto_accept_arg *arg,
|
|
||||||
struct sock *accepted_sk)
|
|
||||||
{
|
|
||||||
set_task_info(accepted_sk);
|
|
||||||
--
|
|
||||||
2.43.0
|
|
||||||
|
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
From e3a4f5092e847ec00e2b66c060f2cef52b8d0177 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ihor Solodrai <ihor.solodrai@pm.me>
|
||||||
|
Date: Thu, 14 Nov 2024 12:49:34 -0800
|
||||||
|
Subject: [PATCH bpf-next] selftests/bpf: set test path for
|
||||||
|
token/obj_priv_implicit_token_envvar
|
||||||
|
|
||||||
|
token/obj_priv_implicit_token_envvar test may fail in an environment
|
||||||
|
where the process executing tests can not write to the root path.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
https://github.com/libbpf/libbpf/actions/runs/11844507007/job/33007897936
|
||||||
|
|
||||||
|
Change default path used by the test to /tmp/bpf-token-fs, and make it
|
||||||
|
runtime configurable via an environment variable.
|
||||||
|
|
||||||
|
Signed-off-by: Ihor Solodrai <ihor.solodrai@pm.me>
|
||||||
|
---
|
||||||
|
tools/testing/selftests/bpf/prog_tests/token.c | 18 +++++++++++-------
|
||||||
|
1 file changed, 11 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/tools/testing/selftests/bpf/prog_tests/token.c b/tools/testing/selftests/bpf/prog_tests/token.c
|
||||||
|
index fe86e4fdb89c..39f5414b674b 100644
|
||||||
|
--- a/tools/testing/selftests/bpf/prog_tests/token.c
|
||||||
|
+++ b/tools/testing/selftests/bpf/prog_tests/token.c
|
||||||
|
@@ -828,8 +828,11 @@ static int userns_obj_priv_btf_success(int mnt_fd, struct token_lsm *lsm_skel)
|
||||||
|
return validate_struct_ops_load(mnt_fd, true /* should succeed */);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static const char* token_bpffs_custom_dir() {
|
||||||
|
+ return getenv("BPF_SELFTESTS_BPF_TOKEN_DIR") ? : "/tmp/bpf-token-fs";
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
#define TOKEN_ENVVAR "LIBBPF_BPF_TOKEN_PATH"
|
||||||
|
-#define TOKEN_BPFFS_CUSTOM "/bpf-token-fs"
|
||||||
|
|
||||||
|
static int userns_obj_priv_implicit_token(int mnt_fd, struct token_lsm *lsm_skel)
|
||||||
|
{
|
||||||
|
@@ -892,6 +895,7 @@ static int userns_obj_priv_implicit_token(int mnt_fd, struct token_lsm *lsm_skel
|
||||||
|
|
||||||
|
static int userns_obj_priv_implicit_token_envvar(int mnt_fd, struct token_lsm *lsm_skel)
|
||||||
|
{
|
||||||
|
+ const char *custom_dir = token_bpffs_custom_dir();
|
||||||
|
LIBBPF_OPTS(bpf_object_open_opts, opts);
|
||||||
|
struct dummy_st_ops_success *skel;
|
||||||
|
int err;
|
||||||
|
@@ -909,10 +913,10 @@ static int userns_obj_priv_implicit_token_envvar(int mnt_fd, struct token_lsm *l
|
||||||
|
* BPF token implicitly, unless pointed to it through
|
||||||
|
* LIBBPF_BPF_TOKEN_PATH envvar
|
||||||
|
*/
|
||||||
|
- rmdir(TOKEN_BPFFS_CUSTOM);
|
||||||
|
- if (!ASSERT_OK(mkdir(TOKEN_BPFFS_CUSTOM, 0777), "mkdir_bpffs_custom"))
|
||||||
|
+ rmdir(custom_dir);
|
||||||
|
+ if (!ASSERT_OK(mkdir(custom_dir, 0777), "mkdir_bpffs_custom"))
|
||||||
|
goto err_out;
|
||||||
|
- err = sys_move_mount(mnt_fd, "", AT_FDCWD, TOKEN_BPFFS_CUSTOM, MOVE_MOUNT_F_EMPTY_PATH);
|
||||||
|
+ err = sys_move_mount(mnt_fd, "", AT_FDCWD, custom_dir, MOVE_MOUNT_F_EMPTY_PATH);
|
||||||
|
if (!ASSERT_OK(err, "move_mount_bpffs"))
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
|
@@ -925,7 +929,7 @@ static int userns_obj_priv_implicit_token_envvar(int mnt_fd, struct token_lsm *l
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- err = setenv(TOKEN_ENVVAR, TOKEN_BPFFS_CUSTOM, 1 /*overwrite*/);
|
||||||
|
+ err = setenv(TOKEN_ENVVAR, custom_dir, 1 /*overwrite*/);
|
||||||
|
if (!ASSERT_OK(err, "setenv_token_path"))
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
|
@@ -951,11 +955,11 @@ static int userns_obj_priv_implicit_token_envvar(int mnt_fd, struct token_lsm *l
|
||||||
|
if (!ASSERT_ERR(err, "obj_empty_token_path_load"))
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
|
- rmdir(TOKEN_BPFFS_CUSTOM);
|
||||||
|
+ rmdir(custom_dir);
|
||||||
|
unsetenv(TOKEN_ENVVAR);
|
||||||
|
return 0;
|
||||||
|
err_out:
|
||||||
|
- rmdir(TOKEN_BPFFS_CUSTOM);
|
||||||
|
+ rmdir(custom_dir);
|
||||||
|
unsetenv(TOKEN_ENVVAR);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.47.0
|
||||||
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
From f267f262815033452195f46c43b572159262f533 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Daniel Borkmann <daniel@iogearbox.net>
|
|
||||||
Date: Tue, 5 Mar 2024 10:08:28 +0100
|
|
||||||
Subject: [PATCH 2/2] xdp, bonding: Fix feature flags when there are no slave
|
|
||||||
devs anymore
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
Commit 9b0ed890ac2a ("bonding: do not report NETDEV_XDP_ACT_XSK_ZEROCOPY")
|
|
||||||
changed the driver from reporting everything as supported before a device
|
|
||||||
was bonded into having the driver report that no XDP feature is supported
|
|
||||||
until a real device is bonded as it seems to be more truthful given
|
|
||||||
eventually real underlying devices decide what XDP features are supported.
|
|
||||||
|
|
||||||
The change however did not take into account when all slave devices get
|
|
||||||
removed from the bond device. In this case after 9b0ed890ac2a, the driver
|
|
||||||
keeps reporting a feature mask of 0x77, that is, NETDEV_XDP_ACT_MASK &
|
|
||||||
~NETDEV_XDP_ACT_XSK_ZEROCOPY whereas it should have reported a feature
|
|
||||||
mask of 0.
|
|
||||||
|
|
||||||
Fix it by resetting XDP feature flags in the same way as if no XDP program
|
|
||||||
is attached to the bond device. This was uncovered by the XDP bond selftest
|
|
||||||
which let BPF CI fail. After adjusting the starting masks on the latter
|
|
||||||
to 0 instead of NETDEV_XDP_ACT_MASK the test passes again together with
|
|
||||||
this fix.
|
|
||||||
|
|
||||||
Fixes: 9b0ed890ac2a ("bonding: do not report NETDEV_XDP_ACT_XSK_ZEROCOPY")
|
|
||||||
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
|
|
||||||
Cc: Magnus Karlsson <magnus.karlsson@intel.com>
|
|
||||||
Cc: Prashant Batra <prbatra.mail@gmail.com>
|
|
||||||
Cc: Toke Høiland-Jørgensen <toke@redhat.com>
|
|
||||||
Cc: Jakub Kicinski <kuba@kernel.org>
|
|
||||||
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
|
|
||||||
Message-ID: <20240305090829.17131-1-daniel@iogearbox.net>
|
|
||||||
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
|
|
||||||
---
|
|
||||||
drivers/net/bonding/bond_main.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
|
|
||||||
index a11748b8d69b..cd0683bcca03 100644
|
|
||||||
--- a/drivers/net/bonding/bond_main.c
|
|
||||||
+++ b/drivers/net/bonding/bond_main.c
|
|
||||||
@@ -1811,7 +1811,7 @@ void bond_xdp_set_features(struct net_device *bond_dev)
|
|
||||||
|
|
||||||
ASSERT_RTNL();
|
|
||||||
|
|
||||||
- if (!bond_xdp_check(bond)) {
|
|
||||||
+ if (!bond_xdp_check(bond) || !bond_has_slaves(bond)) {
|
|
||||||
xdp_clear_features_flag(bond_dev);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.43.0
|
|
||||||
|
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
From bd06a13f44e15e2e83561ea165061c445a15bd9e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Song Liu <song@kernel.org>
|
||||||
|
Date: Thu, 27 Mar 2025 11:55:28 -0700
|
||||||
|
Subject: [PATCH 4000/4002] selftests/bpf: Fix tests after fields reorder in
|
||||||
|
struct file
|
||||||
|
|
||||||
|
The change in struct file [1] moved f_ref to the 3rd cache line.
|
||||||
|
It made *(u64 *)file dereference invalid from the verifier point of view,
|
||||||
|
because btf_struct_walk() walks into f_lock field, which is 4-byte long.
|
||||||
|
|
||||||
|
Fix the selftests to deference the file pointer as a 4-byte access.
|
||||||
|
|
||||||
|
[1] commit e249056c91a2 ("fs: place f_ref to 3rd cache line in struct file to resolve false sharing")
|
||||||
|
Reported-by: Jakub Kicinski <kuba@kernel.org>
|
||||||
|
Signed-off-by: Song Liu <song@kernel.org>
|
||||||
|
Link: https://lore.kernel.org/r/20250327185528.1740787-1-song@kernel.org
|
||||||
|
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
|
||||||
|
---
|
||||||
|
tools/testing/selftests/bpf/progs/test_module_attach.c | 2 +-
|
||||||
|
tools/testing/selftests/bpf/progs/test_subprogs_extable.c | 6 +++---
|
||||||
|
2 files changed, 4 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/tools/testing/selftests/bpf/progs/test_module_attach.c b/tools/testing/selftests/bpf/progs/test_module_attach.c
|
||||||
|
index fb07f5773888..7f3c233943b3 100644
|
||||||
|
--- a/tools/testing/selftests/bpf/progs/test_module_attach.c
|
||||||
|
+++ b/tools/testing/selftests/bpf/progs/test_module_attach.c
|
||||||
|
@@ -117,7 +117,7 @@ int BPF_PROG(handle_fexit_ret, int arg, struct file *ret)
|
||||||
|
|
||||||
|
bpf_probe_read_kernel(&buf, 8, ret);
|
||||||
|
bpf_probe_read_kernel(&buf, 8, (char *)ret + 256);
|
||||||
|
- *(volatile long long *)ret;
|
||||||
|
+ *(volatile int *)ret;
|
||||||
|
*(volatile int *)&ret->f_mode;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
diff --git a/tools/testing/selftests/bpf/progs/test_subprogs_extable.c b/tools/testing/selftests/bpf/progs/test_subprogs_extable.c
|
||||||
|
index e2a21fbd4e44..dcac69f5928a 100644
|
||||||
|
--- a/tools/testing/selftests/bpf/progs/test_subprogs_extable.c
|
||||||
|
+++ b/tools/testing/selftests/bpf/progs/test_subprogs_extable.c
|
||||||
|
@@ -21,7 +21,7 @@ static __u64 test_cb(struct bpf_map *map, __u32 *key, __u64 *val, void *data)
|
||||||
|
SEC("fexit/bpf_testmod_return_ptr")
|
||||||
|
int BPF_PROG(handle_fexit_ret_subprogs, int arg, struct file *ret)
|
||||||
|
{
|
||||||
|
- *(volatile long *)ret;
|
||||||
|
+ *(volatile int *)ret;
|
||||||
|
*(volatile int *)&ret->f_mode;
|
||||||
|
bpf_for_each_map_elem(&test_array, test_cb, NULL, 0);
|
||||||
|
triggered++;
|
||||||
|
@@ -31,7 +31,7 @@ int BPF_PROG(handle_fexit_ret_subprogs, int arg, struct file *ret)
|
||||||
|
SEC("fexit/bpf_testmod_return_ptr")
|
||||||
|
int BPF_PROG(handle_fexit_ret_subprogs2, int arg, struct file *ret)
|
||||||
|
{
|
||||||
|
- *(volatile long *)ret;
|
||||||
|
+ *(volatile int *)ret;
|
||||||
|
*(volatile int *)&ret->f_mode;
|
||||||
|
bpf_for_each_map_elem(&test_array, test_cb, NULL, 0);
|
||||||
|
triggered++;
|
||||||
|
@@ -41,7 +41,7 @@ int BPF_PROG(handle_fexit_ret_subprogs2, int arg, struct file *ret)
|
||||||
|
SEC("fexit/bpf_testmod_return_ptr")
|
||||||
|
int BPF_PROG(handle_fexit_ret_subprogs3, int arg, struct file *ret)
|
||||||
|
{
|
||||||
|
- *(volatile long *)ret;
|
||||||
|
+ *(volatile int *)ret;
|
||||||
|
*(volatile int *)&ret->f_mode;
|
||||||
|
bpf_for_each_map_elem(&test_array, test_cb, NULL, 0);
|
||||||
|
triggered++;
|
||||||
|
--
|
||||||
|
2.49.0
|
||||||
|
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
From 8be3a12f9f266aaf3f06f0cfe0e90cfe4d956f3d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Song Liu <song@kernel.org>
|
||||||
|
Date: Fri, 28 Mar 2025 12:31:24 -0700
|
||||||
|
Subject: [PATCH 4001/4002] selftests/bpf: Fix verifier_bpf_fastcall test
|
||||||
|
|
||||||
|
Commit [1] moves percpu data on x86 from address 0x000... to address
|
||||||
|
0xfff...
|
||||||
|
|
||||||
|
Before [1]:
|
||||||
|
|
||||||
|
159020: 0000000000030700 0 OBJECT GLOBAL DEFAULT 23 pcpu_hot
|
||||||
|
|
||||||
|
After [1]:
|
||||||
|
|
||||||
|
152602: ffffffff83a3e034 4 OBJECT GLOBAL DEFAULT 35 pcpu_hot
|
||||||
|
|
||||||
|
As a result, verifier_bpf_fastcall tests should now expect a negative
|
||||||
|
value for pcpu_hot, IOW, the disassemble should show "r=" instead of
|
||||||
|
"w=".
|
||||||
|
|
||||||
|
Fix this in the test.
|
||||||
|
|
||||||
|
Note that, a later change created a new variable "cpu_number" for
|
||||||
|
bpf_get_smp_processor_id() [2]. The inlining logic is updated properly
|
||||||
|
as part of this change, so there is no need to fix anything on the
|
||||||
|
kernel side.
|
||||||
|
|
||||||
|
[1] commit 9d7de2aa8b41 ("x86/percpu/64: Use relative percpu offsets")
|
||||||
|
[2] commit 01c7bc5198e9 ("x86/smp: Move cpu number to percpu hot section")
|
||||||
|
Reported-by: Jakub Kicinski <kuba@kernel.org>
|
||||||
|
Signed-off-by: Song Liu <song@kernel.org>
|
||||||
|
Link: https://lore.kernel.org/r/20250328193124.808784-1-song@kernel.org
|
||||||
|
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
|
||||||
|
---
|
||||||
|
tools/testing/selftests/bpf/progs/verifier_bpf_fastcall.c | 6 +++---
|
||||||
|
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/tools/testing/selftests/bpf/progs/verifier_bpf_fastcall.c b/tools/testing/selftests/bpf/progs/verifier_bpf_fastcall.c
|
||||||
|
index a9be6ae49454..c258b0722e04 100644
|
||||||
|
--- a/tools/testing/selftests/bpf/progs/verifier_bpf_fastcall.c
|
||||||
|
+++ b/tools/testing/selftests/bpf/progs/verifier_bpf_fastcall.c
|
||||||
|
@@ -12,7 +12,7 @@ SEC("raw_tp")
|
||||||
|
__arch_x86_64
|
||||||
|
__log_level(4) __msg("stack depth 8")
|
||||||
|
__xlated("4: r5 = 5")
|
||||||
|
-__xlated("5: w0 = ")
|
||||||
|
+__xlated("5: r0 = ")
|
||||||
|
__xlated("6: r0 = &(void __percpu *)(r0)")
|
||||||
|
__xlated("7: r0 = *(u32 *)(r0 +0)")
|
||||||
|
__xlated("8: exit")
|
||||||
|
@@ -704,7 +704,7 @@ SEC("raw_tp")
|
||||||
|
__arch_x86_64
|
||||||
|
__log_level(4) __msg("stack depth 32+0")
|
||||||
|
__xlated("2: r1 = 1")
|
||||||
|
-__xlated("3: w0 =")
|
||||||
|
+__xlated("3: r0 =")
|
||||||
|
__xlated("4: r0 = &(void __percpu *)(r0)")
|
||||||
|
__xlated("5: r0 = *(u32 *)(r0 +0)")
|
||||||
|
/* bpf_loop params setup */
|
||||||
|
@@ -753,7 +753,7 @@ __arch_x86_64
|
||||||
|
__log_level(4) __msg("stack depth 40+0")
|
||||||
|
/* call bpf_get_smp_processor_id */
|
||||||
|
__xlated("2: r1 = 42")
|
||||||
|
-__xlated("3: w0 =")
|
||||||
|
+__xlated("3: r0 =")
|
||||||
|
__xlated("4: r0 = &(void __percpu *)(r0)")
|
||||||
|
__xlated("5: r0 = *(u32 *)(r0 +0)")
|
||||||
|
/* call bpf_get_prandom_u32 */
|
||||||
|
--
|
||||||
|
2.49.0
|
||||||
|
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
From 07be1f644ff9eeb842fd0490ddd824df0828cb0e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Yonghong Song <yonghong.song@linux.dev>
|
||||||
|
Date: Sun, 30 Mar 2025 20:38:28 -0700
|
||||||
|
Subject: [PATCH 4002/4002] selftests/bpf: Fix verifier_private_stack test
|
||||||
|
failure
|
||||||
|
|
||||||
|
Several verifier_private_stack tests failed with latest bpf-next.
|
||||||
|
For example, for 'Private stack, single prog' subtest, the
|
||||||
|
jitted code:
|
||||||
|
func #0:
|
||||||
|
0: f3 0f 1e fa endbr64
|
||||||
|
4: 0f 1f 44 00 00 nopl (%rax,%rax)
|
||||||
|
9: 0f 1f 00 nopl (%rax)
|
||||||
|
c: 55 pushq %rbp
|
||||||
|
d: 48 89 e5 movq %rsp, %rbp
|
||||||
|
10: f3 0f 1e fa endbr64
|
||||||
|
14: 49 b9 58 74 8a 8f 7d 60 00 00 movabsq $0x607d8f8a7458, %r9
|
||||||
|
1e: 65 4c 03 0c 25 28 c0 48 87 addq %gs:-0x78b73fd8, %r9
|
||||||
|
27: bf 2a 00 00 00 movl $0x2a, %edi
|
||||||
|
2c: 49 89 b9 00 ff ff ff movq %rdi, -0x100(%r9)
|
||||||
|
33: 31 c0 xorl %eax, %eax
|
||||||
|
35: c9 leave
|
||||||
|
36: e9 20 5d 0f e1 jmp 0xffffffffe10f5d5b
|
||||||
|
|
||||||
|
The insn 'addq %gs:-0x78b73fd8, %r9' does not match the expected
|
||||||
|
regex 'addq %gs:0x{{.*}}, %r9' and this caused test failure.
|
||||||
|
|
||||||
|
Fix it by changing '%gs:0x{{.*}}' to '%gs:{{.*}}' to accommodate the
|
||||||
|
possible negative offset. A few other subtests are fixed in a similar way.
|
||||||
|
|
||||||
|
Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
|
||||||
|
Link: https://lore.kernel.org/r/20250331033828.365077-1-yonghong.song@linux.dev
|
||||||
|
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
|
||||||
|
---
|
||||||
|
tools/testing/selftests/bpf/progs/verifier_private_stack.c | 6 +++---
|
||||||
|
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/tools/testing/selftests/bpf/progs/verifier_private_stack.c b/tools/testing/selftests/bpf/progs/verifier_private_stack.c
|
||||||
|
index b1fbdf119553..fc91b414364e 100644
|
||||||
|
--- a/tools/testing/selftests/bpf/progs/verifier_private_stack.c
|
||||||
|
+++ b/tools/testing/selftests/bpf/progs/verifier_private_stack.c
|
||||||
|
@@ -27,7 +27,7 @@ __description("Private stack, single prog")
|
||||||
|
__success
|
||||||
|
__arch_x86_64
|
||||||
|
__jited(" movabsq $0x{{.*}}, %r9")
|
||||||
|
-__jited(" addq %gs:0x{{.*}}, %r9")
|
||||||
|
+__jited(" addq %gs:{{.*}}, %r9")
|
||||||
|
__jited(" movl $0x2a, %edi")
|
||||||
|
__jited(" movq %rdi, -0x100(%r9)")
|
||||||
|
__naked void private_stack_single_prog(void)
|
||||||
|
@@ -74,7 +74,7 @@ __success
|
||||||
|
__arch_x86_64
|
||||||
|
/* private stack fp for the main prog */
|
||||||
|
__jited(" movabsq $0x{{.*}}, %r9")
|
||||||
|
-__jited(" addq %gs:0x{{.*}}, %r9")
|
||||||
|
+__jited(" addq %gs:{{.*}}, %r9")
|
||||||
|
__jited(" movl $0x2a, %edi")
|
||||||
|
__jited(" movq %rdi, -0x200(%r9)")
|
||||||
|
__jited(" pushq %r9")
|
||||||
|
@@ -122,7 +122,7 @@ __jited(" pushq %rbp")
|
||||||
|
__jited(" movq %rsp, %rbp")
|
||||||
|
__jited(" endbr64")
|
||||||
|
__jited(" movabsq $0x{{.*}}, %r9")
|
||||||
|
-__jited(" addq %gs:0x{{.*}}, %r9")
|
||||||
|
+__jited(" addq %gs:{{.*}}, %r9")
|
||||||
|
__jited(" pushq %r9")
|
||||||
|
__jited(" callq")
|
||||||
|
__jited(" popq %r9")
|
||||||
|
--
|
||||||
|
2.49.0
|
||||||
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
# btf_dump -- need to disable data dump sub-tests
|
|
||||||
core_retro
|
|
||||||
cpu_mask
|
|
||||||
hashmap
|
|
||||||
legacy_printk
|
|
||||||
perf_buffer
|
|
||||||
section_names
|
|
||||||
|
|
||||||
@@ -1,49 +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
|
|
||||||
get_branch_snapshot
|
|
||||||
get_stackid_cannot_attach
|
|
||||||
global_data
|
|
||||||
global_data_init
|
|
||||||
global_func_args
|
|
||||||
hashmap
|
|
||||||
legacy_printk
|
|
||||||
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
|
|
||||||
sockmap_ktls
|
|
||||||
spinlock
|
|
||||||
stacktrace_map
|
|
||||||
stacktrace_map_raw_tp
|
|
||||||
static_linked
|
|
||||||
task_fd_query_rawtp
|
|
||||||
task_fd_query_tp
|
|
||||||
tc_bpf
|
|
||||||
tcp_estats
|
|
||||||
test_global_funcs/arg_tag_ctx*
|
|
||||||
tp_attach_query
|
|
||||||
usdt/urand_pid_attach
|
|
||||||
xdp
|
|
||||||
xdp_noinline
|
|
||||||
xdp_perf
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
# TEMPORARY
|
# TEMPORARY
|
||||||
btf_dump/btf_dump: syntax
|
btf_dump/btf_dump: syntax
|
||||||
|
bpf_cookie/perf_event
|
||||||
kprobe_multi_bench_attach
|
kprobe_multi_bench_attach
|
||||||
core_reloc/enum64val
|
core_reloc/enum64val
|
||||||
core_reloc/size___diff_sz
|
core_reloc/size___diff_sz
|
||||||
@@ -13,3 +14,4 @@ tc_redirect/tc_redirect_dtime # uapi breakage after net-next commit 885c36e59f46
|
|||||||
migrate_reuseport/IPv4 TCP_NEW_SYN_RECV reqsk_timer_handler # flaky, under investigation
|
migrate_reuseport/IPv4 TCP_NEW_SYN_RECV reqsk_timer_handler # flaky, under investigation
|
||||||
migrate_reuseport/IPv6 TCP_NEW_SYN_RECV reqsk_timer_handler # flaky, under investigation
|
migrate_reuseport/IPv6 TCP_NEW_SYN_RECV reqsk_timer_handler # flaky, under investigation
|
||||||
verify_pkcs7_sig # keeps failing
|
verify_pkcs7_sig # keeps failing
|
||||||
|
verif_scale_pyperf600 # fails on newer Clangs
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
# This complements ALLOWLIST-5.5.0 but excludes subtest that can't work on 5.5
|
|
||||||
|
|
||||||
btf # "size check test", "func (Non zero vlen)"
|
|
||||||
tailcalls # tailcall_bpf2bpf_1, tailcall_bpf2bpf_2, tailcall_bpf2bpf_3
|
|
||||||
tc_bpf/tc_bpf_non_root
|
|
||||||
37
ci/vmtest/configs/run-vmtest.env
Normal file
37
ci/vmtest/configs/run-vmtest.env
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# This file is sourced by libbpf/ci/run-vmtest Github Action scripts.
|
||||||
|
|
||||||
|
# $SELFTESTS_BPF and $VMTEST_CONFIGS are set in the workflow, before
|
||||||
|
# libbpf/ci/run-vmtest action is called
|
||||||
|
# See .github/workflows/kernel-test.yml
|
||||||
|
|
||||||
|
ALLOWLIST_FILES=(
|
||||||
|
"${SELFTESTS_BPF}/ALLOWLIST"
|
||||||
|
"${SELFTESTS_BPF}/ALLOWLIST.${ARCH}"
|
||||||
|
"${VMTEST_CONFIGS}/ALLOWLIST"
|
||||||
|
"${VMTEST_CONFIGS}/ALLOWLIST-${KERNEL}"
|
||||||
|
"${VMTEST_CONFIGS}/ALLOWLIST-${KERNEL}.${ARCH}"
|
||||||
|
)
|
||||||
|
|
||||||
|
DENYLIST_FILES=(
|
||||||
|
"${SELFTESTS_BPF}/DENYLIST"
|
||||||
|
"${SELFTESTS_BPF}/DENYLIST.${ARCH}"
|
||||||
|
"${VMTEST_CONFIGS}/DENYLIST"
|
||||||
|
"${VMTEST_CONFIGS}/DENYLIST-${KERNEL}"
|
||||||
|
"${VMTEST_CONFIGS}/DENYLIST-${KERNEL}.${ARCH}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Export pipe-separated strings, because bash doesn't support array export
|
||||||
|
export SELFTESTS_BPF_ALLOWLIST_FILES=$(IFS="|"; echo "${ALLOWLIST_FILES[*]}")
|
||||||
|
export SELFTESTS_BPF_DENYLIST_FILES=$(IFS="|"; echo "${DENYLIST_FILES[*]}")
|
||||||
|
|
||||||
|
if [[ "${LLVM_VERSION}" -lt 18 ]]; then
|
||||||
|
echo "KERNEL_TEST=test_progs test_progs_no_alu32 test_maps test_verifier" >> $GITHUB_ENV
|
||||||
|
else # all
|
||||||
|
echo "KERNEL_TEST=test_progs test_progs_cpuv4 test_progs_no_alu32 test_maps test_verifier" >> $GITHUB_ENV
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "cp -R ${SELFTESTS_BPF} ${GITHUB_WORKSPACE}/selftests"
|
||||||
|
mkdir -p "${GITHUB_WORKSPACE}/selftests"
|
||||||
|
cp -R "${SELFTESTS_BPF}" "${GITHUB_WORKSPACE}/selftests"
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
# shellcheck shell=bash
|
|
||||||
|
|
||||||
# $1 - start or end
|
|
||||||
# $2 - fold identifier, no spaces
|
|
||||||
# $3 - fold section description
|
|
||||||
foldable() {
|
|
||||||
local YELLOW='\033[1;33m'
|
|
||||||
local NOCOLOR='\033[0m'
|
|
||||||
if [ $1 = "start" ]; then
|
|
||||||
line="::group::$2"
|
|
||||||
if [ ! -z "${3:-}" ]; then
|
|
||||||
line="$line - ${YELLOW}$3${NOCOLOR}"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
line="::endgroup::"
|
|
||||||
fi
|
|
||||||
echo -e "$line"
|
|
||||||
}
|
|
||||||
|
|
||||||
__print() {
|
|
||||||
local TITLE=""
|
|
||||||
if [[ -n $2 ]]; then
|
|
||||||
TITLE=" title=$2"
|
|
||||||
fi
|
|
||||||
echo "::$1${TITLE}::$3"
|
|
||||||
}
|
|
||||||
|
|
||||||
# $1 - title
|
|
||||||
# $2 - message
|
|
||||||
print_error() {
|
|
||||||
__print error $1 $2
|
|
||||||
}
|
|
||||||
|
|
||||||
# $1 - title
|
|
||||||
# $2 - message
|
|
||||||
print_notice() {
|
|
||||||
__print notice $1 $2
|
|
||||||
}
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
source $(cd $(dirname $0) && pwd)/helpers.sh
|
|
||||||
|
|
||||||
ARCH=$(uname -m)
|
|
||||||
|
|
||||||
STATUS_FILE=/exitstatus
|
|
||||||
|
|
||||||
read_lists() {
|
|
||||||
(for path in "$@"; do
|
|
||||||
if [[ -s "$path" ]]; then
|
|
||||||
cat "$path"
|
|
||||||
fi;
|
|
||||||
done) | cut -d'#' -f1 | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | tr -s '\n' ','
|
|
||||||
}
|
|
||||||
|
|
||||||
test_progs() {
|
|
||||||
if [[ "${KERNEL}" != '4.9.0' ]]; then
|
|
||||||
foldable start test_progs "Testing test_progs"
|
|
||||||
# "&& true" does not change the return code (it is not executed
|
|
||||||
# if the Python script fails), but it prevents exiting on a
|
|
||||||
# failure due to the "set -e".
|
|
||||||
./test_progs ${DENYLIST:+-d"$DENYLIST"} ${ALLOWLIST:+-a"$ALLOWLIST"} && true
|
|
||||||
echo "test_progs:$?" >> "${STATUS_FILE}"
|
|
||||||
foldable end test_progs
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
test_progs_no_alu32() {
|
|
||||||
foldable start test_progs-no_alu32 "Testing test_progs-no_alu32"
|
|
||||||
./test_progs-no_alu32 ${DENYLIST:+-d"$DENYLIST"} ${ALLOWLIST:+-a"$ALLOWLIST"} && true
|
|
||||||
echo "test_progs-no_alu32:$?" >> "${STATUS_FILE}"
|
|
||||||
foldable end test_progs-no_alu32
|
|
||||||
}
|
|
||||||
|
|
||||||
test_maps() {
|
|
||||||
if [[ "${KERNEL}" == 'latest' ]]; then
|
|
||||||
foldable start test_maps "Testing test_maps"
|
|
||||||
./test_maps && true
|
|
||||||
echo "test_maps:$?" >> "${STATUS_FILE}"
|
|
||||||
foldable end test_maps
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
test_verifier() {
|
|
||||||
if [[ "${KERNEL}" == 'latest' ]]; then
|
|
||||||
foldable start test_verifier "Testing test_verifier"
|
|
||||||
./test_verifier && true
|
|
||||||
echo "test_verifier:$?" >> "${STATUS_FILE}"
|
|
||||||
foldable end test_verifier
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
foldable end vm_init
|
|
||||||
|
|
||||||
foldable start kernel_config "Kconfig"
|
|
||||||
|
|
||||||
zcat /proc/config.gz
|
|
||||||
|
|
||||||
foldable end kernel_config
|
|
||||||
|
|
||||||
|
|
||||||
configs_path=/${PROJECT_NAME}/selftests/bpf
|
|
||||||
local_configs_path=${PROJECT_NAME}/vmtest/configs
|
|
||||||
DENYLIST=$(read_lists \
|
|
||||||
"$configs_path/DENYLIST" \
|
|
||||||
"$configs_path/DENYLIST.${ARCH}" \
|
|
||||||
"$local_configs_path/DENYLIST" \
|
|
||||||
"$local_configs_path/DENYLIST-${KERNEL}" \
|
|
||||||
"$local_configs_path/DENYLIST-${KERNEL}.${ARCH}" \
|
|
||||||
)
|
|
||||||
ALLOWLIST=$(read_lists \
|
|
||||||
"$configs_path/ALLOWLIST" \
|
|
||||||
"$configs_path/ALLOWLIST.${ARCH}" \
|
|
||||||
"$local_configs_path/ALLOWLIST" \
|
|
||||||
"$local_configs_path/ALLOWLIST-${KERNEL}" \
|
|
||||||
"$local_configs_path/ALLOWLIST-${KERNEL}.${ARCH}" \
|
|
||||||
)
|
|
||||||
|
|
||||||
echo "DENYLIST: ${DENYLIST}"
|
|
||||||
echo "ALLOWLIST: ${ALLOWLIST}"
|
|
||||||
|
|
||||||
cd ${PROJECT_NAME}/selftests/bpf
|
|
||||||
|
|
||||||
if [ $# -eq 0 ]; then
|
|
||||||
test_progs
|
|
||||||
test_progs_no_alu32
|
|
||||||
# test_maps
|
|
||||||
test_verifier
|
|
||||||
else
|
|
||||||
for test_name in "$@"; do
|
|
||||||
"${test_name}"
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
@@ -100,10 +100,26 @@ described in more detail in the footnotes.
|
|||||||
| | | ``uretprobe.s+`` [#uprobe]_ | Yes |
|
| | | ``uretprobe.s+`` [#uprobe]_ | Yes |
|
||||||
+ + +----------------------------------+-----------+
|
+ + +----------------------------------+-----------+
|
||||||
| | | ``usdt+`` [#usdt]_ | |
|
| | | ``usdt+`` [#usdt]_ | |
|
||||||
|
+ + +----------------------------------+-----------+
|
||||||
|
| | | ``usdt.s+`` [#usdt]_ | Yes |
|
||||||
+ +----------------------------------------+----------------------------------+-----------+
|
+ +----------------------------------------+----------------------------------+-----------+
|
||||||
| | ``BPF_TRACE_KPROBE_MULTI`` | ``kprobe.multi+`` [#kpmulti]_ | |
|
| | ``BPF_TRACE_KPROBE_MULTI`` | ``kprobe.multi+`` [#kpmulti]_ | |
|
||||||
+ + +----------------------------------+-----------+
|
+ + +----------------------------------+-----------+
|
||||||
| | | ``kretprobe.multi+`` [#kpmulti]_ | |
|
| | | ``kretprobe.multi+`` [#kpmulti]_ | |
|
||||||
|
+ +----------------------------------------+----------------------------------+-----------+
|
||||||
|
| | ``BPF_TRACE_KPROBE_SESSION`` | ``kprobe.session+`` [#kpmulti]_ | |
|
||||||
|
+ +----------------------------------------+----------------------------------+-----------+
|
||||||
|
| | ``BPF_TRACE_UPROBE_MULTI`` | ``uprobe.multi+`` [#upmul]_ | |
|
||||||
|
+ + +----------------------------------+-----------+
|
||||||
|
| | | ``uprobe.multi.s+`` [#upmul]_ | Yes |
|
||||||
|
+ + +----------------------------------+-----------+
|
||||||
|
| | | ``uretprobe.multi+`` [#upmul]_ | |
|
||||||
|
+ + +----------------------------------+-----------+
|
||||||
|
| | | ``uretprobe.multi.s+`` [#upmul]_ | Yes |
|
||||||
|
+ +----------------------------------------+----------------------------------+-----------+
|
||||||
|
| | ``BPF_TRACE_UPROBE_SESSION`` | ``uprobe.session+`` [#upmul]_ | |
|
||||||
|
+ + +----------------------------------+-----------+
|
||||||
|
| | | ``uprobe.session.s+`` [#upmul]_ | Yes |
|
||||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||||
| ``BPF_PROG_TYPE_LIRC_MODE2`` | ``BPF_LIRC_MODE2`` | ``lirc_mode2`` | |
|
| ``BPF_PROG_TYPE_LIRC_MODE2`` | ``BPF_LIRC_MODE2`` | ``lirc_mode2`` | |
|
||||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||||
@@ -121,6 +137,8 @@ described in more detail in the footnotes.
|
|||||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||||
| ``BPF_PROG_TYPE_LWT_XMIT`` | | ``lwt_xmit`` | |
|
| ``BPF_PROG_TYPE_LWT_XMIT`` | | ``lwt_xmit`` | |
|
||||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||||
|
| ``BPF_PROG_TYPE_NETFILTER`` | | ``netfilter`` | |
|
||||||
|
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||||
| ``BPF_PROG_TYPE_PERF_EVENT`` | | ``perf_event`` | |
|
| ``BPF_PROG_TYPE_PERF_EVENT`` | | ``perf_event`` | |
|
||||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||||
| ``BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE`` | | ``raw_tp.w+`` [#rawtp]_ | |
|
| ``BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE`` | | ``raw_tp.w+`` [#rawtp]_ | |
|
||||||
@@ -131,11 +149,23 @@ described in more detail in the footnotes.
|
|||||||
+ + +----------------------------------+-----------+
|
+ + +----------------------------------+-----------+
|
||||||
| | | ``raw_tracepoint+`` | |
|
| | | ``raw_tracepoint+`` | |
|
||||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||||
| ``BPF_PROG_TYPE_SCHED_ACT`` | | ``action`` | |
|
| ``BPF_PROG_TYPE_SCHED_ACT`` | | ``action`` [#tc_legacy]_ | |
|
||||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||||
| ``BPF_PROG_TYPE_SCHED_CLS`` | | ``classifier`` | |
|
| ``BPF_PROG_TYPE_SCHED_CLS`` | | ``classifier`` [#tc_legacy]_ | |
|
||||||
+ + +----------------------------------+-----------+
|
+ + +----------------------------------+-----------+
|
||||||
| | | ``tc`` | |
|
| | | ``tc`` [#tc_legacy]_ | |
|
||||||
|
+ +----------------------------------------+----------------------------------+-----------+
|
||||||
|
| | ``BPF_NETKIT_PRIMARY`` | ``netkit/primary`` | |
|
||||||
|
+ +----------------------------------------+----------------------------------+-----------+
|
||||||
|
| | ``BPF_NETKIT_PEER`` | ``netkit/peer`` | |
|
||||||
|
+ +----------------------------------------+----------------------------------+-----------+
|
||||||
|
| | ``BPF_TCX_INGRESS`` | ``tc/ingress`` | |
|
||||||
|
+ +----------------------------------------+----------------------------------+-----------+
|
||||||
|
| | ``BPF_TCX_EGRESS`` | ``tc/egress`` | |
|
||||||
|
+ +----------------------------------------+----------------------------------+-----------+
|
||||||
|
| | ``BPF_TCX_INGRESS`` | ``tcx/ingress`` | |
|
||||||
|
+ +----------------------------------------+----------------------------------+-----------+
|
||||||
|
| | ``BPF_TCX_EGRESS`` | ``tcx/egress`` | |
|
||||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||||
| ``BPF_PROG_TYPE_SK_LOOKUP`` | ``BPF_SK_LOOKUP`` | ``sk_lookup`` | |
|
| ``BPF_PROG_TYPE_SK_LOOKUP`` | ``BPF_SK_LOOKUP`` | ``sk_lookup`` | |
|
||||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||||
@@ -155,7 +185,9 @@ described in more detail in the footnotes.
|
|||||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||||
| ``BPF_PROG_TYPE_SOCK_OPS`` | ``BPF_CGROUP_SOCK_OPS`` | ``sockops`` | |
|
| ``BPF_PROG_TYPE_SOCK_OPS`` | ``BPF_CGROUP_SOCK_OPS`` | ``sockops`` | |
|
||||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||||
| ``BPF_PROG_TYPE_STRUCT_OPS`` | | ``struct_ops+`` | |
|
| ``BPF_PROG_TYPE_STRUCT_OPS`` | | ``struct_ops+`` [#struct_ops]_ | |
|
||||||
|
+ + +----------------------------------+-----------+
|
||||||
|
| | | ``struct_ops.s+`` [#struct_ops]_ | Yes |
|
||||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||||
| ``BPF_PROG_TYPE_SYSCALL`` | | ``syscall`` | Yes |
|
| ``BPF_PROG_TYPE_SYSCALL`` | | ``syscall`` | Yes |
|
||||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||||
@@ -203,11 +235,19 @@ described in more detail in the footnotes.
|
|||||||
non-negative integer.
|
non-negative integer.
|
||||||
.. [#ksyscall] The ``ksyscall`` attach format is ``ksyscall/<syscall>``.
|
.. [#ksyscall] The ``ksyscall`` attach format is ``ksyscall/<syscall>``.
|
||||||
.. [#uprobe] The ``uprobe`` attach format is ``uprobe[.s]/<path>:<function>[+<offset>]``.
|
.. [#uprobe] The ``uprobe`` attach format is ``uprobe[.s]/<path>:<function>[+<offset>]``.
|
||||||
|
.. [#upmul] The ``uprobe.multi`` attach format is ``uprobe.multi[.s]/<path>:<function-pattern>``
|
||||||
|
where ``function-pattern`` supports ``*`` and ``?`` wildcards.
|
||||||
.. [#usdt] The ``usdt`` attach format is ``usdt/<path>:<provider>:<name>``.
|
.. [#usdt] The ``usdt`` attach format is ``usdt/<path>:<provider>:<name>``.
|
||||||
.. [#kpmulti] The ``kprobe.multi`` attach format is ``kprobe.multi/<pattern>`` where ``pattern``
|
.. [#kpmulti] The ``kprobe.multi`` attach format is ``kprobe.multi/<pattern>`` where ``pattern``
|
||||||
supports ``*`` and ``?`` wildcards. Valid characters for pattern are
|
supports ``*`` and ``?`` wildcards. Valid characters for pattern are
|
||||||
``a-zA-Z0-9_.*?``.
|
``a-zA-Z0-9_.*?``.
|
||||||
.. [#lsm] The ``lsm`` attachment format is ``lsm[.s]/<hook>``.
|
.. [#lsm] The ``lsm`` attachment format is ``lsm[.s]/<hook>``.
|
||||||
.. [#rawtp] The ``raw_tp`` attach format is ``raw_tracepoint[.w]/<tracepoint>``.
|
.. [#rawtp] The ``raw_tp`` attach format is ``raw_tracepoint[.w]/<tracepoint>``.
|
||||||
|
.. [#tc_legacy] The ``tc``, ``classifier`` and ``action`` attach types are deprecated, use
|
||||||
|
``tcx/*`` instead.
|
||||||
|
.. [#struct_ops] The ``struct_ops`` attach format supports ``struct_ops[.s]/<name>`` convention,
|
||||||
|
but ``name`` is ignored and it is recommended to just use plain
|
||||||
|
``SEC("struct_ops[.s]")``. The attachments are defined in a struct initializer
|
||||||
|
that is tagged with ``SEC(".struct_ops[.link]")``.
|
||||||
.. [#tp] The ``tracepoint`` attach format is ``tracepoint/<category>/<name>``.
|
.. [#tp] The ``tracepoint`` attach format is ``tracepoint/<category>/<name>``.
|
||||||
.. [#iter] The ``iter`` attach format is ``iter[.s]/<struct-name>``.
|
.. [#iter] The ``iter`` attach format is ``iter[.s]/<struct-name>``.
|
||||||
|
|||||||
58
fuzz/readme.md
Normal file
58
fuzz/readme.md
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
# About fuzzing
|
||||||
|
|
||||||
|
Fuzzing is done by [OSS-Fuzz](https://google.github.io/oss-fuzz/).
|
||||||
|
It works by creating a project-specific binary that combines fuzzer
|
||||||
|
itself and a project provided entry point named
|
||||||
|
`LLVMFuzzerTestOneInput()`. When invoked, this executable either
|
||||||
|
searches for new test cases or runs an existing test case.
|
||||||
|
|
||||||
|
File `fuzz/bpf-object-fuzzer.c` defines an entry point for the robot:
|
||||||
|
- robot supplies bytes supposed to be an ELF file;
|
||||||
|
- wrapper invokes `bpf_object__open_mem()` to process these bytes.
|
||||||
|
|
||||||
|
File `scripts/build-fuzzers.sh` provides a recipe for fuzzer
|
||||||
|
infrastructure on how to build the executable described above (see
|
||||||
|
[here](https://github.com/google/oss-fuzz/tree/master/projects/libbpf)).
|
||||||
|
|
||||||
|
# Reproducing fuzzing errors
|
||||||
|
|
||||||
|
## Official way
|
||||||
|
|
||||||
|
OSS-Fuzz project describes error reproduction steps in the official
|
||||||
|
[documentation](https://google.github.io/oss-fuzz/advanced-topics/reproducing/).
|
||||||
|
Suppose you received an email linking to the fuzzer generated test
|
||||||
|
case, or got one as an artifact of the `CIFuzz` job (e.g. like
|
||||||
|
[here](https://github.com/libbpf/libbpf/actions/runs/16375110681)).
|
||||||
|
Actions to reproduce the error locally are:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone --depth=1 https://github.com/google/oss-fuzz.git
|
||||||
|
cd oss-fuzz
|
||||||
|
python infra/helper.py pull_images
|
||||||
|
python infra/helper.py build_image libbpf
|
||||||
|
python infra/helper.py build_fuzzers --sanitizer address libbpf <path-to-libbpf-checkout>
|
||||||
|
python infra/helper.py reproduce libbpf bpf-object-fuzzer <path-to-test-case>
|
||||||
|
```
|
||||||
|
|
||||||
|
`<path-to-test-case>` is usually a `crash-<many-hex-digits>` file w/o
|
||||||
|
extension, CI job wraps it into zip archive and attaches as an artifact.
|
||||||
|
|
||||||
|
To recompile after some fixes, repeat the `build_fuzzers` and
|
||||||
|
`reproduce` steps after modifying source code in
|
||||||
|
`<path-to-libbpf-checkout>`.
|
||||||
|
|
||||||
|
Note: the `build_fuzzers` step creates a binary
|
||||||
|
`build/out/libbpf/bpf-object-fuzzer`, it can be executed directly if
|
||||||
|
your environment is compatible.
|
||||||
|
|
||||||
|
## Simple way
|
||||||
|
|
||||||
|
From the project root:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
SKIP_LIBELF_REBUILD=1 scripts/build-fuzzers.sh
|
||||||
|
out/bpf-object-fuzzer <path-to-test-case>
|
||||||
|
```
|
||||||
|
|
||||||
|
`out/bpf-object-fuzzer` is the fuzzer executable described earlier,
|
||||||
|
can be run with gdb etc.
|
||||||
@@ -123,6 +123,14 @@
|
|||||||
BPF_LD_IMM64_RAW_FULL(DST, BPF_PSEUDO_MAP_VALUE, 0, 0, \
|
BPF_LD_IMM64_RAW_FULL(DST, BPF_PSEUDO_MAP_VALUE, 0, 0, \
|
||||||
MAP_FD, VALUE_OFF)
|
MAP_FD, VALUE_OFF)
|
||||||
|
|
||||||
|
#define BPF_JMP_REG(OP, DST, SRC, OFF) \
|
||||||
|
((struct bpf_insn) { \
|
||||||
|
.code = BPF_JMP | BPF_OP(OP) | BPF_X, \
|
||||||
|
.dst_reg = DST, \
|
||||||
|
.src_reg = SRC, \
|
||||||
|
.off = OFF, \
|
||||||
|
.imm = 0 })
|
||||||
|
|
||||||
#define BPF_JMP_IMM(OP, DST, IMM, OFF) \
|
#define BPF_JMP_IMM(OP, DST, IMM, OFF) \
|
||||||
((struct bpf_insn) { \
|
((struct bpf_insn) { \
|
||||||
.code = BPF_JMP | BPF_OP(OP) | BPF_K, \
|
.code = BPF_JMP | BPF_OP(OP) | BPF_K, \
|
||||||
|
|||||||
@@ -43,4 +43,18 @@
|
|||||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||||
#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
|
#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
|
||||||
|
|
||||||
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||||
|
#define be32_to_cpu(x) __builtin_bswap32(x)
|
||||||
|
#define cpu_to_be32(x) __builtin_bswap32(x)
|
||||||
|
#define be64_to_cpu(x) __builtin_bswap64(x)
|
||||||
|
#define cpu_to_be64(x) __builtin_bswap64(x)
|
||||||
|
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
|
#define be32_to_cpu(x) (x)
|
||||||
|
#define cpu_to_be32(x) (x)
|
||||||
|
#define be64_to_cpu(x) (x)
|
||||||
|
#define cpu_to_be64(x) (x)
|
||||||
|
#else
|
||||||
|
# error "__BYTE_ORDER__ undefined or invalid"
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -30,4 +30,7 @@ struct list_head {
|
|||||||
struct list_head *next, *prev;
|
struct list_head *next, *prev;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* needed on Android/Termux, where this linux/types.h is included by other include files */
|
||||||
|
typedef unsigned __bitwise __poll_t;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
* modify it under the terms of version 2 of the GNU General Public
|
* modify it under the terms of version 2 of the GNU General Public
|
||||||
* License as published by the Free Software Foundation.
|
* License as published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
#ifndef _UAPI__LINUX_BPF_H__
|
#ifndef __LINUX_BPF_H__
|
||||||
#define _UAPI__LINUX_BPF_H__
|
#define __LINUX_BPF_H__
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/bpf_common.h>
|
#include <linux/bpf_common.h>
|
||||||
@@ -51,6 +51,9 @@
|
|||||||
#define BPF_XCHG (0xe0 | BPF_FETCH) /* atomic exchange */
|
#define BPF_XCHG (0xe0 | BPF_FETCH) /* atomic exchange */
|
||||||
#define BPF_CMPXCHG (0xf0 | BPF_FETCH) /* atomic compare-and-write */
|
#define BPF_CMPXCHG (0xf0 | BPF_FETCH) /* atomic compare-and-write */
|
||||||
|
|
||||||
|
#define BPF_LOAD_ACQ 0x100 /* load-acquire */
|
||||||
|
#define BPF_STORE_REL 0x110 /* store-release */
|
||||||
|
|
||||||
enum bpf_cond_pseudo_jmp {
|
enum bpf_cond_pseudo_jmp {
|
||||||
BPF_MAY_GOTO = 0,
|
BPF_MAY_GOTO = 0,
|
||||||
};
|
};
|
||||||
@@ -116,6 +119,14 @@ enum bpf_cgroup_iter_order {
|
|||||||
BPF_CGROUP_ITER_DESCENDANTS_PRE, /* walk descendants in pre-order. */
|
BPF_CGROUP_ITER_DESCENDANTS_PRE, /* walk descendants in pre-order. */
|
||||||
BPF_CGROUP_ITER_DESCENDANTS_POST, /* walk descendants in post-order. */
|
BPF_CGROUP_ITER_DESCENDANTS_POST, /* walk descendants in post-order. */
|
||||||
BPF_CGROUP_ITER_ANCESTORS_UP, /* walk ancestors upward. */
|
BPF_CGROUP_ITER_ANCESTORS_UP, /* walk ancestors upward. */
|
||||||
|
/*
|
||||||
|
* Walks the immediate children of the specified parent
|
||||||
|
* cgroup_subsys_state. Unlike BPF_CGROUP_ITER_DESCENDANTS_PRE,
|
||||||
|
* BPF_CGROUP_ITER_DESCENDANTS_POST, and BPF_CGROUP_ITER_ANCESTORS_UP
|
||||||
|
* the iterator does not include the specified parent as one of the
|
||||||
|
* returned iterator elements.
|
||||||
|
*/
|
||||||
|
BPF_CGROUP_ITER_CHILDREN,
|
||||||
};
|
};
|
||||||
|
|
||||||
union bpf_iter_link_info {
|
union bpf_iter_link_info {
|
||||||
@@ -447,6 +458,7 @@ union bpf_iter_link_info {
|
|||||||
* * **struct bpf_map_info**
|
* * **struct bpf_map_info**
|
||||||
* * **struct bpf_btf_info**
|
* * **struct bpf_btf_info**
|
||||||
* * **struct bpf_link_info**
|
* * **struct bpf_link_info**
|
||||||
|
* * **struct bpf_token_info**
|
||||||
*
|
*
|
||||||
* Return
|
* Return
|
||||||
* Returns zero on success. On error, -1 is returned and *errno*
|
* Returns zero on success. On error, -1 is returned and *errno*
|
||||||
@@ -903,6 +915,27 @@ union bpf_iter_link_info {
|
|||||||
* A new file descriptor (a nonnegative integer), or -1 if an
|
* A new file descriptor (a nonnegative integer), or -1 if an
|
||||||
* error occurred (in which case, *errno* is set appropriately).
|
* error occurred (in which case, *errno* is set appropriately).
|
||||||
*
|
*
|
||||||
|
* BPF_PROG_STREAM_READ_BY_FD
|
||||||
|
* Description
|
||||||
|
* Read data of a program's BPF stream. The program is identified
|
||||||
|
* by *prog_fd*, and the stream is identified by the *stream_id*.
|
||||||
|
* The data is copied to a buffer pointed to by *stream_buf*, and
|
||||||
|
* filled less than or equal to *stream_buf_len* bytes.
|
||||||
|
*
|
||||||
|
* Return
|
||||||
|
* Number of bytes read from the stream on success, or -1 if an
|
||||||
|
* error occurred (in which case, *errno* is set appropriately).
|
||||||
|
*
|
||||||
|
* BPF_PROG_ASSOC_STRUCT_OPS
|
||||||
|
* Description
|
||||||
|
* Associate a BPF program with a struct_ops map. The struct_ops
|
||||||
|
* map is identified by *map_fd* and the BPF program is
|
||||||
|
* identified by *prog_fd*.
|
||||||
|
*
|
||||||
|
* Return
|
||||||
|
* 0 on success or -1 if an error occurred (in which case,
|
||||||
|
* *errno* is set appropriately).
|
||||||
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* eBPF objects (maps and programs) can be shared between processes.
|
* eBPF objects (maps and programs) can be shared between processes.
|
||||||
*
|
*
|
||||||
@@ -958,6 +991,8 @@ enum bpf_cmd {
|
|||||||
BPF_LINK_DETACH,
|
BPF_LINK_DETACH,
|
||||||
BPF_PROG_BIND_MAP,
|
BPF_PROG_BIND_MAP,
|
||||||
BPF_TOKEN_CREATE,
|
BPF_TOKEN_CREATE,
|
||||||
|
BPF_PROG_STREAM_READ_BY_FD,
|
||||||
|
BPF_PROG_ASSOC_STRUCT_OPS,
|
||||||
__MAX_BPF_CMD,
|
__MAX_BPF_CMD,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1010,6 +1045,7 @@ enum bpf_map_type {
|
|||||||
BPF_MAP_TYPE_USER_RINGBUF,
|
BPF_MAP_TYPE_USER_RINGBUF,
|
||||||
BPF_MAP_TYPE_CGRP_STORAGE,
|
BPF_MAP_TYPE_CGRP_STORAGE,
|
||||||
BPF_MAP_TYPE_ARENA,
|
BPF_MAP_TYPE_ARENA,
|
||||||
|
BPF_MAP_TYPE_INSN_ARRAY,
|
||||||
__MAX_BPF_MAP_TYPE
|
__MAX_BPF_MAP_TYPE
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1116,11 +1152,16 @@ enum bpf_attach_type {
|
|||||||
BPF_NETKIT_PRIMARY,
|
BPF_NETKIT_PRIMARY,
|
||||||
BPF_NETKIT_PEER,
|
BPF_NETKIT_PEER,
|
||||||
BPF_TRACE_KPROBE_SESSION,
|
BPF_TRACE_KPROBE_SESSION,
|
||||||
|
BPF_TRACE_UPROBE_SESSION,
|
||||||
|
BPF_TRACE_FSESSION,
|
||||||
__MAX_BPF_ATTACH_TYPE
|
__MAX_BPF_ATTACH_TYPE
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
|
#define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
|
||||||
|
|
||||||
|
/* Add BPF_LINK_TYPE(type, name) in bpf_types.h to keep bpf_link_type_strs[]
|
||||||
|
* in sync with the definitions below.
|
||||||
|
*/
|
||||||
enum bpf_link_type {
|
enum bpf_link_type {
|
||||||
BPF_LINK_TYPE_UNSPEC = 0,
|
BPF_LINK_TYPE_UNSPEC = 0,
|
||||||
BPF_LINK_TYPE_RAW_TRACEPOINT = 1,
|
BPF_LINK_TYPE_RAW_TRACEPOINT = 1,
|
||||||
@@ -1203,6 +1244,7 @@ enum bpf_perf_event_type {
|
|||||||
#define BPF_F_BEFORE (1U << 3)
|
#define BPF_F_BEFORE (1U << 3)
|
||||||
#define BPF_F_AFTER (1U << 4)
|
#define BPF_F_AFTER (1U << 4)
|
||||||
#define BPF_F_ID (1U << 5)
|
#define BPF_F_ID (1U << 5)
|
||||||
|
#define BPF_F_PREORDER (1U << 6)
|
||||||
#define BPF_F_LINK BPF_F_LINK /* 1 << 13 */
|
#define BPF_F_LINK BPF_F_LINK /* 1 << 13 */
|
||||||
|
|
||||||
/* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the
|
/* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the
|
||||||
@@ -1351,6 +1393,8 @@ enum {
|
|||||||
BPF_NOEXIST = 1, /* create new element if it didn't exist */
|
BPF_NOEXIST = 1, /* create new element if it didn't exist */
|
||||||
BPF_EXIST = 2, /* update existing element */
|
BPF_EXIST = 2, /* update existing element */
|
||||||
BPF_F_LOCK = 4, /* spin_lock-ed map_lookup/map_update */
|
BPF_F_LOCK = 4, /* spin_lock-ed map_lookup/map_update */
|
||||||
|
BPF_F_CPU = 8, /* cpu flag for percpu maps, upper 32-bit of flags is a cpu number */
|
||||||
|
BPF_F_ALL_CPUS = 16, /* update value across all CPUs for percpu maps */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* flags for BPF_MAP_CREATE command */
|
/* flags for BPF_MAP_CREATE command */
|
||||||
@@ -1409,6 +1453,9 @@ enum {
|
|||||||
|
|
||||||
/* Do not translate kernel bpf_arena pointers to user pointers */
|
/* Do not translate kernel bpf_arena pointers to user pointers */
|
||||||
BPF_F_NO_USER_CONV = (1U << 18),
|
BPF_F_NO_USER_CONV = (1U << 18),
|
||||||
|
|
||||||
|
/* Enable BPF ringbuf overwrite mode */
|
||||||
|
BPF_F_RB_OVERWRITE = (1U << 19),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Flags for BPF_PROG_QUERY. */
|
/* Flags for BPF_PROG_QUERY. */
|
||||||
@@ -1455,6 +1502,11 @@ struct bpf_stack_build_id {
|
|||||||
|
|
||||||
#define BPF_OBJ_NAME_LEN 16U
|
#define BPF_OBJ_NAME_LEN 16U
|
||||||
|
|
||||||
|
enum {
|
||||||
|
BPF_STREAM_STDOUT = 1,
|
||||||
|
BPF_STREAM_STDERR = 2,
|
||||||
|
};
|
||||||
|
|
||||||
union bpf_attr {
|
union bpf_attr {
|
||||||
struct { /* anonymous struct used by BPF_MAP_CREATE command */
|
struct { /* anonymous struct used by BPF_MAP_CREATE command */
|
||||||
__u32 map_type; /* one of enum bpf_map_type */
|
__u32 map_type; /* one of enum bpf_map_type */
|
||||||
@@ -1496,9 +1548,15 @@ union bpf_attr {
|
|||||||
* If provided, map_flags should have BPF_F_TOKEN_FD flag set.
|
* If provided, map_flags should have BPF_F_TOKEN_FD flag set.
|
||||||
*/
|
*/
|
||||||
__s32 map_token_fd;
|
__s32 map_token_fd;
|
||||||
|
|
||||||
|
/* Hash of the program that has exclusive access to the map.
|
||||||
|
*/
|
||||||
|
__aligned_u64 excl_prog_hash;
|
||||||
|
/* Size of the passed excl_prog_hash. */
|
||||||
|
__u32 excl_prog_hash_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */
|
struct { /* anonymous struct used by BPF_MAP_*_ELEM and BPF_MAP_FREEZE commands */
|
||||||
__u32 map_fd;
|
__u32 map_fd;
|
||||||
__aligned_u64 key;
|
__aligned_u64 key;
|
||||||
union {
|
union {
|
||||||
@@ -1569,6 +1627,26 @@ union bpf_attr {
|
|||||||
* If provided, prog_flags should have BPF_F_TOKEN_FD flag set.
|
* If provided, prog_flags should have BPF_F_TOKEN_FD flag set.
|
||||||
*/
|
*/
|
||||||
__s32 prog_token_fd;
|
__s32 prog_token_fd;
|
||||||
|
/* The fd_array_cnt can be used to pass the length of the
|
||||||
|
* fd_array array. In this case all the [map] file descriptors
|
||||||
|
* passed in this array will be bound to the program, even if
|
||||||
|
* the maps are not referenced directly. The functionality is
|
||||||
|
* similar to the BPF_PROG_BIND_MAP syscall, but maps can be
|
||||||
|
* used by the verifier during the program load. If provided,
|
||||||
|
* then the fd_array[0,...,fd_array_cnt-1] is expected to be
|
||||||
|
* continuous.
|
||||||
|
*/
|
||||||
|
__u32 fd_array_cnt;
|
||||||
|
/* Pointer to a buffer containing the signature of the BPF
|
||||||
|
* program.
|
||||||
|
*/
|
||||||
|
__aligned_u64 signature;
|
||||||
|
/* Size of the signature buffer in bytes. */
|
||||||
|
__u32 signature_size;
|
||||||
|
/* ID of the kernel keyring to be used for signature
|
||||||
|
* verification.
|
||||||
|
*/
|
||||||
|
__s32 keyring_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct { /* anonymous struct used by BPF_OBJ_* commands */
|
struct { /* anonymous struct used by BPF_OBJ_* commands */
|
||||||
@@ -1634,6 +1712,7 @@ union bpf_attr {
|
|||||||
};
|
};
|
||||||
__u32 next_id;
|
__u32 next_id;
|
||||||
__u32 open_flags;
|
__u32 open_flags;
|
||||||
|
__s32 fd_by_id_token_fd;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct { /* anonymous struct used by BPF_OBJ_GET_INFO_BY_FD */
|
struct { /* anonymous struct used by BPF_OBJ_GET_INFO_BY_FD */
|
||||||
@@ -1775,6 +1854,13 @@ union bpf_attr {
|
|||||||
};
|
};
|
||||||
__u64 expected_revision;
|
__u64 expected_revision;
|
||||||
} netkit;
|
} netkit;
|
||||||
|
struct {
|
||||||
|
union {
|
||||||
|
__u32 relative_fd;
|
||||||
|
__u32 relative_id;
|
||||||
|
};
|
||||||
|
__u64 expected_revision;
|
||||||
|
} cgroup;
|
||||||
};
|
};
|
||||||
} link_create;
|
} link_create;
|
||||||
|
|
||||||
@@ -1823,6 +1909,19 @@ union bpf_attr {
|
|||||||
__u32 bpffs_fd;
|
__u32 bpffs_fd;
|
||||||
} token_create;
|
} token_create;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
__aligned_u64 stream_buf;
|
||||||
|
__u32 stream_buf_len;
|
||||||
|
__u32 stream_id;
|
||||||
|
__u32 prog_fd;
|
||||||
|
} prog_stream_read;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
__u32 map_fd;
|
||||||
|
__u32 prog_fd;
|
||||||
|
__u32 flags;
|
||||||
|
} prog_assoc_struct_ops;
|
||||||
|
|
||||||
} __attribute__((aligned(8)));
|
} __attribute__((aligned(8)));
|
||||||
|
|
||||||
/* The description below is an attempt at providing documentation to eBPF
|
/* The description below is an attempt at providing documentation to eBPF
|
||||||
@@ -1970,15 +2069,21 @@ union bpf_attr {
|
|||||||
* program.
|
* program.
|
||||||
* Return
|
* Return
|
||||||
* The SMP id of the processor running the program.
|
* The SMP id of the processor running the program.
|
||||||
|
* Attributes
|
||||||
|
* __bpf_fastcall
|
||||||
*
|
*
|
||||||
* long bpf_skb_store_bytes(struct sk_buff *skb, u32 offset, const void *from, u32 len, u64 flags)
|
* long bpf_skb_store_bytes(struct sk_buff *skb, u32 offset, const void *from, u32 len, u64 flags)
|
||||||
* Description
|
* Description
|
||||||
* Store *len* bytes from address *from* into the packet
|
* Store *len* bytes from address *from* into the packet
|
||||||
* associated to *skb*, at *offset*. *flags* are a combination of
|
* associated to *skb*, at *offset*. The *flags* are a combination
|
||||||
* **BPF_F_RECOMPUTE_CSUM** (automatically recompute the
|
* of the following values:
|
||||||
* checksum for the packet after storing the bytes) and
|
*
|
||||||
* **BPF_F_INVALIDATE_HASH** (set *skb*\ **->hash**, *skb*\
|
* **BPF_F_RECOMPUTE_CSUM**
|
||||||
* **->swhash** and *skb*\ **->l4hash** to 0).
|
* Automatically update *skb*\ **->csum** after storing the
|
||||||
|
* bytes.
|
||||||
|
* **BPF_F_INVALIDATE_HASH**
|
||||||
|
* Set *skb*\ **->hash**, *skb*\ **->swhash** and *skb*\
|
||||||
|
* **->l4hash** to 0.
|
||||||
*
|
*
|
||||||
* A call to this helper is susceptible to change the underlying
|
* A call to this helper is susceptible to change the underlying
|
||||||
* packet buffer. Therefore, at load time, all checks on pointers
|
* packet buffer. Therefore, at load time, all checks on pointers
|
||||||
@@ -2030,7 +2135,8 @@ union bpf_attr {
|
|||||||
* untouched (unless **BPF_F_MARK_ENFORCE** is added as well), and
|
* untouched (unless **BPF_F_MARK_ENFORCE** is added as well), and
|
||||||
* for updates resulting in a null checksum the value is set to
|
* for updates resulting in a null checksum the value is set to
|
||||||
* **CSUM_MANGLED_0** instead. Flag **BPF_F_PSEUDO_HDR** indicates
|
* **CSUM_MANGLED_0** instead. Flag **BPF_F_PSEUDO_HDR** indicates
|
||||||
* the checksum is to be computed against a pseudo-header.
|
* that the modified header field is part of the pseudo-header.
|
||||||
|
* Flag **BPF_F_IPV6** should be set for IPv6 packets.
|
||||||
*
|
*
|
||||||
* This helper works in combination with **bpf_csum_diff**\ (),
|
* This helper works in combination with **bpf_csum_diff**\ (),
|
||||||
* which does not update the checksum in-place, but offers more
|
* which does not update the checksum in-place, but offers more
|
||||||
@@ -2377,7 +2483,7 @@ union bpf_attr {
|
|||||||
* into it. An example is available in file
|
* into it. An example is available in file
|
||||||
* *samples/bpf/trace_output_user.c* in the Linux kernel source
|
* *samples/bpf/trace_output_user.c* in the Linux kernel source
|
||||||
* tree (the eBPF program counterpart is in
|
* tree (the eBPF program counterpart is in
|
||||||
* *samples/bpf/trace_output_kern.c*).
|
* *samples/bpf/trace_output.bpf.c*).
|
||||||
*
|
*
|
||||||
* **bpf_perf_event_output**\ () achieves better performance
|
* **bpf_perf_event_output**\ () achieves better performance
|
||||||
* than **bpf_trace_printk**\ () for sharing data with user
|
* than **bpf_trace_printk**\ () for sharing data with user
|
||||||
@@ -2851,7 +2957,7 @@ union bpf_attr {
|
|||||||
* **TCP_SYNCNT**, **TCP_USER_TIMEOUT**, **TCP_NOTSENT_LOWAT**,
|
* **TCP_SYNCNT**, **TCP_USER_TIMEOUT**, **TCP_NOTSENT_LOWAT**,
|
||||||
* **TCP_NODELAY**, **TCP_MAXSEG**, **TCP_WINDOW_CLAMP**,
|
* **TCP_NODELAY**, **TCP_MAXSEG**, **TCP_WINDOW_CLAMP**,
|
||||||
* **TCP_THIN_LINEAR_TIMEOUTS**, **TCP_BPF_DELACK_MAX**,
|
* **TCP_THIN_LINEAR_TIMEOUTS**, **TCP_BPF_DELACK_MAX**,
|
||||||
* **TCP_BPF_RTO_MIN**.
|
* **TCP_BPF_RTO_MIN**, **TCP_BPF_SOCK_OPS_CB_FLAGS**.
|
||||||
* * **IPPROTO_IP**, which supports *optname* **IP_TOS**.
|
* * **IPPROTO_IP**, which supports *optname* **IP_TOS**.
|
||||||
* * **IPPROTO_IPV6**, which supports the following *optname*\ s:
|
* * **IPPROTO_IPV6**, which supports the following *optname*\ s:
|
||||||
* **IPV6_TCLASS**, **IPV6_AUTOFLOWLABEL**.
|
* **IPV6_TCLASS**, **IPV6_AUTOFLOWLABEL**.
|
||||||
@@ -3101,10 +3207,6 @@ union bpf_attr {
|
|||||||
* with the **CONFIG_BPF_KPROBE_OVERRIDE** configuration
|
* with the **CONFIG_BPF_KPROBE_OVERRIDE** configuration
|
||||||
* option, and in this case it only works on functions tagged with
|
* option, and in this case it only works on functions tagged with
|
||||||
* **ALLOW_ERROR_INJECTION** in the kernel code.
|
* **ALLOW_ERROR_INJECTION** in the kernel code.
|
||||||
*
|
|
||||||
* Also, the helper is only available for the architectures having
|
|
||||||
* the CONFIG_FUNCTION_ERROR_INJECTION option. As of this writing,
|
|
||||||
* x86 architecture is the only one to support this feature.
|
|
||||||
* Return
|
* Return
|
||||||
* 0
|
* 0
|
||||||
*
|
*
|
||||||
@@ -4821,7 +4923,7 @@ union bpf_attr {
|
|||||||
*
|
*
|
||||||
* **-ENOENT** if the bpf_local_storage cannot be found.
|
* **-ENOENT** if the bpf_local_storage cannot be found.
|
||||||
*
|
*
|
||||||
* long bpf_d_path(struct path *path, char *buf, u32 sz)
|
* long bpf_d_path(const struct path *path, char *buf, u32 sz)
|
||||||
* Description
|
* Description
|
||||||
* Return full path for given **struct path** object, which
|
* Return full path for given **struct path** object, which
|
||||||
* needs to be the kernel BTF *path* object. The path is
|
* needs to be the kernel BTF *path* object. The path is
|
||||||
@@ -4951,6 +5053,9 @@ union bpf_attr {
|
|||||||
* the netns switch takes place from ingress to ingress without
|
* the netns switch takes place from ingress to ingress without
|
||||||
* going through the CPU's backlog queue.
|
* going through the CPU's backlog queue.
|
||||||
*
|
*
|
||||||
|
* *skb*\ **->mark** and *skb*\ **->tstamp** are not cleared during
|
||||||
|
* the netns switch.
|
||||||
|
*
|
||||||
* The *flags* argument is reserved and must be 0. The helper is
|
* The *flags* argument is reserved and must be 0. The helper is
|
||||||
* currently only supported for tc BPF program types at the
|
* currently only supported for tc BPF program types at the
|
||||||
* ingress hook and for veth and netkit target device types. The
|
* ingress hook and for veth and netkit target device types. The
|
||||||
@@ -5369,7 +5474,7 @@ union bpf_attr {
|
|||||||
* Currently, the **flags** must be 0. Currently, nr_loops is
|
* Currently, the **flags** must be 0. Currently, nr_loops is
|
||||||
* limited to 1 << 23 (~8 million) loops.
|
* limited to 1 << 23 (~8 million) loops.
|
||||||
*
|
*
|
||||||
* long (\*callback_fn)(u32 index, void \*ctx);
|
* long (\*callback_fn)(u64 index, void \*ctx);
|
||||||
*
|
*
|
||||||
* where **index** is the current index in the loop. The index
|
* where **index** is the current index in the loop. The index
|
||||||
* is zero-indexed.
|
* is zero-indexed.
|
||||||
@@ -5519,11 +5624,12 @@ union bpf_attr {
|
|||||||
* **-EOPNOTSUPP** if the hash calculation failed or **-EINVAL** if
|
* **-EOPNOTSUPP** if the hash calculation failed or **-EINVAL** if
|
||||||
* invalid arguments are passed.
|
* invalid arguments are passed.
|
||||||
*
|
*
|
||||||
* void *bpf_kptr_xchg(void *map_value, void *ptr)
|
* void *bpf_kptr_xchg(void *dst, void *ptr)
|
||||||
* Description
|
* Description
|
||||||
* Exchange kptr at pointer *map_value* with *ptr*, and return the
|
* Exchange kptr at pointer *dst* with *ptr*, and return the old value.
|
||||||
* old value. *ptr* can be NULL, otherwise it must be a referenced
|
* *dst* can be map value or local kptr. *ptr* can be NULL, otherwise
|
||||||
* pointer which will be released when this helper is called.
|
* it must be a referenced pointer which will be released when this helper
|
||||||
|
* is called.
|
||||||
* Return
|
* Return
|
||||||
* The old value of kptr (which can be NULL). The returned pointer
|
* The old value of kptr (which can be NULL). The returned pointer
|
||||||
* if not NULL, is a reference which must be released using its
|
* if not NULL, is a reference which must be released using its
|
||||||
@@ -5544,7 +5650,7 @@ union bpf_attr {
|
|||||||
* Return
|
* Return
|
||||||
* *sk* if casting is valid, or **NULL** otherwise.
|
* *sk* if casting is valid, or **NULL** otherwise.
|
||||||
*
|
*
|
||||||
* long bpf_dynptr_from_mem(void *data, u32 size, u64 flags, struct bpf_dynptr *ptr)
|
* long bpf_dynptr_from_mem(void *data, u64 size, u64 flags, struct bpf_dynptr *ptr)
|
||||||
* Description
|
* Description
|
||||||
* Get a dynptr to local memory *data*.
|
* Get a dynptr to local memory *data*.
|
||||||
*
|
*
|
||||||
@@ -5587,7 +5693,7 @@ union bpf_attr {
|
|||||||
* Return
|
* Return
|
||||||
* Nothing. Always succeeds.
|
* Nothing. Always succeeds.
|
||||||
*
|
*
|
||||||
* long bpf_dynptr_read(void *dst, u32 len, const struct bpf_dynptr *src, u32 offset, u64 flags)
|
* long bpf_dynptr_read(void *dst, u64 len, const struct bpf_dynptr *src, u64 offset, u64 flags)
|
||||||
* Description
|
* Description
|
||||||
* Read *len* bytes from *src* into *dst*, starting from *offset*
|
* Read *len* bytes from *src* into *dst*, starting from *offset*
|
||||||
* into *src*.
|
* into *src*.
|
||||||
@@ -5597,7 +5703,7 @@ union bpf_attr {
|
|||||||
* of *src*'s data, -EINVAL if *src* is an invalid dynptr or if
|
* of *src*'s data, -EINVAL if *src* is an invalid dynptr or if
|
||||||
* *flags* is not 0.
|
* *flags* is not 0.
|
||||||
*
|
*
|
||||||
* long bpf_dynptr_write(const struct bpf_dynptr *dst, u32 offset, void *src, u32 len, u64 flags)
|
* long bpf_dynptr_write(const struct bpf_dynptr *dst, u64 offset, void *src, u64 len, u64 flags)
|
||||||
* Description
|
* Description
|
||||||
* Write *len* bytes from *src* into *dst*, starting from *offset*
|
* Write *len* bytes from *src* into *dst*, starting from *offset*
|
||||||
* into *dst*.
|
* into *dst*.
|
||||||
@@ -5618,7 +5724,7 @@ union bpf_attr {
|
|||||||
* is a read-only dynptr or if *flags* is not correct. For skb-type dynptrs,
|
* is a read-only dynptr or if *flags* is not correct. For skb-type dynptrs,
|
||||||
* other errors correspond to errors returned by **bpf_skb_store_bytes**\ ().
|
* other errors correspond to errors returned by **bpf_skb_store_bytes**\ ().
|
||||||
*
|
*
|
||||||
* void *bpf_dynptr_data(const struct bpf_dynptr *ptr, u32 offset, u32 len)
|
* void *bpf_dynptr_data(const struct bpf_dynptr *ptr, u64 offset, u64 len)
|
||||||
* Description
|
* Description
|
||||||
* Get a pointer to the underlying dynptr data.
|
* Get a pointer to the underlying dynptr data.
|
||||||
*
|
*
|
||||||
@@ -6006,7 +6112,10 @@ union bpf_attr {
|
|||||||
FN(user_ringbuf_drain, 209, ##ctx) \
|
FN(user_ringbuf_drain, 209, ##ctx) \
|
||||||
FN(cgrp_storage_get, 210, ##ctx) \
|
FN(cgrp_storage_get, 210, ##ctx) \
|
||||||
FN(cgrp_storage_delete, 211, ##ctx) \
|
FN(cgrp_storage_delete, 211, ##ctx) \
|
||||||
/* */
|
/* This helper list is effectively frozen. If you are trying to \
|
||||||
|
* add a new helper, you should add a kfunc instead which has \
|
||||||
|
* less stability guarantees. See Documentation/bpf/kfuncs.rst \
|
||||||
|
*/
|
||||||
|
|
||||||
/* backwards-compatibility macros for users of __BPF_FUNC_MAPPER that don't
|
/* backwards-compatibility macros for users of __BPF_FUNC_MAPPER that don't
|
||||||
* know or care about integer value that is now passed as second argument
|
* know or care about integer value that is now passed as second argument
|
||||||
@@ -6044,11 +6153,7 @@ enum {
|
|||||||
BPF_F_PSEUDO_HDR = (1ULL << 4),
|
BPF_F_PSEUDO_HDR = (1ULL << 4),
|
||||||
BPF_F_MARK_MANGLED_0 = (1ULL << 5),
|
BPF_F_MARK_MANGLED_0 = (1ULL << 5),
|
||||||
BPF_F_MARK_ENFORCE = (1ULL << 6),
|
BPF_F_MARK_ENFORCE = (1ULL << 6),
|
||||||
};
|
BPF_F_IPV6 = (1ULL << 7),
|
||||||
|
|
||||||
/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */
|
|
||||||
enum {
|
|
||||||
BPF_F_INGRESS = (1ULL << 0),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* BPF_FUNC_skb_set_tunnel_key and BPF_FUNC_skb_get_tunnel_key flags. */
|
/* BPF_FUNC_skb_set_tunnel_key and BPF_FUNC_skb_get_tunnel_key flags. */
|
||||||
@@ -6158,6 +6263,7 @@ enum {
|
|||||||
BPF_RB_RING_SIZE = 1,
|
BPF_RB_RING_SIZE = 1,
|
||||||
BPF_RB_CONS_POS = 2,
|
BPF_RB_CONS_POS = 2,
|
||||||
BPF_RB_PROD_POS = 3,
|
BPF_RB_PROD_POS = 3,
|
||||||
|
BPF_RB_OVERWRITE_POS = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* BPF ring buffer constants */
|
/* BPF ring buffer constants */
|
||||||
@@ -6197,10 +6303,12 @@ enum {
|
|||||||
BPF_F_BPRM_SECUREEXEC = (1ULL << 0),
|
BPF_F_BPRM_SECUREEXEC = (1ULL << 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Flags for bpf_redirect_map helper */
|
/* Flags for bpf_redirect and bpf_redirect_map helpers */
|
||||||
enum {
|
enum {
|
||||||
BPF_F_BROADCAST = (1ULL << 3),
|
BPF_F_INGRESS = (1ULL << 0), /* used for skb path */
|
||||||
BPF_F_EXCLUDE_INGRESS = (1ULL << 4),
|
BPF_F_BROADCAST = (1ULL << 3), /* used for XDP path */
|
||||||
|
BPF_F_EXCLUDE_INGRESS = (1ULL << 4), /* used for XDP path */
|
||||||
|
#define BPF_F_REDIRECT_FLAGS (BPF_F_INGRESS | BPF_F_BROADCAST | BPF_F_EXCLUDE_INGRESS)
|
||||||
};
|
};
|
||||||
|
|
||||||
#define __bpf_md_ptr(type, name) \
|
#define __bpf_md_ptr(type, name) \
|
||||||
@@ -6607,6 +6715,8 @@ struct bpf_map_info {
|
|||||||
__u32 btf_value_type_id;
|
__u32 btf_value_type_id;
|
||||||
__u32 btf_vmlinux_id;
|
__u32 btf_vmlinux_id;
|
||||||
__u64 map_extra;
|
__u64 map_extra;
|
||||||
|
__aligned_u64 hash;
|
||||||
|
__u32 hash_size;
|
||||||
} __attribute__((aligned(8)));
|
} __attribute__((aligned(8)));
|
||||||
|
|
||||||
struct bpf_btf_info {
|
struct bpf_btf_info {
|
||||||
@@ -6626,11 +6736,15 @@ struct bpf_link_info {
|
|||||||
struct {
|
struct {
|
||||||
__aligned_u64 tp_name; /* in/out: tp_name buffer ptr */
|
__aligned_u64 tp_name; /* in/out: tp_name buffer ptr */
|
||||||
__u32 tp_name_len; /* in/out: tp_name buffer len */
|
__u32 tp_name_len; /* in/out: tp_name buffer len */
|
||||||
|
__u32 :32;
|
||||||
|
__u64 cookie;
|
||||||
} raw_tracepoint;
|
} raw_tracepoint;
|
||||||
struct {
|
struct {
|
||||||
__u32 attach_type;
|
__u32 attach_type;
|
||||||
__u32 target_obj_id; /* prog_id for PROG_EXT, otherwise btf object id */
|
__u32 target_obj_id; /* prog_id for PROG_EXT, otherwise btf object id */
|
||||||
__u32 target_btf_id; /* BTF type id inside the object */
|
__u32 target_btf_id; /* BTF type id inside the object */
|
||||||
|
__u32 :32;
|
||||||
|
__u64 cookie;
|
||||||
} tracing;
|
} tracing;
|
||||||
struct {
|
struct {
|
||||||
__u64 cgroup_id;
|
__u64 cgroup_id;
|
||||||
@@ -6702,6 +6816,7 @@ struct bpf_link_info {
|
|||||||
__u32 name_len;
|
__u32 name_len;
|
||||||
__u32 offset; /* offset from file_name */
|
__u32 offset; /* offset from file_name */
|
||||||
__u64 cookie;
|
__u64 cookie;
|
||||||
|
__u64 ref_ctr_offset;
|
||||||
} uprobe; /* BPF_PERF_EVENT_UPROBE, BPF_PERF_EVENT_URETPROBE */
|
} uprobe; /* BPF_PERF_EVENT_UPROBE, BPF_PERF_EVENT_URETPROBE */
|
||||||
struct {
|
struct {
|
||||||
__aligned_u64 func_name; /* in/out */
|
__aligned_u64 func_name; /* in/out */
|
||||||
@@ -6740,6 +6855,13 @@ struct bpf_link_info {
|
|||||||
};
|
};
|
||||||
} __attribute__((aligned(8)));
|
} __attribute__((aligned(8)));
|
||||||
|
|
||||||
|
struct bpf_token_info {
|
||||||
|
__u64 allowed_cmds;
|
||||||
|
__u64 allowed_maps;
|
||||||
|
__u64 allowed_progs;
|
||||||
|
__u64 allowed_attachs;
|
||||||
|
} __attribute__((aligned(8)));
|
||||||
|
|
||||||
/* User bpf_sock_addr struct to access socket fields and sockaddr struct passed
|
/* User bpf_sock_addr struct to access socket fields and sockaddr struct passed
|
||||||
* by user and intended to be used by socket (e.g. to bind to, depends on
|
* by user and intended to be used by socket (e.g. to bind to, depends on
|
||||||
* attach type).
|
* attach type).
|
||||||
@@ -6903,6 +7025,12 @@ enum {
|
|||||||
BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7F,
|
BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7F,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SK_BPF_CB_TX_TIMESTAMPING = 1<<0,
|
||||||
|
SK_BPF_CB_MASK = (SK_BPF_CB_TX_TIMESTAMPING - 1) |
|
||||||
|
SK_BPF_CB_TX_TIMESTAMPING
|
||||||
|
};
|
||||||
|
|
||||||
/* List of known BPF sock_ops operators.
|
/* List of known BPF sock_ops operators.
|
||||||
* New entries can only be added at the end
|
* New entries can only be added at the end
|
||||||
*/
|
*/
|
||||||
@@ -7015,6 +7143,29 @@ enum {
|
|||||||
* by the kernel or the
|
* by the kernel or the
|
||||||
* earlier bpf-progs.
|
* earlier bpf-progs.
|
||||||
*/
|
*/
|
||||||
|
BPF_SOCK_OPS_TSTAMP_SCHED_CB, /* Called when skb is passing
|
||||||
|
* through dev layer when
|
||||||
|
* SK_BPF_CB_TX_TIMESTAMPING
|
||||||
|
* feature is on.
|
||||||
|
*/
|
||||||
|
BPF_SOCK_OPS_TSTAMP_SND_SW_CB, /* Called when skb is about to send
|
||||||
|
* to the nic when SK_BPF_CB_TX_TIMESTAMPING
|
||||||
|
* feature is on.
|
||||||
|
*/
|
||||||
|
BPF_SOCK_OPS_TSTAMP_SND_HW_CB, /* Called in hardware phase when
|
||||||
|
* SK_BPF_CB_TX_TIMESTAMPING feature
|
||||||
|
* is on.
|
||||||
|
*/
|
||||||
|
BPF_SOCK_OPS_TSTAMP_ACK_CB, /* Called when all the skbs in the
|
||||||
|
* same sendmsg call are acked
|
||||||
|
* when SK_BPF_CB_TX_TIMESTAMPING
|
||||||
|
* feature is on.
|
||||||
|
*/
|
||||||
|
BPF_SOCK_OPS_TSTAMP_SENDMSG_CB, /* Called when every sendmsg syscall
|
||||||
|
* is triggered. It's used to correlate
|
||||||
|
* sendmsg timestamp with corresponding
|
||||||
|
* tskey.
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
/* List of TCP states. There is a build check in net/ipv4/tcp.c to detect
|
/* List of TCP states. There is a build check in net/ipv4/tcp.c to detect
|
||||||
@@ -7080,6 +7231,10 @@ enum {
|
|||||||
TCP_BPF_SYN = 1005, /* Copy the TCP header */
|
TCP_BPF_SYN = 1005, /* Copy the TCP header */
|
||||||
TCP_BPF_SYN_IP = 1006, /* Copy the IP[46] and TCP header */
|
TCP_BPF_SYN_IP = 1006, /* Copy the IP[46] and TCP header */
|
||||||
TCP_BPF_SYN_MAC = 1007, /* Copy the MAC, IP[46], and TCP header */
|
TCP_BPF_SYN_MAC = 1007, /* Copy the MAC, IP[46], and TCP header */
|
||||||
|
TCP_BPF_SOCK_OPS_CB_FLAGS = 1008, /* Get or Set TCP sock ops flags */
|
||||||
|
SK_BPF_CB_FLAGS = 1009, /* Get or set sock ops flags in socket */
|
||||||
|
SK_BPF_BYPASS_PROT_MEM = 1010, /* Get or Set sk->sk_bypass_prot_mem */
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -7316,6 +7471,10 @@ struct bpf_timer {
|
|||||||
__u64 __opaque[2];
|
__u64 __opaque[2];
|
||||||
} __attribute__((aligned(8)));
|
} __attribute__((aligned(8)));
|
||||||
|
|
||||||
|
struct bpf_task_work {
|
||||||
|
__u64 __opaque;
|
||||||
|
} __attribute__((aligned(8)));
|
||||||
|
|
||||||
struct bpf_wq {
|
struct bpf_wq {
|
||||||
__u64 __opaque[2];
|
__u64 __opaque[2];
|
||||||
} __attribute__((aligned(8)));
|
} __attribute__((aligned(8)));
|
||||||
@@ -7521,4 +7680,24 @@ enum bpf_kfunc_flags {
|
|||||||
BPF_F_PAD_ZEROS = (1ULL << 0),
|
BPF_F_PAD_ZEROS = (1ULL << 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _UAPI__LINUX_BPF_H__ */
|
/*
|
||||||
|
* Values of a BPF_MAP_TYPE_INSN_ARRAY entry must be of this type.
|
||||||
|
*
|
||||||
|
* Before the map is used the orig_off field should point to an
|
||||||
|
* instruction inside the program being loaded. The other fields
|
||||||
|
* must be set to 0.
|
||||||
|
*
|
||||||
|
* After the program is loaded, the xlated_off will be adjusted
|
||||||
|
* by the verifier to point to the index of the original instruction
|
||||||
|
* in the xlated program. If the instruction is deleted, it will
|
||||||
|
* be set to (u32)-1. The jitted_off will be set to the corresponding
|
||||||
|
* offset in the jitted image of the program.
|
||||||
|
*/
|
||||||
|
struct bpf_insn_array_value {
|
||||||
|
__u32 orig_off;
|
||||||
|
__u32 xlated_off;
|
||||||
|
__u32 jitted_off;
|
||||||
|
__u32 :32;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __LINUX_BPF_H__ */
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||||
#ifndef _UAPI__LINUX_BPF_COMMON_H__
|
#ifndef __LINUX_BPF_COMMON_H__
|
||||||
#define _UAPI__LINUX_BPF_COMMON_H__
|
#define __LINUX_BPF_COMMON_H__
|
||||||
|
|
||||||
/* Instruction classes */
|
/* Instruction classes */
|
||||||
#define BPF_CLASS(code) ((code) & 0x07)
|
#define BPF_CLASS(code) ((code) & 0x07)
|
||||||
@@ -54,4 +54,4 @@
|
|||||||
#define BPF_MAXINSNS 4096
|
#define BPF_MAXINSNS 4096
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _UAPI__LINUX_BPF_COMMON_H__ */
|
#endif /* __LINUX_BPF_COMMON_H__ */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||||
/* Copyright (c) 2018 Facebook */
|
/* Copyright (c) 2018 Facebook */
|
||||||
#ifndef _UAPI__LINUX_BTF_H__
|
#ifndef __LINUX_BTF_H__
|
||||||
#define _UAPI__LINUX_BTF_H__
|
#define __LINUX_BTF_H__
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
@@ -36,7 +36,8 @@ struct btf_type {
|
|||||||
* bits 24-28: kind (e.g. int, ptr, array...etc)
|
* bits 24-28: kind (e.g. int, ptr, array...etc)
|
||||||
* bits 29-30: unused
|
* bits 29-30: unused
|
||||||
* bit 31: kind_flag, currently used by
|
* bit 31: kind_flag, currently used by
|
||||||
* struct, union, enum, fwd and enum64
|
* struct, union, enum, fwd, enum64,
|
||||||
|
* decl_tag and type_tag
|
||||||
*/
|
*/
|
||||||
__u32 info;
|
__u32 info;
|
||||||
/* "size" is used by INT, ENUM, STRUCT, UNION, DATASEC and ENUM64.
|
/* "size" is used by INT, ENUM, STRUCT, UNION, DATASEC and ENUM64.
|
||||||
@@ -197,4 +198,4 @@ struct btf_enum64 {
|
|||||||
__u32 val_hi32;
|
__u32 val_hi32;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _UAPI__LINUX_BTF_H__ */
|
#endif /* __LINUX_BTF_H__ */
|
||||||
|
|||||||
193
include/uapi/linux/fcntl.h
Normal file
193
include/uapi/linux/fcntl.h
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||||
|
#ifndef _LINUX_FCNTL_H
|
||||||
|
#define _LINUX_FCNTL_H
|
||||||
|
|
||||||
|
#include <asm/fcntl.h>
|
||||||
|
#include <linux/openat2.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#define F_SETLEASE (F_LINUX_SPECIFIC_BASE + 0)
|
||||||
|
#define F_GETLEASE (F_LINUX_SPECIFIC_BASE + 1)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Request nofications on a directory.
|
||||||
|
* See below for events that may be notified.
|
||||||
|
*/
|
||||||
|
#define F_NOTIFY (F_LINUX_SPECIFIC_BASE + 2)
|
||||||
|
|
||||||
|
#define F_DUPFD_QUERY (F_LINUX_SPECIFIC_BASE + 3)
|
||||||
|
|
||||||
|
/* Was the file just created? */
|
||||||
|
#define F_CREATED_QUERY (F_LINUX_SPECIFIC_BASE + 4)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cancel a blocking posix lock; internal use only until we expose an
|
||||||
|
* asynchronous lock api to userspace:
|
||||||
|
*/
|
||||||
|
#define F_CANCELLK (F_LINUX_SPECIFIC_BASE + 5)
|
||||||
|
|
||||||
|
/* Create a file descriptor with FD_CLOEXEC set. */
|
||||||
|
#define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set and get of pipe page size array
|
||||||
|
*/
|
||||||
|
#define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7)
|
||||||
|
#define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set/Get seals
|
||||||
|
*/
|
||||||
|
#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
|
||||||
|
#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Types of seals
|
||||||
|
*/
|
||||||
|
#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */
|
||||||
|
#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */
|
||||||
|
#define F_SEAL_GROW 0x0004 /* prevent file from growing */
|
||||||
|
#define F_SEAL_WRITE 0x0008 /* prevent writes */
|
||||||
|
#define F_SEAL_FUTURE_WRITE 0x0010 /* prevent future writes while mapped */
|
||||||
|
#define F_SEAL_EXEC 0x0020 /* prevent chmod modifying exec bits */
|
||||||
|
/* (1U << 31) is reserved for signed error codes */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set/Get write life time hints. {GET,SET}_RW_HINT operate on the
|
||||||
|
* underlying inode, while {GET,SET}_FILE_RW_HINT operate only on
|
||||||
|
* the specific file.
|
||||||
|
*/
|
||||||
|
#define F_GET_RW_HINT (F_LINUX_SPECIFIC_BASE + 11)
|
||||||
|
#define F_SET_RW_HINT (F_LINUX_SPECIFIC_BASE + 12)
|
||||||
|
#define F_GET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 13)
|
||||||
|
#define F_SET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 14)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Valid hint values for F_{GET,SET}_RW_HINT. 0 is "not set", or can be
|
||||||
|
* used to clear any hints previously set.
|
||||||
|
*/
|
||||||
|
#define RWH_WRITE_LIFE_NOT_SET 0
|
||||||
|
#define RWH_WRITE_LIFE_NONE 1
|
||||||
|
#define RWH_WRITE_LIFE_SHORT 2
|
||||||
|
#define RWH_WRITE_LIFE_MEDIUM 3
|
||||||
|
#define RWH_WRITE_LIFE_LONG 4
|
||||||
|
#define RWH_WRITE_LIFE_EXTREME 5
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The originally introduced spelling is remained from the first
|
||||||
|
* versions of the patch set that introduced the feature, see commit
|
||||||
|
* v4.13-rc1~212^2~51.
|
||||||
|
*/
|
||||||
|
#define RWF_WRITE_LIFE_NOT_SET RWH_WRITE_LIFE_NOT_SET
|
||||||
|
|
||||||
|
/* Set/Get delegations */
|
||||||
|
#define F_GETDELEG (F_LINUX_SPECIFIC_BASE + 15)
|
||||||
|
#define F_SETDELEG (F_LINUX_SPECIFIC_BASE + 16)
|
||||||
|
|
||||||
|
/* Argument structure for F_GETDELEG and F_SETDELEG */
|
||||||
|
struct delegation {
|
||||||
|
__u32 d_flags; /* Must be 0 */
|
||||||
|
__u16 d_type; /* F_RDLCK, F_WRLCK, F_UNLCK */
|
||||||
|
__u16 __pad; /* Must be 0 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Types of directory notifications that may be requested.
|
||||||
|
*/
|
||||||
|
#define DN_ACCESS 0x00000001 /* File accessed */
|
||||||
|
#define DN_MODIFY 0x00000002 /* File modified */
|
||||||
|
#define DN_CREATE 0x00000004 /* File created */
|
||||||
|
#define DN_DELETE 0x00000008 /* File removed */
|
||||||
|
#define DN_RENAME 0x00000010 /* File renamed */
|
||||||
|
#define DN_ATTRIB 0x00000020 /* File changed attibutes */
|
||||||
|
#define DN_MULTISHOT 0x80000000 /* Don't remove notifier */
|
||||||
|
|
||||||
|
/* Reserved kernel ranges [-100], [-10000, -40000]. */
|
||||||
|
#define AT_FDCWD -100 /* Special value for dirfd used to
|
||||||
|
indicate openat should use the
|
||||||
|
current working directory. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The concept of process and threads in userland and the kernel is a confusing
|
||||||
|
* one - within the kernel every thread is a 'task' with its own individual PID,
|
||||||
|
* however from userland's point of view threads are grouped by a single PID,
|
||||||
|
* which is that of the 'thread group leader', typically the first thread
|
||||||
|
* spawned.
|
||||||
|
*
|
||||||
|
* To cut the Gideon knot, for internal kernel usage, we refer to
|
||||||
|
* PIDFD_SELF_THREAD to refer to the current thread (or task from a kernel
|
||||||
|
* perspective), and PIDFD_SELF_THREAD_GROUP to refer to the current thread
|
||||||
|
* group leader...
|
||||||
|
*/
|
||||||
|
#define PIDFD_SELF_THREAD -10000 /* Current thread. */
|
||||||
|
#define PIDFD_SELF_THREAD_GROUP -10001 /* Current thread group leader. */
|
||||||
|
|
||||||
|
#define FD_PIDFS_ROOT -10002 /* Root of the pidfs filesystem */
|
||||||
|
#define FD_NSFS_ROOT -10003 /* Root of the nsfs filesystem */
|
||||||
|
#define FD_INVALID -10009 /* Invalid file descriptor: -10000 - EBADF = -10009 */
|
||||||
|
|
||||||
|
/* Generic flags for the *at(2) family of syscalls. */
|
||||||
|
|
||||||
|
/* Reserved for per-syscall flags 0xff. */
|
||||||
|
#define AT_SYMLINK_NOFOLLOW 0x100 /* Do not follow symbolic
|
||||||
|
links. */
|
||||||
|
/* Reserved for per-syscall flags 0x200 */
|
||||||
|
#define AT_SYMLINK_FOLLOW 0x400 /* Follow symbolic links. */
|
||||||
|
#define AT_NO_AUTOMOUNT 0x800 /* Suppress terminal automount
|
||||||
|
traversal. */
|
||||||
|
#define AT_EMPTY_PATH 0x1000 /* Allow empty relative
|
||||||
|
pathname to operate on dirfd
|
||||||
|
directly. */
|
||||||
|
/*
|
||||||
|
* These flags are currently statx(2)-specific, but they could be made generic
|
||||||
|
* in the future and so they should not be used for other per-syscall flags.
|
||||||
|
*/
|
||||||
|
#define AT_STATX_SYNC_TYPE 0x6000 /* Type of synchronisation required from statx() */
|
||||||
|
#define AT_STATX_SYNC_AS_STAT 0x0000 /* - Do whatever stat() does */
|
||||||
|
#define AT_STATX_FORCE_SYNC 0x2000 /* - Force the attributes to be sync'd with the server */
|
||||||
|
#define AT_STATX_DONT_SYNC 0x4000 /* - Don't sync attributes with the server */
|
||||||
|
|
||||||
|
#define AT_RECURSIVE 0x8000 /* Apply to the entire subtree */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Per-syscall flags for the *at(2) family of syscalls.
|
||||||
|
*
|
||||||
|
* These are flags that are so syscall-specific that a user passing these flags
|
||||||
|
* to the wrong syscall is so "clearly wrong" that we can safely call such
|
||||||
|
* usage "undefined behaviour".
|
||||||
|
*
|
||||||
|
* For example, the constants AT_REMOVEDIR and AT_EACCESS have the same value.
|
||||||
|
* AT_EACCESS is meaningful only to faccessat, while AT_REMOVEDIR is meaningful
|
||||||
|
* only to unlinkat. The two functions do completely different things and
|
||||||
|
* therefore, the flags can be allowed to overlap. For example, passing
|
||||||
|
* AT_REMOVEDIR to faccessat would be undefined behavior and thus treating it
|
||||||
|
* equivalent to AT_EACCESS is valid undefined behavior.
|
||||||
|
*
|
||||||
|
* Note for implementers: When picking a new per-syscall AT_* flag, try to
|
||||||
|
* reuse already existing flags first. This leaves us with as many unused bits
|
||||||
|
* as possible, so we can use them for generic bits in the future if necessary.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Flags for renameat2(2) (must match legacy RENAME_* flags). */
|
||||||
|
#define AT_RENAME_NOREPLACE 0x0001
|
||||||
|
#define AT_RENAME_EXCHANGE 0x0002
|
||||||
|
#define AT_RENAME_WHITEOUT 0x0004
|
||||||
|
|
||||||
|
/* Flag for faccessat(2). */
|
||||||
|
#define AT_EACCESS 0x200 /* Test access permitted for
|
||||||
|
effective IDs, not real IDs. */
|
||||||
|
/* Flag for unlinkat(2). */
|
||||||
|
#define AT_REMOVEDIR 0x200 /* Remove directory instead of
|
||||||
|
unlinking file. */
|
||||||
|
/* Flags for name_to_handle_at(2). */
|
||||||
|
#define AT_HANDLE_FID 0x200 /* File handle is needed to compare
|
||||||
|
object identity and may not be
|
||||||
|
usable with open_by_handle_at(2). */
|
||||||
|
#define AT_HANDLE_MNT_ID_UNIQUE 0x001 /* Return the u64 unique mount ID. */
|
||||||
|
#define AT_HANDLE_CONNECTABLE 0x002 /* Request a connectable file handle */
|
||||||
|
|
||||||
|
/* Flags for execveat2(2). */
|
||||||
|
#define AT_EXECVE_CHECK 0x10000 /* Only perform a check if execution
|
||||||
|
would be allowed. */
|
||||||
|
|
||||||
|
#endif /* _LINUX_FCNTL_H */
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||||
#ifndef _UAPI_LINUX_IF_LINK_H
|
#ifndef _LINUX_IF_LINK_H
|
||||||
#define _UAPI_LINUX_IF_LINK_H
|
#define _LINUX_IF_LINK_H
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
@@ -377,6 +377,10 @@ enum {
|
|||||||
IFLA_GSO_IPV4_MAX_SIZE,
|
IFLA_GSO_IPV4_MAX_SIZE,
|
||||||
IFLA_GRO_IPV4_MAX_SIZE,
|
IFLA_GRO_IPV4_MAX_SIZE,
|
||||||
IFLA_DPLL_PIN,
|
IFLA_DPLL_PIN,
|
||||||
|
IFLA_MAX_PACING_OFFLOAD_HORIZON,
|
||||||
|
IFLA_NETNS_IMMUTABLE,
|
||||||
|
IFLA_HEADROOM,
|
||||||
|
IFLA_TAILROOM,
|
||||||
__IFLA_MAX
|
__IFLA_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -461,6 +465,286 @@ enum in6_addr_gen_mode {
|
|||||||
|
|
||||||
/* Bridge section */
|
/* Bridge section */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DOC: Bridge enum definition
|
||||||
|
*
|
||||||
|
* Please *note* that the timer values in the following section are expected
|
||||||
|
* in clock_t format, which is seconds multiplied by USER_HZ (generally
|
||||||
|
* defined as 100).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_FORWARD_DELAY
|
||||||
|
* The bridge forwarding delay is the time spent in LISTENING state
|
||||||
|
* (before moving to LEARNING) and in LEARNING state (before moving
|
||||||
|
* to FORWARDING). Only relevant if STP is enabled.
|
||||||
|
*
|
||||||
|
* The valid values are between (2 * USER_HZ) and (30 * USER_HZ).
|
||||||
|
* The default value is (15 * USER_HZ).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_HELLO_TIME
|
||||||
|
* The time between hello packets sent by the bridge, when it is a root
|
||||||
|
* bridge or a designated bridge. Only relevant if STP is enabled.
|
||||||
|
*
|
||||||
|
* The valid values are between (1 * USER_HZ) and (10 * USER_HZ).
|
||||||
|
* The default value is (2 * USER_HZ).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_MAX_AGE
|
||||||
|
* The hello packet timeout is the time until another bridge in the
|
||||||
|
* spanning tree is assumed to be dead, after reception of its last hello
|
||||||
|
* message. Only relevant if STP is enabled.
|
||||||
|
*
|
||||||
|
* The valid values are between (6 * USER_HZ) and (40 * USER_HZ).
|
||||||
|
* The default value is (20 * USER_HZ).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_AGEING_TIME
|
||||||
|
* Configure the bridge's FDB entries aging time. It is the time a MAC
|
||||||
|
* address will be kept in the FDB after a packet has been received from
|
||||||
|
* that address. After this time has passed, entries are cleaned up.
|
||||||
|
* Allow values outside the 802.1 standard specification for special cases:
|
||||||
|
*
|
||||||
|
* * 0 - entry never ages (all permanent)
|
||||||
|
* * 1 - entry disappears (no persistence)
|
||||||
|
*
|
||||||
|
* The default value is (300 * USER_HZ).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_STP_STATE
|
||||||
|
* Turn spanning tree protocol on (*IFLA_BR_STP_STATE* > 0) or off
|
||||||
|
* (*IFLA_BR_STP_STATE* == 0) for this bridge.
|
||||||
|
*
|
||||||
|
* The default value is 0 (disabled).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_PRIORITY
|
||||||
|
* Set this bridge's spanning tree priority, used during STP root bridge
|
||||||
|
* election.
|
||||||
|
*
|
||||||
|
* The valid values are between 0 and 65535.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_VLAN_FILTERING
|
||||||
|
* Turn VLAN filtering on (*IFLA_BR_VLAN_FILTERING* > 0) or off
|
||||||
|
* (*IFLA_BR_VLAN_FILTERING* == 0). When disabled, the bridge will not
|
||||||
|
* consider the VLAN tag when handling packets.
|
||||||
|
*
|
||||||
|
* The default value is 0 (disabled).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_VLAN_PROTOCOL
|
||||||
|
* Set the protocol used for VLAN filtering.
|
||||||
|
*
|
||||||
|
* The valid values are 0x8100(802.1Q) or 0x88A8(802.1AD). The default value
|
||||||
|
* is 0x8100(802.1Q).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_GROUP_FWD_MASK
|
||||||
|
* The group forwarding mask. This is the bitmask that is applied to
|
||||||
|
* decide whether to forward incoming frames destined to link-local
|
||||||
|
* addresses (of the form 01:80:C2:00:00:0X).
|
||||||
|
*
|
||||||
|
* The default value is 0, which means the bridge does not forward any
|
||||||
|
* link-local frames coming on this port.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_ROOT_ID
|
||||||
|
* The bridge root id, read only.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_BRIDGE_ID
|
||||||
|
* The bridge id, read only.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_ROOT_PORT
|
||||||
|
* The bridge root port, read only.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_ROOT_PATH_COST
|
||||||
|
* The bridge root path cost, read only.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_TOPOLOGY_CHANGE
|
||||||
|
* The bridge topology change, read only.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_TOPOLOGY_CHANGE_DETECTED
|
||||||
|
* The bridge topology change detected, read only.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_HELLO_TIMER
|
||||||
|
* The bridge hello timer, read only.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_TCN_TIMER
|
||||||
|
* The bridge tcn timer, read only.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_TOPOLOGY_CHANGE_TIMER
|
||||||
|
* The bridge topology change timer, read only.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_GC_TIMER
|
||||||
|
* The bridge gc timer, read only.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_GROUP_ADDR
|
||||||
|
* Set the MAC address of the multicast group this bridge uses for STP.
|
||||||
|
* The address must be a link-local address in standard Ethernet MAC address
|
||||||
|
* format. It is an address of the form 01:80:C2:00:00:0X, with X in [0, 4..f].
|
||||||
|
*
|
||||||
|
* The default value is 0.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_FDB_FLUSH
|
||||||
|
* Flush bridge's fdb dynamic entries.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_MCAST_ROUTER
|
||||||
|
* Set bridge's multicast router if IGMP snooping is enabled.
|
||||||
|
* The valid values are:
|
||||||
|
*
|
||||||
|
* * 0 - disabled.
|
||||||
|
* * 1 - automatic (queried).
|
||||||
|
* * 2 - permanently enabled.
|
||||||
|
*
|
||||||
|
* The default value is 1.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_MCAST_SNOOPING
|
||||||
|
* Turn multicast snooping on (*IFLA_BR_MCAST_SNOOPING* > 0) or off
|
||||||
|
* (*IFLA_BR_MCAST_SNOOPING* == 0).
|
||||||
|
*
|
||||||
|
* The default value is 1.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_MCAST_QUERY_USE_IFADDR
|
||||||
|
* If enabled use the bridge's own IP address as source address for IGMP
|
||||||
|
* queries (*IFLA_BR_MCAST_QUERY_USE_IFADDR* > 0) or the default of 0.0.0.0
|
||||||
|
* (*IFLA_BR_MCAST_QUERY_USE_IFADDR* == 0).
|
||||||
|
*
|
||||||
|
* The default value is 0 (disabled).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_MCAST_QUERIER
|
||||||
|
* Enable (*IFLA_BR_MULTICAST_QUERIER* > 0) or disable
|
||||||
|
* (*IFLA_BR_MULTICAST_QUERIER* == 0) IGMP querier, ie sending of multicast
|
||||||
|
* queries by the bridge.
|
||||||
|
*
|
||||||
|
* The default value is 0 (disabled).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_MCAST_HASH_ELASTICITY
|
||||||
|
* Set multicast database hash elasticity, It is the maximum chain length in
|
||||||
|
* the multicast hash table. This attribute is *deprecated* and the value
|
||||||
|
* is always 16.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_MCAST_HASH_MAX
|
||||||
|
* Set maximum size of the multicast hash table
|
||||||
|
*
|
||||||
|
* The default value is 4096, the value must be a power of 2.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_MCAST_LAST_MEMBER_CNT
|
||||||
|
* The Last Member Query Count is the number of Group-Specific Queries
|
||||||
|
* sent before the router assumes there are no local members. The Last
|
||||||
|
* Member Query Count is also the number of Group-and-Source-Specific
|
||||||
|
* Queries sent before the router assumes there are no listeners for a
|
||||||
|
* particular source.
|
||||||
|
*
|
||||||
|
* The default value is 2.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_MCAST_STARTUP_QUERY_CNT
|
||||||
|
* The Startup Query Count is the number of Queries sent out on startup,
|
||||||
|
* separated by the Startup Query Interval.
|
||||||
|
*
|
||||||
|
* The default value is 2.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_MCAST_LAST_MEMBER_INTVL
|
||||||
|
* The Last Member Query Interval is the Max Response Time inserted into
|
||||||
|
* Group-Specific Queries sent in response to Leave Group messages, and
|
||||||
|
* is also the amount of time between Group-Specific Query messages.
|
||||||
|
*
|
||||||
|
* The default value is (1 * USER_HZ).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_MCAST_MEMBERSHIP_INTVL
|
||||||
|
* The interval after which the bridge will leave a group, if no membership
|
||||||
|
* reports for this group are received.
|
||||||
|
*
|
||||||
|
* The default value is (260 * USER_HZ).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_MCAST_QUERIER_INTVL
|
||||||
|
* The interval between queries sent by other routers. if no queries are
|
||||||
|
* seen after this delay has passed, the bridge will start to send its own
|
||||||
|
* queries (as if *IFLA_BR_MCAST_QUERIER_INTVL* was enabled).
|
||||||
|
*
|
||||||
|
* The default value is (255 * USER_HZ).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_MCAST_QUERY_INTVL
|
||||||
|
* The Query Interval is the interval between General Queries sent by
|
||||||
|
* the Querier.
|
||||||
|
*
|
||||||
|
* The default value is (125 * USER_HZ). The minimum value is (1 * USER_HZ).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_MCAST_QUERY_RESPONSE_INTVL
|
||||||
|
* The Max Response Time used to calculate the Max Resp Code inserted
|
||||||
|
* into the periodic General Queries.
|
||||||
|
*
|
||||||
|
* The default value is (10 * USER_HZ).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_MCAST_STARTUP_QUERY_INTVL
|
||||||
|
* The interval between queries in the startup phase.
|
||||||
|
*
|
||||||
|
* The default value is (125 * USER_HZ) / 4. The minimum value is (1 * USER_HZ).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_NF_CALL_IPTABLES
|
||||||
|
* Enable (*NF_CALL_IPTABLES* > 0) or disable (*NF_CALL_IPTABLES* == 0)
|
||||||
|
* iptables hooks on the bridge.
|
||||||
|
*
|
||||||
|
* The default value is 0 (disabled).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_NF_CALL_IP6TABLES
|
||||||
|
* Enable (*NF_CALL_IP6TABLES* > 0) or disable (*NF_CALL_IP6TABLES* == 0)
|
||||||
|
* ip6tables hooks on the bridge.
|
||||||
|
*
|
||||||
|
* The default value is 0 (disabled).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_NF_CALL_ARPTABLES
|
||||||
|
* Enable (*NF_CALL_ARPTABLES* > 0) or disable (*NF_CALL_ARPTABLES* == 0)
|
||||||
|
* arptables hooks on the bridge.
|
||||||
|
*
|
||||||
|
* The default value is 0 (disabled).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_VLAN_DEFAULT_PVID
|
||||||
|
* VLAN ID applied to untagged and priority-tagged incoming packets.
|
||||||
|
*
|
||||||
|
* The default value is 1. Setting to the special value 0 makes all ports of
|
||||||
|
* this bridge not have a PVID by default, which means that they will
|
||||||
|
* not accept VLAN-untagged traffic.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_PAD
|
||||||
|
* Bridge attribute padding type for netlink message.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_VLAN_STATS_ENABLED
|
||||||
|
* Enable (*IFLA_BR_VLAN_STATS_ENABLED* == 1) or disable
|
||||||
|
* (*IFLA_BR_VLAN_STATS_ENABLED* == 0) per-VLAN stats accounting.
|
||||||
|
*
|
||||||
|
* The default value is 0 (disabled).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_MCAST_STATS_ENABLED
|
||||||
|
* Enable (*IFLA_BR_MCAST_STATS_ENABLED* > 0) or disable
|
||||||
|
* (*IFLA_BR_MCAST_STATS_ENABLED* == 0) multicast (IGMP/MLD) stats
|
||||||
|
* accounting.
|
||||||
|
*
|
||||||
|
* The default value is 0 (disabled).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_MCAST_IGMP_VERSION
|
||||||
|
* Set the IGMP version.
|
||||||
|
*
|
||||||
|
* The valid values are 2 and 3. The default value is 2.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_MCAST_MLD_VERSION
|
||||||
|
* Set the MLD version.
|
||||||
|
*
|
||||||
|
* The valid values are 1 and 2. The default value is 1.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_VLAN_STATS_PER_PORT
|
||||||
|
* Enable (*IFLA_BR_VLAN_STATS_PER_PORT* == 1) or disable
|
||||||
|
* (*IFLA_BR_VLAN_STATS_PER_PORT* == 0) per-VLAN per-port stats accounting.
|
||||||
|
* Can be changed only when there are no port VLANs configured.
|
||||||
|
*
|
||||||
|
* The default value is 0 (disabled).
|
||||||
|
*
|
||||||
|
* @IFLA_BR_MULTI_BOOLOPT
|
||||||
|
* The multi_boolopt is used to control new boolean options to avoid adding
|
||||||
|
* new netlink attributes. You can look at ``enum br_boolopt_id`` for those
|
||||||
|
* options.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_MCAST_QUERIER_STATE
|
||||||
|
* Bridge mcast querier states, read only.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_FDB_N_LEARNED
|
||||||
|
* The number of dynamically learned FDB entries for the current bridge,
|
||||||
|
* read only.
|
||||||
|
*
|
||||||
|
* @IFLA_BR_FDB_MAX_LEARNED
|
||||||
|
* Set the number of max dynamically learned FDB entries for the current
|
||||||
|
* bridge.
|
||||||
|
*/
|
||||||
enum {
|
enum {
|
||||||
IFLA_BR_UNSPEC,
|
IFLA_BR_UNSPEC,
|
||||||
IFLA_BR_FORWARD_DELAY,
|
IFLA_BR_FORWARD_DELAY,
|
||||||
@@ -510,6 +794,8 @@ enum {
|
|||||||
IFLA_BR_VLAN_STATS_PER_PORT,
|
IFLA_BR_VLAN_STATS_PER_PORT,
|
||||||
IFLA_BR_MULTI_BOOLOPT,
|
IFLA_BR_MULTI_BOOLOPT,
|
||||||
IFLA_BR_MCAST_QUERIER_STATE,
|
IFLA_BR_MCAST_QUERIER_STATE,
|
||||||
|
IFLA_BR_FDB_N_LEARNED,
|
||||||
|
IFLA_BR_FDB_MAX_LEARNED,
|
||||||
__IFLA_BR_MAX,
|
__IFLA_BR_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -520,11 +806,252 @@ struct ifla_bridge_id {
|
|||||||
__u8 addr[6]; /* ETH_ALEN */
|
__u8 addr[6]; /* ETH_ALEN */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DOC: Bridge mode enum definition
|
||||||
|
*
|
||||||
|
* @BRIDGE_MODE_HAIRPIN
|
||||||
|
* Controls whether traffic may be sent back out of the port on which it
|
||||||
|
* was received. This option is also called reflective relay mode, and is
|
||||||
|
* used to support basic VEPA (Virtual Ethernet Port Aggregator)
|
||||||
|
* capabilities. By default, this flag is turned off and the bridge will
|
||||||
|
* not forward traffic back out of the receiving port.
|
||||||
|
*/
|
||||||
enum {
|
enum {
|
||||||
BRIDGE_MODE_UNSPEC,
|
BRIDGE_MODE_UNSPEC,
|
||||||
BRIDGE_MODE_HAIRPIN,
|
BRIDGE_MODE_HAIRPIN,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DOC: Bridge port enum definition
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_STATE
|
||||||
|
* The operation state of the port. Here are the valid values.
|
||||||
|
*
|
||||||
|
* * 0 - port is in STP *DISABLED* state. Make this port completely
|
||||||
|
* inactive for STP. This is also called BPDU filter and could be used
|
||||||
|
* to disable STP on an untrusted port, like a leaf virtual device.
|
||||||
|
* The traffic forwarding is also stopped on this port.
|
||||||
|
* * 1 - port is in STP *LISTENING* state. Only valid if STP is enabled
|
||||||
|
* on the bridge. In this state the port listens for STP BPDUs and
|
||||||
|
* drops all other traffic frames.
|
||||||
|
* * 2 - port is in STP *LEARNING* state. Only valid if STP is enabled on
|
||||||
|
* the bridge. In this state the port will accept traffic only for the
|
||||||
|
* purpose of updating MAC address tables.
|
||||||
|
* * 3 - port is in STP *FORWARDING* state. Port is fully active.
|
||||||
|
* * 4 - port is in STP *BLOCKING* state. Only valid if STP is enabled on
|
||||||
|
* the bridge. This state is used during the STP election process.
|
||||||
|
* In this state, port will only process STP BPDUs.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_PRIORITY
|
||||||
|
* The STP port priority. The valid values are between 0 and 255.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_COST
|
||||||
|
* The STP path cost of the port. The valid values are between 1 and 65535.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_MODE
|
||||||
|
* Set the bridge port mode. See *BRIDGE_MODE_HAIRPIN* for more details.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_GUARD
|
||||||
|
* Controls whether STP BPDUs will be processed by the bridge port. By
|
||||||
|
* default, the flag is turned off to allow BPDU processing. Turning this
|
||||||
|
* flag on will disable the bridge port if a STP BPDU packet is received.
|
||||||
|
*
|
||||||
|
* If the bridge has Spanning Tree enabled, hostile devices on the network
|
||||||
|
* may send BPDU on a port and cause network failure. Setting *guard on*
|
||||||
|
* will detect and stop this by disabling the port. The port will be
|
||||||
|
* restarted if the link is brought down, or removed and reattached.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_PROTECT
|
||||||
|
* Controls whether a given port is allowed to become a root port or not.
|
||||||
|
* Only used when STP is enabled on the bridge. By default the flag is off.
|
||||||
|
*
|
||||||
|
* This feature is also called root port guard. If BPDU is received from a
|
||||||
|
* leaf (edge) port, it should not be elected as root port. This could
|
||||||
|
* be used if using STP on a bridge and the downstream bridges are not fully
|
||||||
|
* trusted; this prevents a hostile guest from rerouting traffic.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_FAST_LEAVE
|
||||||
|
* This flag allows the bridge to immediately stop multicast traffic
|
||||||
|
* forwarding on a port that receives an IGMP Leave message. It is only used
|
||||||
|
* when IGMP snooping is enabled on the bridge. By default the flag is off.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_LEARNING
|
||||||
|
* Controls whether a given port will learn *source* MAC addresses from
|
||||||
|
* received traffic or not. Also controls whether dynamic FDB entries
|
||||||
|
* (which can also be added by software) will be refreshed by incoming
|
||||||
|
* traffic. By default this flag is on.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_UNICAST_FLOOD
|
||||||
|
* Controls whether unicast traffic for which there is no FDB entry will
|
||||||
|
* be flooded towards this port. By default this flag is on.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_PROXYARP
|
||||||
|
* Enable proxy ARP on this port.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_LEARNING_SYNC
|
||||||
|
* Controls whether a given port will sync MAC addresses learned on device
|
||||||
|
* port to bridge FDB.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_PROXYARP_WIFI
|
||||||
|
* Enable proxy ARP on this port which meets extended requirements by
|
||||||
|
* IEEE 802.11 and Hotspot 2.0 specifications.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_ROOT_ID
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_BRIDGE_ID
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_DESIGNATED_PORT
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_DESIGNATED_COST
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_ID
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_NO
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_TOPOLOGY_CHANGE_ACK
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_CONFIG_PENDING
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_MESSAGE_AGE_TIMER
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_FORWARD_DELAY_TIMER
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_HOLD_TIMER
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_FLUSH
|
||||||
|
* Flush bridge ports' fdb dynamic entries.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_MULTICAST_ROUTER
|
||||||
|
* Configure the port's multicast router presence. A port with
|
||||||
|
* a multicast router will receive all multicast traffic.
|
||||||
|
* The valid values are:
|
||||||
|
*
|
||||||
|
* * 0 disable multicast routers on this port
|
||||||
|
* * 1 let the system detect the presence of routers (default)
|
||||||
|
* * 2 permanently enable multicast traffic forwarding on this port
|
||||||
|
* * 3 enable multicast routers temporarily on this port, not depending
|
||||||
|
* on incoming queries.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_PAD
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_MCAST_FLOOD
|
||||||
|
* Controls whether a given port will flood multicast traffic for which
|
||||||
|
* there is no MDB entry. By default this flag is on.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_MCAST_TO_UCAST
|
||||||
|
* Controls whether a given port will replicate packets using unicast
|
||||||
|
* instead of multicast. By default this flag is off.
|
||||||
|
*
|
||||||
|
* This is done by copying the packet per host and changing the multicast
|
||||||
|
* destination MAC to a unicast one accordingly.
|
||||||
|
*
|
||||||
|
* *mcast_to_unicast* works on top of the multicast snooping feature of the
|
||||||
|
* bridge. Which means unicast copies are only delivered to hosts which
|
||||||
|
* are interested in unicast and signaled this via IGMP/MLD reports previously.
|
||||||
|
*
|
||||||
|
* This feature is intended for interface types which have a more reliable
|
||||||
|
* and/or efficient way to deliver unicast packets than broadcast ones
|
||||||
|
* (e.g. WiFi).
|
||||||
|
*
|
||||||
|
* However, it should only be enabled on interfaces where no IGMPv2/MLDv1
|
||||||
|
* report suppression takes place. IGMP/MLD report suppression issue is
|
||||||
|
* usually overcome by the network daemon (supplicant) enabling AP isolation
|
||||||
|
* and by that separating all STAs.
|
||||||
|
*
|
||||||
|
* Delivery of STA-to-STA IP multicast is made possible again by enabling
|
||||||
|
* and utilizing the bridge hairpin mode, which considers the incoming port
|
||||||
|
* as a potential outgoing port, too (see *BRIDGE_MODE_HAIRPIN* option).
|
||||||
|
* Hairpin mode is performed after multicast snooping, therefore leading
|
||||||
|
* to only deliver reports to STAs running a multicast router.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_VLAN_TUNNEL
|
||||||
|
* Controls whether vlan to tunnel mapping is enabled on the port.
|
||||||
|
* By default this flag is off.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_BCAST_FLOOD
|
||||||
|
* Controls flooding of broadcast traffic on the given port. By default
|
||||||
|
* this flag is on.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_GROUP_FWD_MASK
|
||||||
|
* Set the group forward mask. This is a bitmask that is applied to
|
||||||
|
* decide whether to forward incoming frames destined to link-local
|
||||||
|
* addresses. The addresses of the form are 01:80:C2:00:00:0X (defaults
|
||||||
|
* to 0, which means the bridge does not forward any link-local frames
|
||||||
|
* coming on this port).
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_NEIGH_SUPPRESS
|
||||||
|
* Controls whether neighbor discovery (arp and nd) proxy and suppression
|
||||||
|
* is enabled on the port. By default this flag is off.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_ISOLATED
|
||||||
|
* Controls whether a given port will be isolated, which means it will be
|
||||||
|
* able to communicate with non-isolated ports only. By default this
|
||||||
|
* flag is off.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_BACKUP_PORT
|
||||||
|
* Set a backup port. If the port loses carrier all traffic will be
|
||||||
|
* redirected to the configured backup port. Set the value to 0 to disable
|
||||||
|
* it.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_MRP_RING_OPEN
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_MRP_IN_OPEN
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT
|
||||||
|
* The number of per-port EHT hosts limit. The default value is 512.
|
||||||
|
* Setting to 0 is not allowed.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_MCAST_EHT_HOSTS_CNT
|
||||||
|
* The current number of tracked hosts, read only.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_LOCKED
|
||||||
|
* Controls whether a port will be locked, meaning that hosts behind the
|
||||||
|
* port will not be able to communicate through the port unless an FDB
|
||||||
|
* entry with the unit's MAC address is in the FDB. The common use case is
|
||||||
|
* that hosts are allowed access through authentication with the IEEE 802.1X
|
||||||
|
* protocol or based on whitelists. By default this flag is off.
|
||||||
|
*
|
||||||
|
* Please note that secure 802.1X deployments should always use the
|
||||||
|
* *BR_BOOLOPT_NO_LL_LEARN* flag, to not permit the bridge to populate its
|
||||||
|
* FDB based on link-local (EAPOL) traffic received on the port.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_MAB
|
||||||
|
* Controls whether a port will use MAC Authentication Bypass (MAB), a
|
||||||
|
* technique through which select MAC addresses may be allowed on a locked
|
||||||
|
* port, without using 802.1X authentication. Packets with an unknown source
|
||||||
|
* MAC address generates a "locked" FDB entry on the incoming bridge port.
|
||||||
|
* The common use case is for user space to react to these bridge FDB
|
||||||
|
* notifications and optionally replace the locked FDB entry with a normal
|
||||||
|
* one, allowing traffic to pass for whitelisted MAC addresses.
|
||||||
|
*
|
||||||
|
* Setting this flag also requires *IFLA_BRPORT_LOCKED* and
|
||||||
|
* *IFLA_BRPORT_LEARNING*. *IFLA_BRPORT_LOCKED* ensures that unauthorized
|
||||||
|
* data packets are dropped, and *IFLA_BRPORT_LEARNING* allows the dynamic
|
||||||
|
* FDB entries installed by user space (as replacements for the locked FDB
|
||||||
|
* entries) to be refreshed and/or aged out.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_MCAST_N_GROUPS
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_MCAST_MAX_GROUPS
|
||||||
|
* Sets the maximum number of MDB entries that can be registered for a
|
||||||
|
* given port. Attempts to register more MDB entries at the port than this
|
||||||
|
* limit allows will be rejected, whether they are done through netlink
|
||||||
|
* (e.g. the bridge tool), or IGMP or MLD membership reports. Setting a
|
||||||
|
* limit of 0 disables the limit. The default value is 0.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_NEIGH_VLAN_SUPPRESS
|
||||||
|
* Controls whether neighbor discovery (arp and nd) proxy and suppression is
|
||||||
|
* enabled for a given port. By default this flag is off.
|
||||||
|
*
|
||||||
|
* Note that this option only takes effect when *IFLA_BRPORT_NEIGH_SUPPRESS*
|
||||||
|
* is enabled for a given port.
|
||||||
|
*
|
||||||
|
* @IFLA_BRPORT_BACKUP_NHID
|
||||||
|
* The FDB nexthop object ID to attach to packets being redirected to a
|
||||||
|
* backup port that has VLAN tunnel mapping enabled (via the
|
||||||
|
* *IFLA_BRPORT_VLAN_TUNNEL* option). Setting a value of 0 (default) has
|
||||||
|
* the effect of not attaching any ID.
|
||||||
|
*/
|
||||||
enum {
|
enum {
|
||||||
IFLA_BRPORT_UNSPEC,
|
IFLA_BRPORT_UNSPEC,
|
||||||
IFLA_BRPORT_STATE, /* Spanning tree state */
|
IFLA_BRPORT_STATE, /* Spanning tree state */
|
||||||
@@ -769,6 +1296,19 @@ enum netkit_mode {
|
|||||||
NETKIT_L3,
|
NETKIT_L3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* NETKIT_SCRUB_NONE leaves clearing skb->{mark,priority} up to
|
||||||
|
* the BPF program if attached. This also means the latter can
|
||||||
|
* consume the two fields if they were populated earlier.
|
||||||
|
*
|
||||||
|
* NETKIT_SCRUB_DEFAULT zeroes skb->{mark,priority} fields before
|
||||||
|
* invoking the attached BPF program when the peer device resides
|
||||||
|
* in a different network namespace. This is the default behavior.
|
||||||
|
*/
|
||||||
|
enum netkit_scrub {
|
||||||
|
NETKIT_SCRUB_NONE,
|
||||||
|
NETKIT_SCRUB_DEFAULT,
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
IFLA_NETKIT_UNSPEC,
|
IFLA_NETKIT_UNSPEC,
|
||||||
IFLA_NETKIT_PEER_INFO,
|
IFLA_NETKIT_PEER_INFO,
|
||||||
@@ -776,6 +1316,10 @@ enum {
|
|||||||
IFLA_NETKIT_POLICY,
|
IFLA_NETKIT_POLICY,
|
||||||
IFLA_NETKIT_PEER_POLICY,
|
IFLA_NETKIT_PEER_POLICY,
|
||||||
IFLA_NETKIT_MODE,
|
IFLA_NETKIT_MODE,
|
||||||
|
IFLA_NETKIT_SCRUB,
|
||||||
|
IFLA_NETKIT_PEER_SCRUB,
|
||||||
|
IFLA_NETKIT_HEADROOM,
|
||||||
|
IFLA_NETKIT_TAILROOM,
|
||||||
__IFLA_NETKIT_MAX,
|
__IFLA_NETKIT_MAX,
|
||||||
};
|
};
|
||||||
#define IFLA_NETKIT_MAX (__IFLA_NETKIT_MAX - 1)
|
#define IFLA_NETKIT_MAX (__IFLA_NETKIT_MAX - 1)
|
||||||
@@ -854,6 +1398,9 @@ enum {
|
|||||||
IFLA_VXLAN_DF,
|
IFLA_VXLAN_DF,
|
||||||
IFLA_VXLAN_VNIFILTER, /* only applicable with COLLECT_METADATA mode */
|
IFLA_VXLAN_VNIFILTER, /* only applicable with COLLECT_METADATA mode */
|
||||||
IFLA_VXLAN_LOCALBYPASS,
|
IFLA_VXLAN_LOCALBYPASS,
|
||||||
|
IFLA_VXLAN_LABEL_POLICY, /* IPv6 flow label policy; ifla_vxlan_label_policy */
|
||||||
|
IFLA_VXLAN_RESERVED_BITS,
|
||||||
|
IFLA_VXLAN_MC_ROUTE,
|
||||||
__IFLA_VXLAN_MAX
|
__IFLA_VXLAN_MAX
|
||||||
};
|
};
|
||||||
#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
|
#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
|
||||||
@@ -871,6 +1418,13 @@ enum ifla_vxlan_df {
|
|||||||
VXLAN_DF_MAX = __VXLAN_DF_END - 1,
|
VXLAN_DF_MAX = __VXLAN_DF_END - 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ifla_vxlan_label_policy {
|
||||||
|
VXLAN_LABEL_FIXED = 0,
|
||||||
|
VXLAN_LABEL_INHERIT = 1,
|
||||||
|
__VXLAN_LABEL_END,
|
||||||
|
VXLAN_LABEL_MAX = __VXLAN_LABEL_END - 1,
|
||||||
|
};
|
||||||
|
|
||||||
/* GENEVE section */
|
/* GENEVE section */
|
||||||
enum {
|
enum {
|
||||||
IFLA_GENEVE_UNSPEC,
|
IFLA_GENEVE_UNSPEC,
|
||||||
@@ -888,6 +1442,7 @@ enum {
|
|||||||
IFLA_GENEVE_TTL_INHERIT,
|
IFLA_GENEVE_TTL_INHERIT,
|
||||||
IFLA_GENEVE_DF,
|
IFLA_GENEVE_DF,
|
||||||
IFLA_GENEVE_INNER_PROTO_INHERIT,
|
IFLA_GENEVE_INNER_PROTO_INHERIT,
|
||||||
|
IFLA_GENEVE_PORT_RANGE,
|
||||||
__IFLA_GENEVE_MAX
|
__IFLA_GENEVE_MAX
|
||||||
};
|
};
|
||||||
#define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1)
|
#define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1)
|
||||||
@@ -900,6 +1455,11 @@ enum ifla_geneve_df {
|
|||||||
GENEVE_DF_MAX = __GENEVE_DF_END - 1,
|
GENEVE_DF_MAX = __GENEVE_DF_END - 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ifla_geneve_port_range {
|
||||||
|
__be16 low;
|
||||||
|
__be16 high;
|
||||||
|
};
|
||||||
|
|
||||||
/* Bareudp section */
|
/* Bareudp section */
|
||||||
enum {
|
enum {
|
||||||
IFLA_BAREUDP_UNSPEC,
|
IFLA_BAREUDP_UNSPEC,
|
||||||
@@ -935,6 +1495,8 @@ enum {
|
|||||||
IFLA_GTP_ROLE,
|
IFLA_GTP_ROLE,
|
||||||
IFLA_GTP_CREATE_SOCKETS,
|
IFLA_GTP_CREATE_SOCKETS,
|
||||||
IFLA_GTP_RESTART_COUNT,
|
IFLA_GTP_RESTART_COUNT,
|
||||||
|
IFLA_GTP_LOCAL,
|
||||||
|
IFLA_GTP_LOCAL6,
|
||||||
__IFLA_GTP_MAX,
|
__IFLA_GTP_MAX,
|
||||||
};
|
};
|
||||||
#define IFLA_GTP_MAX (__IFLA_GTP_MAX - 1)
|
#define IFLA_GTP_MAX (__IFLA_GTP_MAX - 1)
|
||||||
@@ -975,6 +1537,7 @@ enum {
|
|||||||
IFLA_BOND_MISSED_MAX,
|
IFLA_BOND_MISSED_MAX,
|
||||||
IFLA_BOND_NS_IP6_TARGET,
|
IFLA_BOND_NS_IP6_TARGET,
|
||||||
IFLA_BOND_COUPLED_CONTROL,
|
IFLA_BOND_COUPLED_CONTROL,
|
||||||
|
IFLA_BOND_BROADCAST_NEIGH,
|
||||||
__IFLA_BOND_MAX,
|
__IFLA_BOND_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1003,6 +1566,7 @@ enum {
|
|||||||
IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE,
|
IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE,
|
||||||
IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE,
|
IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE,
|
||||||
IFLA_BOND_SLAVE_PRIO,
|
IFLA_BOND_SLAVE_PRIO,
|
||||||
|
IFLA_BOND_SLAVE_ACTOR_PORT_PRIO,
|
||||||
__IFLA_BOND_SLAVE_MAX,
|
__IFLA_BOND_SLAVE_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1240,6 +1804,7 @@ enum {
|
|||||||
IFLA_HSR_PROTOCOL, /* Indicate different protocol than
|
IFLA_HSR_PROTOCOL, /* Indicate different protocol than
|
||||||
* HSR. For example PRP.
|
* HSR. For example PRP.
|
||||||
*/
|
*/
|
||||||
|
IFLA_HSR_INTERLINK, /* HSR interlink network device */
|
||||||
__IFLA_HSR_MAX,
|
__IFLA_HSR_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1408,6 +1973,7 @@ struct ifla_rmnet_flags {
|
|||||||
enum {
|
enum {
|
||||||
IFLA_MCTP_UNSPEC,
|
IFLA_MCTP_UNSPEC,
|
||||||
IFLA_MCTP_NET,
|
IFLA_MCTP_NET,
|
||||||
|
IFLA_MCTP_PHYS_BINDING,
|
||||||
__IFLA_MCTP_MAX,
|
__IFLA_MCTP_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1417,10 +1983,27 @@ enum {
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
IFLA_DSA_UNSPEC,
|
IFLA_DSA_UNSPEC,
|
||||||
IFLA_DSA_MASTER,
|
IFLA_DSA_CONDUIT,
|
||||||
|
/* Deprecated, use IFLA_DSA_CONDUIT instead */
|
||||||
|
IFLA_DSA_MASTER = IFLA_DSA_CONDUIT,
|
||||||
__IFLA_DSA_MAX,
|
__IFLA_DSA_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define IFLA_DSA_MAX (__IFLA_DSA_MAX - 1)
|
#define IFLA_DSA_MAX (__IFLA_DSA_MAX - 1)
|
||||||
|
|
||||||
#endif /* _UAPI_LINUX_IF_LINK_H */
|
/* OVPN section */
|
||||||
|
|
||||||
|
enum ovpn_mode {
|
||||||
|
OVPN_MODE_P2P,
|
||||||
|
OVPN_MODE_MP,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
IFLA_OVPN_UNSPEC,
|
||||||
|
IFLA_OVPN_MODE,
|
||||||
|
__IFLA_OVPN_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define IFLA_OVPN_MAX (__IFLA_OVPN_MAX - 1)
|
||||||
|
|
||||||
|
#endif /* _LINUX_IF_LINK_H */
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ struct xdp_mmap_offsets {
|
|||||||
#define XDP_UMEM_COMPLETION_RING 6
|
#define XDP_UMEM_COMPLETION_RING 6
|
||||||
#define XDP_STATISTICS 7
|
#define XDP_STATISTICS 7
|
||||||
#define XDP_OPTIONS 8
|
#define XDP_OPTIONS 8
|
||||||
|
#define XDP_MAX_TX_SKB_BUDGET 9
|
||||||
|
|
||||||
struct xdp_umem_reg {
|
struct xdp_umem_reg {
|
||||||
__u64 addr; /* Start of packet data area */
|
__u64 addr; /* Start of packet data area */
|
||||||
@@ -117,16 +118,22 @@ struct xdp_options {
|
|||||||
((1ULL << XSK_UNALIGNED_BUF_OFFSET_SHIFT) - 1)
|
((1ULL << XSK_UNALIGNED_BUF_OFFSET_SHIFT) - 1)
|
||||||
|
|
||||||
/* Request transmit timestamp. Upon completion, put it into tx_timestamp
|
/* Request transmit timestamp. Upon completion, put it into tx_timestamp
|
||||||
* field of union xsk_tx_metadata.
|
* field of struct xsk_tx_metadata.
|
||||||
*/
|
*/
|
||||||
#define XDP_TXMD_FLAGS_TIMESTAMP (1 << 0)
|
#define XDP_TXMD_FLAGS_TIMESTAMP (1 << 0)
|
||||||
|
|
||||||
/* Request transmit checksum offload. Checksum start position and offset
|
/* Request transmit checksum offload. Checksum start position and offset
|
||||||
* are communicated via csum_start and csum_offset fields of union
|
* are communicated via csum_start and csum_offset fields of struct
|
||||||
* xsk_tx_metadata.
|
* xsk_tx_metadata.
|
||||||
*/
|
*/
|
||||||
#define XDP_TXMD_FLAGS_CHECKSUM (1 << 1)
|
#define XDP_TXMD_FLAGS_CHECKSUM (1 << 1)
|
||||||
|
|
||||||
|
/* Request launch time hardware offload. The device will schedule the packet for
|
||||||
|
* transmission at a pre-determined time called launch time. The value of
|
||||||
|
* launch time is communicated via launch_time field of struct xsk_tx_metadata.
|
||||||
|
*/
|
||||||
|
#define XDP_TXMD_FLAGS_LAUNCH_TIME (1 << 2)
|
||||||
|
|
||||||
/* AF_XDP offloads request. 'request' union member is consumed by the driver
|
/* AF_XDP offloads request. 'request' union member is consumed by the driver
|
||||||
* when the packet is being transmitted. 'completion' union member is
|
* when the packet is being transmitted. 'completion' union member is
|
||||||
* filled by the driver when the transmit completion arrives.
|
* filled by the driver when the transmit completion arrives.
|
||||||
@@ -142,6 +149,10 @@ struct xsk_tx_metadata {
|
|||||||
__u16 csum_start;
|
__u16 csum_start;
|
||||||
/* Offset from csum_start where checksum should be stored. */
|
/* Offset from csum_start where checksum should be stored. */
|
||||||
__u16 csum_offset;
|
__u16 csum_offset;
|
||||||
|
|
||||||
|
/* XDP_TXMD_FLAGS_LAUNCH_TIME */
|
||||||
|
/* Launch time in nanosecond against the PTP HW Clock */
|
||||||
|
__u64 launch_time;
|
||||||
} request;
|
} request;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
@@ -2,9 +2,10 @@
|
|||||||
/* Do not edit directly, auto-generated from: */
|
/* Do not edit directly, auto-generated from: */
|
||||||
/* Documentation/netlink/specs/netdev.yaml */
|
/* Documentation/netlink/specs/netdev.yaml */
|
||||||
/* YNL-GEN uapi header */
|
/* YNL-GEN uapi header */
|
||||||
|
/* To regenerate run: tools/net/ynl/ynl-regen.sh */
|
||||||
|
|
||||||
#ifndef _UAPI_LINUX_NETDEV_H
|
#ifndef _LINUX_NETDEV_H
|
||||||
#define _UAPI_LINUX_NETDEV_H
|
#define _LINUX_NETDEV_H
|
||||||
|
|
||||||
#define NETDEV_FAMILY_NAME "netdev"
|
#define NETDEV_FAMILY_NAME "netdev"
|
||||||
#define NETDEV_FAMILY_VERSION 1
|
#define NETDEV_FAMILY_VERSION 1
|
||||||
@@ -59,10 +60,13 @@ enum netdev_xdp_rx_metadata {
|
|||||||
* by the driver.
|
* by the driver.
|
||||||
* @NETDEV_XSK_FLAGS_TX_CHECKSUM: L3 checksum HW offload is supported by the
|
* @NETDEV_XSK_FLAGS_TX_CHECKSUM: L3 checksum HW offload is supported by the
|
||||||
* driver.
|
* driver.
|
||||||
|
* @NETDEV_XSK_FLAGS_TX_LAUNCH_TIME_FIFO: Launch time HW offload is supported
|
||||||
|
* by the driver.
|
||||||
*/
|
*/
|
||||||
enum netdev_xsk_flags {
|
enum netdev_xsk_flags {
|
||||||
NETDEV_XSK_FLAGS_TX_TIMESTAMP = 1,
|
NETDEV_XSK_FLAGS_TX_TIMESTAMP = 1,
|
||||||
NETDEV_XSK_FLAGS_TX_CHECKSUM = 2,
|
NETDEV_XSK_FLAGS_TX_CHECKSUM = 2,
|
||||||
|
NETDEV_XSK_FLAGS_TX_LAUNCH_TIME_FIFO = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum netdev_queue_type {
|
enum netdev_queue_type {
|
||||||
@@ -74,6 +78,12 @@ enum netdev_qstats_scope {
|
|||||||
NETDEV_QSTATS_SCOPE_QUEUE = 1,
|
NETDEV_QSTATS_SCOPE_QUEUE = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum netdev_napi_threaded {
|
||||||
|
NETDEV_NAPI_THREADED_DISABLED,
|
||||||
|
NETDEV_NAPI_THREADED_ENABLED,
|
||||||
|
NETDEV_NAPI_THREADED_BUSY_POLL,
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
NETDEV_A_DEV_IFINDEX = 1,
|
NETDEV_A_DEV_IFINDEX = 1,
|
||||||
NETDEV_A_DEV_PAD,
|
NETDEV_A_DEV_PAD,
|
||||||
@@ -86,6 +96,11 @@ enum {
|
|||||||
NETDEV_A_DEV_MAX = (__NETDEV_A_DEV_MAX - 1)
|
NETDEV_A_DEV_MAX = (__NETDEV_A_DEV_MAX - 1)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
__NETDEV_A_IO_URING_PROVIDER_INFO_MAX,
|
||||||
|
NETDEV_A_IO_URING_PROVIDER_INFO_MAX = (__NETDEV_A_IO_URING_PROVIDER_INFO_MAX - 1)
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
NETDEV_A_PAGE_POOL_ID = 1,
|
NETDEV_A_PAGE_POOL_ID = 1,
|
||||||
NETDEV_A_PAGE_POOL_IFINDEX,
|
NETDEV_A_PAGE_POOL_IFINDEX,
|
||||||
@@ -93,6 +108,8 @@ enum {
|
|||||||
NETDEV_A_PAGE_POOL_INFLIGHT,
|
NETDEV_A_PAGE_POOL_INFLIGHT,
|
||||||
NETDEV_A_PAGE_POOL_INFLIGHT_MEM,
|
NETDEV_A_PAGE_POOL_INFLIGHT_MEM,
|
||||||
NETDEV_A_PAGE_POOL_DETACH_TIME,
|
NETDEV_A_PAGE_POOL_DETACH_TIME,
|
||||||
|
NETDEV_A_PAGE_POOL_DMABUF,
|
||||||
|
NETDEV_A_PAGE_POOL_IO_URING,
|
||||||
|
|
||||||
__NETDEV_A_PAGE_POOL_MAX,
|
__NETDEV_A_PAGE_POOL_MAX,
|
||||||
NETDEV_A_PAGE_POOL_MAX = (__NETDEV_A_PAGE_POOL_MAX - 1)
|
NETDEV_A_PAGE_POOL_MAX = (__NETDEV_A_PAGE_POOL_MAX - 1)
|
||||||
@@ -121,16 +138,28 @@ enum {
|
|||||||
NETDEV_A_NAPI_ID,
|
NETDEV_A_NAPI_ID,
|
||||||
NETDEV_A_NAPI_IRQ,
|
NETDEV_A_NAPI_IRQ,
|
||||||
NETDEV_A_NAPI_PID,
|
NETDEV_A_NAPI_PID,
|
||||||
|
NETDEV_A_NAPI_DEFER_HARD_IRQS,
|
||||||
|
NETDEV_A_NAPI_GRO_FLUSH_TIMEOUT,
|
||||||
|
NETDEV_A_NAPI_IRQ_SUSPEND_TIMEOUT,
|
||||||
|
NETDEV_A_NAPI_THREADED,
|
||||||
|
|
||||||
__NETDEV_A_NAPI_MAX,
|
__NETDEV_A_NAPI_MAX,
|
||||||
NETDEV_A_NAPI_MAX = (__NETDEV_A_NAPI_MAX - 1)
|
NETDEV_A_NAPI_MAX = (__NETDEV_A_NAPI_MAX - 1)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
__NETDEV_A_XSK_INFO_MAX,
|
||||||
|
NETDEV_A_XSK_INFO_MAX = (__NETDEV_A_XSK_INFO_MAX - 1)
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
NETDEV_A_QUEUE_ID = 1,
|
NETDEV_A_QUEUE_ID = 1,
|
||||||
NETDEV_A_QUEUE_IFINDEX,
|
NETDEV_A_QUEUE_IFINDEX,
|
||||||
NETDEV_A_QUEUE_TYPE,
|
NETDEV_A_QUEUE_TYPE,
|
||||||
NETDEV_A_QUEUE_NAPI_ID,
|
NETDEV_A_QUEUE_NAPI_ID,
|
||||||
|
NETDEV_A_QUEUE_DMABUF,
|
||||||
|
NETDEV_A_QUEUE_IO_URING,
|
||||||
|
NETDEV_A_QUEUE_XSK,
|
||||||
|
|
||||||
__NETDEV_A_QUEUE_MAX,
|
__NETDEV_A_QUEUE_MAX,
|
||||||
NETDEV_A_QUEUE_MAX = (__NETDEV_A_QUEUE_MAX - 1)
|
NETDEV_A_QUEUE_MAX = (__NETDEV_A_QUEUE_MAX - 1)
|
||||||
@@ -173,6 +202,16 @@ enum {
|
|||||||
NETDEV_A_QSTATS_MAX = (__NETDEV_A_QSTATS_MAX - 1)
|
NETDEV_A_QSTATS_MAX = (__NETDEV_A_QSTATS_MAX - 1)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NETDEV_A_DMABUF_IFINDEX = 1,
|
||||||
|
NETDEV_A_DMABUF_QUEUES,
|
||||||
|
NETDEV_A_DMABUF_FD,
|
||||||
|
NETDEV_A_DMABUF_ID,
|
||||||
|
|
||||||
|
__NETDEV_A_DMABUF_MAX,
|
||||||
|
NETDEV_A_DMABUF_MAX = (__NETDEV_A_DMABUF_MAX - 1)
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
NETDEV_CMD_DEV_GET = 1,
|
NETDEV_CMD_DEV_GET = 1,
|
||||||
NETDEV_CMD_DEV_ADD_NTF,
|
NETDEV_CMD_DEV_ADD_NTF,
|
||||||
@@ -186,6 +225,9 @@ enum {
|
|||||||
NETDEV_CMD_QUEUE_GET,
|
NETDEV_CMD_QUEUE_GET,
|
||||||
NETDEV_CMD_NAPI_GET,
|
NETDEV_CMD_NAPI_GET,
|
||||||
NETDEV_CMD_QSTATS_GET,
|
NETDEV_CMD_QSTATS_GET,
|
||||||
|
NETDEV_CMD_BIND_RX,
|
||||||
|
NETDEV_CMD_NAPI_SET,
|
||||||
|
NETDEV_CMD_BIND_TX,
|
||||||
|
|
||||||
__NETDEV_CMD_MAX,
|
__NETDEV_CMD_MAX,
|
||||||
NETDEV_CMD_MAX = (__NETDEV_CMD_MAX - 1)
|
NETDEV_CMD_MAX = (__NETDEV_CMD_MAX - 1)
|
||||||
@@ -194,4 +236,4 @@ enum {
|
|||||||
#define NETDEV_MCGRP_MGMT "mgmt"
|
#define NETDEV_MCGRP_MGMT "mgmt"
|
||||||
#define NETDEV_MCGRP_PAGE_POOL "page-pool"
|
#define NETDEV_MCGRP_PAGE_POOL "page-pool"
|
||||||
|
|
||||||
#endif /* _UAPI_LINUX_NETDEV_H */
|
#endif /* _LINUX_NETDEV_H */
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||||
#ifndef _UAPI__LINUX_NETLINK_H
|
#ifndef __LINUX_NETLINK_H
|
||||||
#define _UAPI__LINUX_NETLINK_H
|
#define __LINUX_NETLINK_H
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/const.h>
|
||||||
#include <linux/socket.h> /* for __kernel_sa_family_t */
|
#include <linux/socket.h> /* for __kernel_sa_family_t */
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
#define NETLINK_CONNECTOR 11
|
#define NETLINK_CONNECTOR 11
|
||||||
#define NETLINK_NETFILTER 12 /* netfilter subsystem */
|
#define NETLINK_NETFILTER 12 /* netfilter subsystem */
|
||||||
#define NETLINK_IP6_FW 13
|
#define NETLINK_IP6_FW 13
|
||||||
#define NETLINK_DNRTMSG 14 /* DECnet routing messages */
|
#define NETLINK_DNRTMSG 14 /* DECnet routing messages (obsolete) */
|
||||||
#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */
|
#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */
|
||||||
#define NETLINK_GENERIC 16
|
#define NETLINK_GENERIC 16
|
||||||
/* leave room for NETLINK_DM (DM Events) */
|
/* leave room for NETLINK_DM (DM Events) */
|
||||||
@@ -41,12 +41,20 @@ struct sockaddr_nl {
|
|||||||
__u32 nl_groups; /* multicast groups mask */
|
__u32 nl_groups; /* multicast groups mask */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct nlmsghdr - fixed format metadata header of Netlink messages
|
||||||
|
* @nlmsg_len: Length of message including header
|
||||||
|
* @nlmsg_type: Message content type
|
||||||
|
* @nlmsg_flags: Additional flags
|
||||||
|
* @nlmsg_seq: Sequence number
|
||||||
|
* @nlmsg_pid: Sending process port ID
|
||||||
|
*/
|
||||||
struct nlmsghdr {
|
struct nlmsghdr {
|
||||||
__u32 nlmsg_len; /* Length of message including header */
|
__u32 nlmsg_len;
|
||||||
__u16 nlmsg_type; /* Message content */
|
__u16 nlmsg_type;
|
||||||
__u16 nlmsg_flags; /* Additional flags */
|
__u16 nlmsg_flags;
|
||||||
__u32 nlmsg_seq; /* Sequence number */
|
__u32 nlmsg_seq;
|
||||||
__u32 nlmsg_pid; /* Sending process port ID */
|
__u32 nlmsg_pid;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Flags values */
|
/* Flags values */
|
||||||
@@ -54,7 +62,7 @@ struct nlmsghdr {
|
|||||||
#define NLM_F_REQUEST 0x01 /* It is request message. */
|
#define NLM_F_REQUEST 0x01 /* It is request message. */
|
||||||
#define NLM_F_MULTI 0x02 /* Multipart message, terminated by NLMSG_DONE */
|
#define NLM_F_MULTI 0x02 /* Multipart message, terminated by NLMSG_DONE */
|
||||||
#define NLM_F_ACK 0x04 /* Reply with ack, with zero or error code */
|
#define NLM_F_ACK 0x04 /* Reply with ack, with zero or error code */
|
||||||
#define NLM_F_ECHO 0x08 /* Echo this request */
|
#define NLM_F_ECHO 0x08 /* Receive resulting notifications */
|
||||||
#define NLM_F_DUMP_INTR 0x10 /* Dump was inconsistent due to sequence change */
|
#define NLM_F_DUMP_INTR 0x10 /* Dump was inconsistent due to sequence change */
|
||||||
#define NLM_F_DUMP_FILTERED 0x20 /* Dump was filtered as requested */
|
#define NLM_F_DUMP_FILTERED 0x20 /* Dump was filtered as requested */
|
||||||
|
|
||||||
@@ -72,6 +80,7 @@ struct nlmsghdr {
|
|||||||
|
|
||||||
/* Modifiers to DELETE request */
|
/* Modifiers to DELETE request */
|
||||||
#define NLM_F_NONREC 0x100 /* Do not delete recursively */
|
#define NLM_F_NONREC 0x100 /* Do not delete recursively */
|
||||||
|
#define NLM_F_BULK 0x200 /* Delete multiple objects */
|
||||||
|
|
||||||
/* Flags for ACK message */
|
/* Flags for ACK message */
|
||||||
#define NLM_F_CAPPED 0x100 /* request was capped */
|
#define NLM_F_CAPPED 0x100 /* request was capped */
|
||||||
@@ -91,9 +100,10 @@ struct nlmsghdr {
|
|||||||
#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
|
#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
|
||||||
#define NLMSG_LENGTH(len) ((len) + NLMSG_HDRLEN)
|
#define NLMSG_LENGTH(len) ((len) + NLMSG_HDRLEN)
|
||||||
#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
|
#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
|
||||||
#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
|
#define NLMSG_DATA(nlh) ((void *)(((char *)nlh) + NLMSG_HDRLEN))
|
||||||
#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
|
#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
|
||||||
(struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
|
(struct nlmsghdr *)(((char *)(nlh)) + \
|
||||||
|
NLMSG_ALIGN((nlh)->nlmsg_len)))
|
||||||
#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \
|
#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \
|
||||||
(nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
|
(nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
|
||||||
(nlh)->nlmsg_len <= (len))
|
(nlh)->nlmsg_len <= (len))
|
||||||
@@ -129,6 +139,11 @@ struct nlmsgerr {
|
|||||||
* @NLMSGERR_ATTR_COOKIE: arbitrary subsystem specific cookie to
|
* @NLMSGERR_ATTR_COOKIE: arbitrary subsystem specific cookie to
|
||||||
* be used - in the success case - to identify a created
|
* be used - in the success case - to identify a created
|
||||||
* object or operation or similar (binary)
|
* object or operation or similar (binary)
|
||||||
|
* @NLMSGERR_ATTR_POLICY: policy for a rejected attribute
|
||||||
|
* @NLMSGERR_ATTR_MISS_TYPE: type of a missing required attribute,
|
||||||
|
* %NLMSGERR_ATTR_MISS_NEST will not be present if the attribute was
|
||||||
|
* missing at the message level
|
||||||
|
* @NLMSGERR_ATTR_MISS_NEST: offset of the nest where attribute was missing
|
||||||
* @__NLMSGERR_ATTR_MAX: number of attributes
|
* @__NLMSGERR_ATTR_MAX: number of attributes
|
||||||
* @NLMSGERR_ATTR_MAX: highest attribute number
|
* @NLMSGERR_ATTR_MAX: highest attribute number
|
||||||
*/
|
*/
|
||||||
@@ -137,6 +152,9 @@ enum nlmsgerr_attrs {
|
|||||||
NLMSGERR_ATTR_MSG,
|
NLMSGERR_ATTR_MSG,
|
||||||
NLMSGERR_ATTR_OFFS,
|
NLMSGERR_ATTR_OFFS,
|
||||||
NLMSGERR_ATTR_COOKIE,
|
NLMSGERR_ATTR_COOKIE,
|
||||||
|
NLMSGERR_ATTR_POLICY,
|
||||||
|
NLMSGERR_ATTR_MISS_TYPE,
|
||||||
|
NLMSGERR_ATTR_MISS_NEST,
|
||||||
|
|
||||||
__NLMSGERR_ATTR_MAX,
|
__NLMSGERR_ATTR_MAX,
|
||||||
NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1
|
NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1
|
||||||
@@ -249,4 +267,117 @@ struct nla_bitfield32 {
|
|||||||
__u32 selector;
|
__u32 selector;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _UAPI__LINUX_NETLINK_H */
|
/*
|
||||||
|
* policy descriptions - it's specific to each family how this is used
|
||||||
|
* Normally, it should be retrieved via a dump inside another attribute
|
||||||
|
* specifying where it applies.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum netlink_attribute_type - type of an attribute
|
||||||
|
* @NL_ATTR_TYPE_INVALID: unused
|
||||||
|
* @NL_ATTR_TYPE_FLAG: flag attribute (present/not present)
|
||||||
|
* @NL_ATTR_TYPE_U8: 8-bit unsigned attribute
|
||||||
|
* @NL_ATTR_TYPE_U16: 16-bit unsigned attribute
|
||||||
|
* @NL_ATTR_TYPE_U32: 32-bit unsigned attribute
|
||||||
|
* @NL_ATTR_TYPE_U64: 64-bit unsigned attribute
|
||||||
|
* @NL_ATTR_TYPE_S8: 8-bit signed attribute
|
||||||
|
* @NL_ATTR_TYPE_S16: 16-bit signed attribute
|
||||||
|
* @NL_ATTR_TYPE_S32: 32-bit signed attribute
|
||||||
|
* @NL_ATTR_TYPE_S64: 64-bit signed attribute
|
||||||
|
* @NL_ATTR_TYPE_BINARY: binary data, min/max length may be specified
|
||||||
|
* @NL_ATTR_TYPE_STRING: string, min/max length may be specified
|
||||||
|
* @NL_ATTR_TYPE_NUL_STRING: NUL-terminated string,
|
||||||
|
* min/max length may be specified
|
||||||
|
* @NL_ATTR_TYPE_NESTED: nested, i.e. the content of this attribute
|
||||||
|
* consists of sub-attributes. The nested policy and maxtype
|
||||||
|
* inside may be specified.
|
||||||
|
* @NL_ATTR_TYPE_NESTED_ARRAY: nested array, i.e. the content of this
|
||||||
|
* attribute contains sub-attributes whose type is irrelevant
|
||||||
|
* (just used to separate the array entries) and each such array
|
||||||
|
* entry has attributes again, the policy for those inner ones
|
||||||
|
* and the corresponding maxtype may be specified.
|
||||||
|
* @NL_ATTR_TYPE_BITFIELD32: &struct nla_bitfield32 attribute
|
||||||
|
* @NL_ATTR_TYPE_SINT: 32-bit or 64-bit signed attribute, aligned to 4B
|
||||||
|
* @NL_ATTR_TYPE_UINT: 32-bit or 64-bit unsigned attribute, aligned to 4B
|
||||||
|
*/
|
||||||
|
enum netlink_attribute_type {
|
||||||
|
NL_ATTR_TYPE_INVALID,
|
||||||
|
|
||||||
|
NL_ATTR_TYPE_FLAG,
|
||||||
|
|
||||||
|
NL_ATTR_TYPE_U8,
|
||||||
|
NL_ATTR_TYPE_U16,
|
||||||
|
NL_ATTR_TYPE_U32,
|
||||||
|
NL_ATTR_TYPE_U64,
|
||||||
|
|
||||||
|
NL_ATTR_TYPE_S8,
|
||||||
|
NL_ATTR_TYPE_S16,
|
||||||
|
NL_ATTR_TYPE_S32,
|
||||||
|
NL_ATTR_TYPE_S64,
|
||||||
|
|
||||||
|
NL_ATTR_TYPE_BINARY,
|
||||||
|
NL_ATTR_TYPE_STRING,
|
||||||
|
NL_ATTR_TYPE_NUL_STRING,
|
||||||
|
|
||||||
|
NL_ATTR_TYPE_NESTED,
|
||||||
|
NL_ATTR_TYPE_NESTED_ARRAY,
|
||||||
|
|
||||||
|
NL_ATTR_TYPE_BITFIELD32,
|
||||||
|
|
||||||
|
NL_ATTR_TYPE_SINT,
|
||||||
|
NL_ATTR_TYPE_UINT,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum netlink_policy_type_attr - policy type attributes
|
||||||
|
* @NL_POLICY_TYPE_ATTR_UNSPEC: unused
|
||||||
|
* @NL_POLICY_TYPE_ATTR_TYPE: type of the attribute,
|
||||||
|
* &enum netlink_attribute_type (U32)
|
||||||
|
* @NL_POLICY_TYPE_ATTR_MIN_VALUE_S: minimum value for signed
|
||||||
|
* integers (S64)
|
||||||
|
* @NL_POLICY_TYPE_ATTR_MAX_VALUE_S: maximum value for signed
|
||||||
|
* integers (S64)
|
||||||
|
* @NL_POLICY_TYPE_ATTR_MIN_VALUE_U: minimum value for unsigned
|
||||||
|
* integers (U64)
|
||||||
|
* @NL_POLICY_TYPE_ATTR_MAX_VALUE_U: maximum value for unsigned
|
||||||
|
* integers (U64)
|
||||||
|
* @NL_POLICY_TYPE_ATTR_MIN_LENGTH: minimum length for binary
|
||||||
|
* attributes, no minimum if not given (U32)
|
||||||
|
* @NL_POLICY_TYPE_ATTR_MAX_LENGTH: maximum length for binary
|
||||||
|
* attributes, no maximum if not given (U32)
|
||||||
|
* @NL_POLICY_TYPE_ATTR_POLICY_IDX: sub policy for nested and
|
||||||
|
* nested array types (U32)
|
||||||
|
* @NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE: maximum sub policy
|
||||||
|
* attribute for nested and nested array types, this can
|
||||||
|
* in theory be < the size of the policy pointed to by
|
||||||
|
* the index, if limited inside the nesting (U32)
|
||||||
|
* @NL_POLICY_TYPE_ATTR_BITFIELD32_MASK: valid mask for the
|
||||||
|
* bitfield32 type (U32)
|
||||||
|
* @NL_POLICY_TYPE_ATTR_MASK: mask of valid bits for unsigned integers (U64)
|
||||||
|
* @NL_POLICY_TYPE_ATTR_PAD: pad attribute for 64-bit alignment
|
||||||
|
*
|
||||||
|
* @__NL_POLICY_TYPE_ATTR_MAX: number of attributes
|
||||||
|
* @NL_POLICY_TYPE_ATTR_MAX: highest attribute number
|
||||||
|
*/
|
||||||
|
enum netlink_policy_type_attr {
|
||||||
|
NL_POLICY_TYPE_ATTR_UNSPEC,
|
||||||
|
NL_POLICY_TYPE_ATTR_TYPE,
|
||||||
|
NL_POLICY_TYPE_ATTR_MIN_VALUE_S,
|
||||||
|
NL_POLICY_TYPE_ATTR_MAX_VALUE_S,
|
||||||
|
NL_POLICY_TYPE_ATTR_MIN_VALUE_U,
|
||||||
|
NL_POLICY_TYPE_ATTR_MAX_VALUE_U,
|
||||||
|
NL_POLICY_TYPE_ATTR_MIN_LENGTH,
|
||||||
|
NL_POLICY_TYPE_ATTR_MAX_LENGTH,
|
||||||
|
NL_POLICY_TYPE_ATTR_POLICY_IDX,
|
||||||
|
NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE,
|
||||||
|
NL_POLICY_TYPE_ATTR_BITFIELD32_MASK,
|
||||||
|
NL_POLICY_TYPE_ATTR_PAD,
|
||||||
|
NL_POLICY_TYPE_ATTR_MASK,
|
||||||
|
|
||||||
|
/* keep last */
|
||||||
|
__NL_POLICY_TYPE_ATTR_MAX,
|
||||||
|
NL_POLICY_TYPE_ATTR_MAX = __NL_POLICY_TYPE_ATTR_MAX - 1
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __LINUX_NETLINK_H */
|
||||||
|
|||||||
43
include/uapi/linux/openat2.h
Normal file
43
include/uapi/linux/openat2.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||||
|
#ifndef _LINUX_OPENAT2_H
|
||||||
|
#define _LINUX_OPENAT2_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Arguments for how openat2(2) should open the target path. If only @flags and
|
||||||
|
* @mode are non-zero, then openat2(2) operates very similarly to openat(2).
|
||||||
|
*
|
||||||
|
* However, unlike openat(2), unknown or invalid bits in @flags result in
|
||||||
|
* -EINVAL rather than being silently ignored. @mode must be zero unless one of
|
||||||
|
* {O_CREAT, O_TMPFILE} are set.
|
||||||
|
*
|
||||||
|
* @flags: O_* flags.
|
||||||
|
* @mode: O_CREAT/O_TMPFILE file mode.
|
||||||
|
* @resolve: RESOLVE_* flags.
|
||||||
|
*/
|
||||||
|
struct open_how {
|
||||||
|
__u64 flags;
|
||||||
|
__u64 mode;
|
||||||
|
__u64 resolve;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* how->resolve flags for openat2(2). */
|
||||||
|
#define RESOLVE_NO_XDEV 0x01 /* Block mount-point crossings
|
||||||
|
(includes bind-mounts). */
|
||||||
|
#define RESOLVE_NO_MAGICLINKS 0x02 /* Block traversal through procfs-style
|
||||||
|
"magic-links". */
|
||||||
|
#define RESOLVE_NO_SYMLINKS 0x04 /* Block traversal through all symlinks
|
||||||
|
(implies OEXT_NO_MAGICLINKS) */
|
||||||
|
#define RESOLVE_BENEATH 0x08 /* Block "lexical" trickery like
|
||||||
|
"..", symlinks, and absolute
|
||||||
|
paths which escape the dirfd. */
|
||||||
|
#define RESOLVE_IN_ROOT 0x10 /* Make all jumps to "/" and ".."
|
||||||
|
be scoped inside the dirfd
|
||||||
|
(similar to chroot(2)). */
|
||||||
|
#define RESOLVE_CACHED 0x20 /* Only complete if resolution can be
|
||||||
|
completed through cached lookup. May
|
||||||
|
return -EAGAIN if that's not
|
||||||
|
possible. */
|
||||||
|
|
||||||
|
#endif /* _LINUX_OPENAT2_H */
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -16,9 +16,40 @@ enum {
|
|||||||
TCA_ACT_STATS,
|
TCA_ACT_STATS,
|
||||||
TCA_ACT_PAD,
|
TCA_ACT_PAD,
|
||||||
TCA_ACT_COOKIE,
|
TCA_ACT_COOKIE,
|
||||||
|
TCA_ACT_FLAGS,
|
||||||
|
TCA_ACT_HW_STATS,
|
||||||
|
TCA_ACT_USED_HW_STATS,
|
||||||
|
TCA_ACT_IN_HW_COUNT,
|
||||||
__TCA_ACT_MAX
|
__TCA_ACT_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* See other TCA_ACT_FLAGS_ * flags in include/net/act_api.h. */
|
||||||
|
#define TCA_ACT_FLAGS_NO_PERCPU_STATS (1 << 0) /* Don't use percpu allocator for
|
||||||
|
* actions stats.
|
||||||
|
*/
|
||||||
|
#define TCA_ACT_FLAGS_SKIP_HW (1 << 1) /* don't offload action to HW */
|
||||||
|
#define TCA_ACT_FLAGS_SKIP_SW (1 << 2) /* don't use action in SW */
|
||||||
|
|
||||||
|
/* tca HW stats type
|
||||||
|
* When user does not pass the attribute, he does not care.
|
||||||
|
* It is the same as if he would pass the attribute with
|
||||||
|
* all supported bits set.
|
||||||
|
* In case no bits are set, user is not interested in getting any HW statistics.
|
||||||
|
*/
|
||||||
|
#define TCA_ACT_HW_STATS_IMMEDIATE (1 << 0) /* Means that in dump, user
|
||||||
|
* gets the current HW stats
|
||||||
|
* state from the device
|
||||||
|
* queried at the dump time.
|
||||||
|
*/
|
||||||
|
#define TCA_ACT_HW_STATS_DELAYED (1 << 1) /* Means that in dump, user gets
|
||||||
|
* HW stats that might be out of date
|
||||||
|
* for some time, maybe couple of
|
||||||
|
* seconds. This is the case when
|
||||||
|
* driver polls stats updates
|
||||||
|
* periodically or when it gets async
|
||||||
|
* stats update from the device.
|
||||||
|
*/
|
||||||
|
|
||||||
#define TCA_ACT_MAX __TCA_ACT_MAX
|
#define TCA_ACT_MAX __TCA_ACT_MAX
|
||||||
#define TCA_OLD_COMPAT (TCA_ACT_MAX+1)
|
#define TCA_OLD_COMPAT (TCA_ACT_MAX+1)
|
||||||
#define TCA_ACT_MAX_PRIO 32
|
#define TCA_ACT_MAX_PRIO 32
|
||||||
@@ -63,12 +94,53 @@ enum {
|
|||||||
#define TC_ACT_GOTO_CHAIN __TC_ACT_EXT(2)
|
#define TC_ACT_GOTO_CHAIN __TC_ACT_EXT(2)
|
||||||
#define TC_ACT_EXT_OPCODE_MAX TC_ACT_GOTO_CHAIN
|
#define TC_ACT_EXT_OPCODE_MAX TC_ACT_GOTO_CHAIN
|
||||||
|
|
||||||
|
/* These macros are put here for binary compatibility with userspace apps that
|
||||||
|
* make use of them. For kernel code and new userspace apps, use the TCA_ID_*
|
||||||
|
* versions.
|
||||||
|
*/
|
||||||
|
#define TCA_ACT_GACT 5
|
||||||
|
#define TCA_ACT_IPT 6 /* obsoleted, can be reused */
|
||||||
|
#define TCA_ACT_PEDIT 7
|
||||||
|
#define TCA_ACT_MIRRED 8
|
||||||
|
#define TCA_ACT_NAT 9
|
||||||
|
#define TCA_ACT_XT 10
|
||||||
|
#define TCA_ACT_SKBEDIT 11
|
||||||
|
#define TCA_ACT_VLAN 12
|
||||||
|
#define TCA_ACT_BPF 13
|
||||||
|
#define TCA_ACT_CONNMARK 14
|
||||||
|
#define TCA_ACT_SKBMOD 15
|
||||||
|
#define TCA_ACT_CSUM 16
|
||||||
|
#define TCA_ACT_TUNNEL_KEY 17
|
||||||
|
#define TCA_ACT_SIMP 22
|
||||||
|
#define TCA_ACT_IFE 25
|
||||||
|
#define TCA_ACT_SAMPLE 26
|
||||||
|
|
||||||
/* Action type identifiers*/
|
/* Action type identifiers*/
|
||||||
enum {
|
enum tca_id {
|
||||||
TCA_ID_UNSPEC=0,
|
TCA_ID_UNSPEC = 0,
|
||||||
TCA_ID_POLICE=1,
|
TCA_ID_POLICE = 1,
|
||||||
|
TCA_ID_GACT = TCA_ACT_GACT,
|
||||||
|
TCA_ID_IPT = TCA_ACT_IPT, /* Obsoleted, can be reused */
|
||||||
|
TCA_ID_PEDIT = TCA_ACT_PEDIT,
|
||||||
|
TCA_ID_MIRRED = TCA_ACT_MIRRED,
|
||||||
|
TCA_ID_NAT = TCA_ACT_NAT,
|
||||||
|
TCA_ID_XT = TCA_ACT_XT,
|
||||||
|
TCA_ID_SKBEDIT = TCA_ACT_SKBEDIT,
|
||||||
|
TCA_ID_VLAN = TCA_ACT_VLAN,
|
||||||
|
TCA_ID_BPF = TCA_ACT_BPF,
|
||||||
|
TCA_ID_CONNMARK = TCA_ACT_CONNMARK,
|
||||||
|
TCA_ID_SKBMOD = TCA_ACT_SKBMOD,
|
||||||
|
TCA_ID_CSUM = TCA_ACT_CSUM,
|
||||||
|
TCA_ID_TUNNEL_KEY = TCA_ACT_TUNNEL_KEY,
|
||||||
|
TCA_ID_SIMP = TCA_ACT_SIMP,
|
||||||
|
TCA_ID_IFE = TCA_ACT_IFE,
|
||||||
|
TCA_ID_SAMPLE = TCA_ACT_SAMPLE,
|
||||||
|
TCA_ID_CTINFO,
|
||||||
|
TCA_ID_MPLS,
|
||||||
|
TCA_ID_CT,
|
||||||
|
TCA_ID_GATE,
|
||||||
/* other actions go here */
|
/* other actions go here */
|
||||||
__TCA_ID_MAX=255
|
__TCA_ID_MAX = 255
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TCA_ID_MAX __TCA_ID_MAX
|
#define TCA_ID_MAX __TCA_ID_MAX
|
||||||
@@ -120,6 +192,10 @@ enum {
|
|||||||
TCA_POLICE_RESULT,
|
TCA_POLICE_RESULT,
|
||||||
TCA_POLICE_TM,
|
TCA_POLICE_TM,
|
||||||
TCA_POLICE_PAD,
|
TCA_POLICE_PAD,
|
||||||
|
TCA_POLICE_RATE64,
|
||||||
|
TCA_POLICE_PEAKRATE64,
|
||||||
|
TCA_POLICE_PKTRATE64,
|
||||||
|
TCA_POLICE_PKTBURST64,
|
||||||
__TCA_POLICE_MAX
|
__TCA_POLICE_MAX
|
||||||
#define TCA_POLICE_RESULT TCA_POLICE_RESULT
|
#define TCA_POLICE_RESULT TCA_POLICE_RESULT
|
||||||
};
|
};
|
||||||
@@ -170,16 +246,19 @@ struct tc_u32_key {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct tc_u32_sel {
|
struct tc_u32_sel {
|
||||||
unsigned char flags;
|
/* New members MUST be added within the __struct_group() macro below. */
|
||||||
unsigned char offshift;
|
__struct_group(tc_u32_sel_hdr, hdr, /* no attrs */,
|
||||||
unsigned char nkeys;
|
unsigned char flags;
|
||||||
|
unsigned char offshift;
|
||||||
|
unsigned char nkeys;
|
||||||
|
|
||||||
__be16 offmask;
|
__be16 offmask;
|
||||||
__u16 off;
|
__u16 off;
|
||||||
short offoff;
|
short offoff;
|
||||||
|
|
||||||
short hoff;
|
short hoff;
|
||||||
__be32 hmask;
|
__be32 hmask;
|
||||||
|
);
|
||||||
struct tc_u32_key keys[];
|
struct tc_u32_key keys[];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -286,12 +365,19 @@ enum {
|
|||||||
|
|
||||||
/* Basic filter */
|
/* Basic filter */
|
||||||
|
|
||||||
|
struct tc_basic_pcnt {
|
||||||
|
__u64 rcnt;
|
||||||
|
__u64 rhit;
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TCA_BASIC_UNSPEC,
|
TCA_BASIC_UNSPEC,
|
||||||
TCA_BASIC_CLASSID,
|
TCA_BASIC_CLASSID,
|
||||||
TCA_BASIC_EMATCHES,
|
TCA_BASIC_EMATCHES,
|
||||||
TCA_BASIC_ACT,
|
TCA_BASIC_ACT,
|
||||||
TCA_BASIC_POLICE,
|
TCA_BASIC_POLICE,
|
||||||
|
TCA_BASIC_PCNT,
|
||||||
|
TCA_BASIC_PAD,
|
||||||
__TCA_BASIC_MAX
|
__TCA_BASIC_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -438,17 +524,79 @@ enum {
|
|||||||
|
|
||||||
TCA_FLOWER_IN_HW_COUNT,
|
TCA_FLOWER_IN_HW_COUNT,
|
||||||
|
|
||||||
|
TCA_FLOWER_KEY_PORT_SRC_MIN, /* be16 */
|
||||||
|
TCA_FLOWER_KEY_PORT_SRC_MAX, /* be16 */
|
||||||
|
TCA_FLOWER_KEY_PORT_DST_MIN, /* be16 */
|
||||||
|
TCA_FLOWER_KEY_PORT_DST_MAX, /* be16 */
|
||||||
|
|
||||||
|
TCA_FLOWER_KEY_CT_STATE, /* u16 */
|
||||||
|
TCA_FLOWER_KEY_CT_STATE_MASK, /* u16 */
|
||||||
|
TCA_FLOWER_KEY_CT_ZONE, /* u16 */
|
||||||
|
TCA_FLOWER_KEY_CT_ZONE_MASK, /* u16 */
|
||||||
|
TCA_FLOWER_KEY_CT_MARK, /* u32 */
|
||||||
|
TCA_FLOWER_KEY_CT_MARK_MASK, /* u32 */
|
||||||
|
TCA_FLOWER_KEY_CT_LABELS, /* u128 */
|
||||||
|
TCA_FLOWER_KEY_CT_LABELS_MASK, /* u128 */
|
||||||
|
|
||||||
|
TCA_FLOWER_KEY_MPLS_OPTS,
|
||||||
|
|
||||||
|
TCA_FLOWER_KEY_HASH, /* u32 */
|
||||||
|
TCA_FLOWER_KEY_HASH_MASK, /* u32 */
|
||||||
|
|
||||||
|
TCA_FLOWER_KEY_NUM_OF_VLANS, /* u8 */
|
||||||
|
|
||||||
|
TCA_FLOWER_KEY_PPPOE_SID, /* be16 */
|
||||||
|
TCA_FLOWER_KEY_PPP_PROTO, /* be16 */
|
||||||
|
|
||||||
|
TCA_FLOWER_KEY_L2TPV3_SID, /* be32 */
|
||||||
|
|
||||||
|
TCA_FLOWER_L2_MISS, /* u8 */
|
||||||
|
|
||||||
|
TCA_FLOWER_KEY_CFM, /* nested */
|
||||||
|
|
||||||
|
TCA_FLOWER_KEY_SPI, /* be32 */
|
||||||
|
TCA_FLOWER_KEY_SPI_MASK, /* be32 */
|
||||||
|
|
||||||
|
TCA_FLOWER_KEY_ENC_FLAGS, /* be32 */
|
||||||
|
TCA_FLOWER_KEY_ENC_FLAGS_MASK, /* be32 */
|
||||||
|
|
||||||
__TCA_FLOWER_MAX,
|
__TCA_FLOWER_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1)
|
#define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TCA_FLOWER_KEY_CT_FLAGS_NEW = 1 << 0, /* Beginning of a new connection. */
|
||||||
|
TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED = 1 << 1, /* Part of an existing connection. */
|
||||||
|
TCA_FLOWER_KEY_CT_FLAGS_RELATED = 1 << 2, /* Related to an established connection. */
|
||||||
|
TCA_FLOWER_KEY_CT_FLAGS_TRACKED = 1 << 3, /* Conntrack has occurred. */
|
||||||
|
TCA_FLOWER_KEY_CT_FLAGS_INVALID = 1 << 4, /* Conntrack is invalid. */
|
||||||
|
TCA_FLOWER_KEY_CT_FLAGS_REPLY = 1 << 5, /* Packet is in the reply direction. */
|
||||||
|
__TCA_FLOWER_KEY_CT_FLAGS_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TCA_FLOWER_KEY_ENC_OPTS_UNSPEC,
|
TCA_FLOWER_KEY_ENC_OPTS_UNSPEC,
|
||||||
TCA_FLOWER_KEY_ENC_OPTS_GENEVE, /* Nested
|
TCA_FLOWER_KEY_ENC_OPTS_GENEVE, /* Nested
|
||||||
* TCA_FLOWER_KEY_ENC_OPT_GENEVE_
|
* TCA_FLOWER_KEY_ENC_OPT_GENEVE_
|
||||||
* attributes
|
* attributes
|
||||||
*/
|
*/
|
||||||
|
TCA_FLOWER_KEY_ENC_OPTS_VXLAN, /* Nested
|
||||||
|
* TCA_FLOWER_KEY_ENC_OPT_VXLAN_
|
||||||
|
* attributes
|
||||||
|
*/
|
||||||
|
TCA_FLOWER_KEY_ENC_OPTS_ERSPAN, /* Nested
|
||||||
|
* TCA_FLOWER_KEY_ENC_OPT_ERSPAN_
|
||||||
|
* attributes
|
||||||
|
*/
|
||||||
|
TCA_FLOWER_KEY_ENC_OPTS_GTP, /* Nested
|
||||||
|
* TCA_FLOWER_KEY_ENC_OPT_GTP_
|
||||||
|
* attributes
|
||||||
|
*/
|
||||||
|
TCA_FLOWER_KEY_ENC_OPTS_PFCP, /* Nested
|
||||||
|
* TCA_FLOWER_KEY_ENC_IPT_PFCP
|
||||||
|
* attributes
|
||||||
|
*/
|
||||||
__TCA_FLOWER_KEY_ENC_OPTS_MAX,
|
__TCA_FLOWER_KEY_ENC_OPTS_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -467,17 +615,105 @@ enum {
|
|||||||
(__TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX - 1)
|
(__TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX - 1)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT = (1 << 0),
|
TCA_FLOWER_KEY_ENC_OPT_VXLAN_UNSPEC,
|
||||||
TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST = (1 << 1),
|
TCA_FLOWER_KEY_ENC_OPT_VXLAN_GBP, /* u32 */
|
||||||
|
__TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX \
|
||||||
|
(__TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX - 1)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TCA_FLOWER_KEY_ENC_OPT_ERSPAN_UNSPEC,
|
||||||
|
TCA_FLOWER_KEY_ENC_OPT_ERSPAN_VER, /* u8 */
|
||||||
|
TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX, /* be32 */
|
||||||
|
TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR, /* u8 */
|
||||||
|
TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID, /* u8 */
|
||||||
|
__TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX \
|
||||||
|
(__TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX - 1)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TCA_FLOWER_KEY_ENC_OPT_GTP_UNSPEC,
|
||||||
|
TCA_FLOWER_KEY_ENC_OPT_GTP_PDU_TYPE, /* u8 */
|
||||||
|
TCA_FLOWER_KEY_ENC_OPT_GTP_QFI, /* u8 */
|
||||||
|
|
||||||
|
__TCA_FLOWER_KEY_ENC_OPT_GTP_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TCA_FLOWER_KEY_ENC_OPT_GTP_MAX \
|
||||||
|
(__TCA_FLOWER_KEY_ENC_OPT_GTP_MAX - 1)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TCA_FLOWER_KEY_ENC_OPT_PFCP_UNSPEC,
|
||||||
|
TCA_FLOWER_KEY_ENC_OPT_PFCP_TYPE, /* u8 */
|
||||||
|
TCA_FLOWER_KEY_ENC_OPT_PFCP_SEID, /* be64 */
|
||||||
|
__TCA_FLOWER_KEY_ENC_OPT_PFCP_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TCA_FLOWER_KEY_ENC_OPT_PFCP_MAX \
|
||||||
|
(__TCA_FLOWER_KEY_ENC_OPT_PFCP_MAX - 1)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TCA_FLOWER_KEY_MPLS_OPTS_UNSPEC,
|
||||||
|
TCA_FLOWER_KEY_MPLS_OPTS_LSE,
|
||||||
|
__TCA_FLOWER_KEY_MPLS_OPTS_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TCA_FLOWER_KEY_MPLS_OPTS_MAX (__TCA_FLOWER_KEY_MPLS_OPTS_MAX - 1)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TCA_FLOWER_KEY_MPLS_OPT_LSE_UNSPEC,
|
||||||
|
TCA_FLOWER_KEY_MPLS_OPT_LSE_DEPTH,
|
||||||
|
TCA_FLOWER_KEY_MPLS_OPT_LSE_TTL,
|
||||||
|
TCA_FLOWER_KEY_MPLS_OPT_LSE_BOS,
|
||||||
|
TCA_FLOWER_KEY_MPLS_OPT_LSE_TC,
|
||||||
|
TCA_FLOWER_KEY_MPLS_OPT_LSE_LABEL,
|
||||||
|
__TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX \
|
||||||
|
(__TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX - 1)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT = (1 << 0),
|
||||||
|
TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST = (1 << 1),
|
||||||
|
TCA_FLOWER_KEY_FLAGS_TUNNEL_CSUM = (1 << 2),
|
||||||
|
TCA_FLOWER_KEY_FLAGS_TUNNEL_DONT_FRAGMENT = (1 << 3),
|
||||||
|
TCA_FLOWER_KEY_FLAGS_TUNNEL_OAM = (1 << 4),
|
||||||
|
TCA_FLOWER_KEY_FLAGS_TUNNEL_CRIT_OPT = (1 << 5),
|
||||||
|
__TCA_FLOWER_KEY_FLAGS_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TCA_FLOWER_KEY_FLAGS_MAX (__TCA_FLOWER_KEY_FLAGS_MAX - 1)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TCA_FLOWER_KEY_CFM_OPT_UNSPEC,
|
||||||
|
TCA_FLOWER_KEY_CFM_MD_LEVEL,
|
||||||
|
TCA_FLOWER_KEY_CFM_OPCODE,
|
||||||
|
__TCA_FLOWER_KEY_CFM_OPT_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TCA_FLOWER_KEY_CFM_OPT_MAX (__TCA_FLOWER_KEY_CFM_OPT_MAX - 1)
|
||||||
|
#define TCA_FLOWER_KEY_CFM_MAX (__TCA_FLOWER_KEY_CFM_OPT_MAX - 1)
|
||||||
|
|
||||||
|
#define TCA_FLOWER_MASK_FLAGS_RANGE (1 << 0) /* Range-based match */
|
||||||
|
|
||||||
/* Match-all classifier */
|
/* Match-all classifier */
|
||||||
|
|
||||||
|
struct tc_matchall_pcnt {
|
||||||
|
__u64 rhit;
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TCA_MATCHALL_UNSPEC,
|
TCA_MATCHALL_UNSPEC,
|
||||||
TCA_MATCHALL_CLASSID,
|
TCA_MATCHALL_CLASSID,
|
||||||
TCA_MATCHALL_ACT,
|
TCA_MATCHALL_ACT,
|
||||||
TCA_MATCHALL_FLAGS,
|
TCA_MATCHALL_FLAGS,
|
||||||
|
TCA_MATCHALL_PCNT,
|
||||||
|
TCA_MATCHALL_PAD,
|
||||||
__TCA_MATCHALL_MAX,
|
__TCA_MATCHALL_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#ifndef __LINUX_PKT_SCHED_H
|
#ifndef __LINUX_PKT_SCHED_H
|
||||||
#define __LINUX_PKT_SCHED_H
|
#define __LINUX_PKT_SCHED_H
|
||||||
|
|
||||||
|
#include <linux/const.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
/* Logical priority bands not depending on specific packet scheduler.
|
/* Logical priority bands not depending on specific packet scheduler.
|
||||||
@@ -255,6 +256,9 @@ enum {
|
|||||||
TCA_RED_PARMS,
|
TCA_RED_PARMS,
|
||||||
TCA_RED_STAB,
|
TCA_RED_STAB,
|
||||||
TCA_RED_MAX_P,
|
TCA_RED_MAX_P,
|
||||||
|
TCA_RED_FLAGS, /* bitfield32 */
|
||||||
|
TCA_RED_EARLY_DROP_BLOCK, /* u32 */
|
||||||
|
TCA_RED_MARK_BLOCK, /* u32 */
|
||||||
__TCA_RED_MAX,
|
__TCA_RED_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -267,12 +271,28 @@ struct tc_red_qopt {
|
|||||||
unsigned char Wlog; /* log(W) */
|
unsigned char Wlog; /* log(W) */
|
||||||
unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */
|
unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */
|
||||||
unsigned char Scell_log; /* cell size for idle damping */
|
unsigned char Scell_log; /* cell size for idle damping */
|
||||||
|
|
||||||
|
/* This field can be used for flags that a RED-like qdisc has
|
||||||
|
* historically supported. E.g. when configuring RED, it can be used for
|
||||||
|
* ECN, HARDDROP and ADAPTATIVE. For SFQ it can be used for ECN,
|
||||||
|
* HARDDROP. Etc. Because this field has not been validated, and is
|
||||||
|
* copied back on dump, any bits besides those to which a given qdisc
|
||||||
|
* has assigned a historical meaning need to be considered for free use
|
||||||
|
* by userspace tools.
|
||||||
|
*
|
||||||
|
* Any further flags need to be passed differently, e.g. through an
|
||||||
|
* attribute (such as TCA_RED_FLAGS above). Such attribute should allow
|
||||||
|
* passing both recent and historic flags in one value.
|
||||||
|
*/
|
||||||
unsigned char flags;
|
unsigned char flags;
|
||||||
#define TC_RED_ECN 1
|
#define TC_RED_ECN 1
|
||||||
#define TC_RED_HARDDROP 2
|
#define TC_RED_HARDDROP 2
|
||||||
#define TC_RED_ADAPTATIVE 4
|
#define TC_RED_ADAPTATIVE 4
|
||||||
|
#define TC_RED_NODROP 8
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define TC_RED_HISTORIC_FLAGS (TC_RED_ECN | TC_RED_HARDDROP | TC_RED_ADAPTATIVE)
|
||||||
|
|
||||||
struct tc_red_xstats {
|
struct tc_red_xstats {
|
||||||
__u32 early; /* Early drops */
|
__u32 early; /* Early drops */
|
||||||
__u32 pdrop; /* Drops due to queue limits */
|
__u32 pdrop; /* Drops due to queue limits */
|
||||||
@@ -474,6 +494,7 @@ enum {
|
|||||||
TCA_NETEM_JITTER64,
|
TCA_NETEM_JITTER64,
|
||||||
TCA_NETEM_SLOT,
|
TCA_NETEM_SLOT,
|
||||||
TCA_NETEM_SLOT_DIST,
|
TCA_NETEM_SLOT_DIST,
|
||||||
|
TCA_NETEM_PRNG_SEED,
|
||||||
__TCA_NETEM_MAX,
|
__TCA_NETEM_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -590,6 +611,11 @@ enum {
|
|||||||
|
|
||||||
#define __TC_MQPRIO_SHAPER_MAX (__TC_MQPRIO_SHAPER_MAX - 1)
|
#define __TC_MQPRIO_SHAPER_MAX (__TC_MQPRIO_SHAPER_MAX - 1)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TC_FP_EXPRESS = 1,
|
||||||
|
TC_FP_PREEMPTIBLE = 2,
|
||||||
|
};
|
||||||
|
|
||||||
struct tc_mqprio_qopt {
|
struct tc_mqprio_qopt {
|
||||||
__u8 num_tc;
|
__u8 num_tc;
|
||||||
__u8 prio_tc_map[TC_QOPT_BITMASK + 1];
|
__u8 prio_tc_map[TC_QOPT_BITMASK + 1];
|
||||||
@@ -603,12 +629,23 @@ struct tc_mqprio_qopt {
|
|||||||
#define TC_MQPRIO_F_MIN_RATE 0x4
|
#define TC_MQPRIO_F_MIN_RATE 0x4
|
||||||
#define TC_MQPRIO_F_MAX_RATE 0x8
|
#define TC_MQPRIO_F_MAX_RATE 0x8
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TCA_MQPRIO_TC_ENTRY_UNSPEC,
|
||||||
|
TCA_MQPRIO_TC_ENTRY_INDEX, /* u32 */
|
||||||
|
TCA_MQPRIO_TC_ENTRY_FP, /* u32 */
|
||||||
|
|
||||||
|
/* add new constants above here */
|
||||||
|
__TCA_MQPRIO_TC_ENTRY_CNT,
|
||||||
|
TCA_MQPRIO_TC_ENTRY_MAX = (__TCA_MQPRIO_TC_ENTRY_CNT - 1)
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TCA_MQPRIO_UNSPEC,
|
TCA_MQPRIO_UNSPEC,
|
||||||
TCA_MQPRIO_MODE,
|
TCA_MQPRIO_MODE,
|
||||||
TCA_MQPRIO_SHAPER,
|
TCA_MQPRIO_SHAPER,
|
||||||
TCA_MQPRIO_MIN_RATE64,
|
TCA_MQPRIO_MIN_RATE64,
|
||||||
TCA_MQPRIO_MAX_RATE64,
|
TCA_MQPRIO_MAX_RATE64,
|
||||||
|
TCA_MQPRIO_TC_ENTRY,
|
||||||
__TCA_MQPRIO_MAX,
|
__TCA_MQPRIO_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -698,6 +735,8 @@ struct tc_codel_xstats {
|
|||||||
|
|
||||||
/* FQ_CODEL */
|
/* FQ_CODEL */
|
||||||
|
|
||||||
|
#define FQ_CODEL_QUANTUM_MAX (1 << 20)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TCA_FQ_CODEL_UNSPEC,
|
TCA_FQ_CODEL_UNSPEC,
|
||||||
TCA_FQ_CODEL_TARGET,
|
TCA_FQ_CODEL_TARGET,
|
||||||
@@ -709,6 +748,8 @@ enum {
|
|||||||
TCA_FQ_CODEL_CE_THRESHOLD,
|
TCA_FQ_CODEL_CE_THRESHOLD,
|
||||||
TCA_FQ_CODEL_DROP_BATCH_SIZE,
|
TCA_FQ_CODEL_DROP_BATCH_SIZE,
|
||||||
TCA_FQ_CODEL_MEMORY_LIMIT,
|
TCA_FQ_CODEL_MEMORY_LIMIT,
|
||||||
|
TCA_FQ_CODEL_CE_THRESHOLD_SELECTOR,
|
||||||
|
TCA_FQ_CODEL_CE_THRESHOLD_MASK,
|
||||||
__TCA_FQ_CODEL_MAX
|
__TCA_FQ_CODEL_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -785,15 +826,30 @@ enum {
|
|||||||
|
|
||||||
TCA_FQ_CE_THRESHOLD, /* DCTCP-like CE-marking threshold */
|
TCA_FQ_CE_THRESHOLD, /* DCTCP-like CE-marking threshold */
|
||||||
|
|
||||||
|
TCA_FQ_TIMER_SLACK, /* timer slack */
|
||||||
|
|
||||||
|
TCA_FQ_HORIZON, /* time horizon in us */
|
||||||
|
|
||||||
|
TCA_FQ_HORIZON_DROP, /* drop packets beyond horizon, or cap their EDT */
|
||||||
|
|
||||||
|
TCA_FQ_PRIOMAP, /* prio2band */
|
||||||
|
|
||||||
|
TCA_FQ_WEIGHTS, /* Weights for each band */
|
||||||
|
|
||||||
|
TCA_FQ_OFFLOAD_HORIZON, /* dequeue paced packets within this horizon immediately (us units) */
|
||||||
|
|
||||||
__TCA_FQ_MAX
|
__TCA_FQ_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TCA_FQ_MAX (__TCA_FQ_MAX - 1)
|
#define TCA_FQ_MAX (__TCA_FQ_MAX - 1)
|
||||||
|
|
||||||
|
#define FQ_BANDS 3
|
||||||
|
#define FQ_MIN_WEIGHT 16384
|
||||||
|
|
||||||
struct tc_fq_qd_stats {
|
struct tc_fq_qd_stats {
|
||||||
__u64 gc_flows;
|
__u64 gc_flows;
|
||||||
__u64 highprio_packets;
|
__u64 highprio_packets; /* obsolete */
|
||||||
__u64 tcp_retrans;
|
__u64 tcp_retrans; /* obsolete */
|
||||||
__u64 throttled;
|
__u64 throttled;
|
||||||
__u64 flows_plimit;
|
__u64 flows_plimit;
|
||||||
__u64 pkts_too_long;
|
__u64 pkts_too_long;
|
||||||
@@ -804,6 +860,12 @@ struct tc_fq_qd_stats {
|
|||||||
__u32 throttled_flows;
|
__u32 throttled_flows;
|
||||||
__u32 unthrottle_latency_ns;
|
__u32 unthrottle_latency_ns;
|
||||||
__u64 ce_mark; /* packets above ce_threshold */
|
__u64 ce_mark; /* packets above ce_threshold */
|
||||||
|
__u64 horizon_drops;
|
||||||
|
__u64 horizon_caps;
|
||||||
|
__u64 fastpath_packets;
|
||||||
|
__u64 band_drops[FQ_BANDS];
|
||||||
|
__u32 band_pkt_count[FQ_BANDS];
|
||||||
|
__u32 pad;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Heavy-Hitter Filter */
|
/* Heavy-Hitter Filter */
|
||||||
@@ -841,19 +903,56 @@ enum {
|
|||||||
TCA_PIE_BETA,
|
TCA_PIE_BETA,
|
||||||
TCA_PIE_ECN,
|
TCA_PIE_ECN,
|
||||||
TCA_PIE_BYTEMODE,
|
TCA_PIE_BYTEMODE,
|
||||||
|
TCA_PIE_DQ_RATE_ESTIMATOR,
|
||||||
__TCA_PIE_MAX
|
__TCA_PIE_MAX
|
||||||
};
|
};
|
||||||
#define TCA_PIE_MAX (__TCA_PIE_MAX - 1)
|
#define TCA_PIE_MAX (__TCA_PIE_MAX - 1)
|
||||||
|
|
||||||
struct tc_pie_xstats {
|
struct tc_pie_xstats {
|
||||||
__u32 prob; /* current probability */
|
__u64 prob; /* current probability */
|
||||||
__u32 delay; /* current delay in ms */
|
__u32 delay; /* current delay in ms */
|
||||||
__u32 avg_dq_rate; /* current average dq_rate in bits/pie_time */
|
__u32 avg_dq_rate; /* current average dq_rate in
|
||||||
__u32 packets_in; /* total number of packets enqueued */
|
* bits/pie_time
|
||||||
__u32 dropped; /* packets dropped due to pie_action */
|
*/
|
||||||
__u32 overlimit; /* dropped due to lack of space in queue */
|
__u32 dq_rate_estimating; /* is avg_dq_rate being calculated? */
|
||||||
__u32 maxq; /* maximum queue size */
|
__u32 packets_in; /* total number of packets enqueued */
|
||||||
__u32 ecn_mark; /* packets marked with ecn*/
|
__u32 dropped; /* packets dropped due to pie_action */
|
||||||
|
__u32 overlimit; /* dropped due to lack of space
|
||||||
|
* in queue
|
||||||
|
*/
|
||||||
|
__u32 maxq; /* maximum queue size */
|
||||||
|
__u32 ecn_mark; /* packets marked with ecn*/
|
||||||
|
};
|
||||||
|
|
||||||
|
/* FQ PIE */
|
||||||
|
enum {
|
||||||
|
TCA_FQ_PIE_UNSPEC,
|
||||||
|
TCA_FQ_PIE_LIMIT,
|
||||||
|
TCA_FQ_PIE_FLOWS,
|
||||||
|
TCA_FQ_PIE_TARGET,
|
||||||
|
TCA_FQ_PIE_TUPDATE,
|
||||||
|
TCA_FQ_PIE_ALPHA,
|
||||||
|
TCA_FQ_PIE_BETA,
|
||||||
|
TCA_FQ_PIE_QUANTUM,
|
||||||
|
TCA_FQ_PIE_MEMORY_LIMIT,
|
||||||
|
TCA_FQ_PIE_ECN_PROB,
|
||||||
|
TCA_FQ_PIE_ECN,
|
||||||
|
TCA_FQ_PIE_BYTEMODE,
|
||||||
|
TCA_FQ_PIE_DQ_RATE_ESTIMATOR,
|
||||||
|
__TCA_FQ_PIE_MAX
|
||||||
|
};
|
||||||
|
#define TCA_FQ_PIE_MAX (__TCA_FQ_PIE_MAX - 1)
|
||||||
|
|
||||||
|
struct tc_fq_pie_xstats {
|
||||||
|
__u32 packets_in; /* total number of packets enqueued */
|
||||||
|
__u32 dropped; /* packets dropped due to fq_pie_action */
|
||||||
|
__u32 overlimit; /* dropped due to lack of space in queue */
|
||||||
|
__u32 overmemory; /* dropped due to lack of memory in queue */
|
||||||
|
__u32 ecn_mark; /* packets marked with ecn */
|
||||||
|
__u32 new_flow_count; /* count of new flows created by packets */
|
||||||
|
__u32 new_flows_len; /* count of flows in new list */
|
||||||
|
__u32 old_flows_len; /* count of flows in old list */
|
||||||
|
__u32 memory_usage; /* total memory across all queues */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* CBS */
|
/* CBS */
|
||||||
@@ -880,8 +979,9 @@ struct tc_etf_qopt {
|
|||||||
__s32 delta;
|
__s32 delta;
|
||||||
__s32 clockid;
|
__s32 clockid;
|
||||||
__u32 flags;
|
__u32 flags;
|
||||||
#define TC_ETF_DEADLINE_MODE_ON BIT(0)
|
#define TC_ETF_DEADLINE_MODE_ON _BITUL(0)
|
||||||
#define TC_ETF_OFFLOAD_ON BIT(1)
|
#define TC_ETF_OFFLOAD_ON _BITUL(1)
|
||||||
|
#define TC_ETF_SKIP_SOCK_CHECK _BITUL(2)
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -913,6 +1013,7 @@ enum {
|
|||||||
TCA_CAKE_INGRESS,
|
TCA_CAKE_INGRESS,
|
||||||
TCA_CAKE_ACK_FILTER,
|
TCA_CAKE_ACK_FILTER,
|
||||||
TCA_CAKE_SPLIT_GSO,
|
TCA_CAKE_SPLIT_GSO,
|
||||||
|
TCA_CAKE_FWMARK,
|
||||||
__TCA_CAKE_MAX
|
__TCA_CAKE_MAX
|
||||||
};
|
};
|
||||||
#define TCA_CAKE_MAX (__TCA_CAKE_MAX - 1)
|
#define TCA_CAKE_MAX (__TCA_CAKE_MAX - 1)
|
||||||
@@ -1039,6 +1140,40 @@ enum {
|
|||||||
|
|
||||||
#define TCA_TAPRIO_SCHED_MAX (__TCA_TAPRIO_SCHED_MAX - 1)
|
#define TCA_TAPRIO_SCHED_MAX (__TCA_TAPRIO_SCHED_MAX - 1)
|
||||||
|
|
||||||
|
/* The format for the admin sched (dump only):
|
||||||
|
* [TCA_TAPRIO_SCHED_ADMIN_SCHED]
|
||||||
|
* [TCA_TAPRIO_ATTR_SCHED_BASE_TIME]
|
||||||
|
* [TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST]
|
||||||
|
* [TCA_TAPRIO_ATTR_SCHED_ENTRY]
|
||||||
|
* [TCA_TAPRIO_ATTR_SCHED_ENTRY_CMD]
|
||||||
|
* [TCA_TAPRIO_ATTR_SCHED_ENTRY_GATES]
|
||||||
|
* [TCA_TAPRIO_ATTR_SCHED_ENTRY_INTERVAL]
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST _BITUL(0)
|
||||||
|
#define TCA_TAPRIO_ATTR_FLAG_FULL_OFFLOAD _BITUL(1)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TCA_TAPRIO_TC_ENTRY_UNSPEC,
|
||||||
|
TCA_TAPRIO_TC_ENTRY_INDEX, /* u32 */
|
||||||
|
TCA_TAPRIO_TC_ENTRY_MAX_SDU, /* u32 */
|
||||||
|
TCA_TAPRIO_TC_ENTRY_FP, /* u32 */
|
||||||
|
|
||||||
|
/* add new constants above here */
|
||||||
|
__TCA_TAPRIO_TC_ENTRY_CNT,
|
||||||
|
TCA_TAPRIO_TC_ENTRY_MAX = (__TCA_TAPRIO_TC_ENTRY_CNT - 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TCA_TAPRIO_OFFLOAD_STATS_PAD = 1, /* u64 */
|
||||||
|
TCA_TAPRIO_OFFLOAD_STATS_WINDOW_DROPS, /* u64 */
|
||||||
|
TCA_TAPRIO_OFFLOAD_STATS_TX_OVERRUNS, /* u64 */
|
||||||
|
|
||||||
|
/* add new constants above here */
|
||||||
|
__TCA_TAPRIO_OFFLOAD_STATS_CNT,
|
||||||
|
TCA_TAPRIO_OFFLOAD_STATS_MAX = (__TCA_TAPRIO_OFFLOAD_STATS_CNT - 1)
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TCA_TAPRIO_ATTR_UNSPEC,
|
TCA_TAPRIO_ATTR_UNSPEC,
|
||||||
TCA_TAPRIO_ATTR_PRIOMAP, /* struct tc_mqprio_qopt */
|
TCA_TAPRIO_ATTR_PRIOMAP, /* struct tc_mqprio_qopt */
|
||||||
@@ -1047,9 +1182,101 @@ enum {
|
|||||||
TCA_TAPRIO_ATTR_SCHED_SINGLE_ENTRY, /* single entry */
|
TCA_TAPRIO_ATTR_SCHED_SINGLE_ENTRY, /* single entry */
|
||||||
TCA_TAPRIO_ATTR_SCHED_CLOCKID, /* s32 */
|
TCA_TAPRIO_ATTR_SCHED_CLOCKID, /* s32 */
|
||||||
TCA_TAPRIO_PAD,
|
TCA_TAPRIO_PAD,
|
||||||
|
TCA_TAPRIO_ATTR_PAD = TCA_TAPRIO_PAD,
|
||||||
|
TCA_TAPRIO_ATTR_ADMIN_SCHED, /* The admin sched, only used in dump */
|
||||||
|
TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME, /* s64 */
|
||||||
|
TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION, /* s64 */
|
||||||
|
TCA_TAPRIO_ATTR_FLAGS, /* u32 */
|
||||||
|
TCA_TAPRIO_ATTR_TXTIME_DELAY, /* u32 */
|
||||||
|
TCA_TAPRIO_ATTR_TC_ENTRY, /* nest */
|
||||||
__TCA_TAPRIO_ATTR_MAX,
|
__TCA_TAPRIO_ATTR_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TCA_TAPRIO_ATTR_MAX (__TCA_TAPRIO_ATTR_MAX - 1)
|
#define TCA_TAPRIO_ATTR_MAX (__TCA_TAPRIO_ATTR_MAX - 1)
|
||||||
|
|
||||||
|
/* ETS */
|
||||||
|
|
||||||
|
#define TCQ_ETS_MAX_BANDS 16
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TCA_ETS_UNSPEC,
|
||||||
|
TCA_ETS_NBANDS, /* u8 */
|
||||||
|
TCA_ETS_NSTRICT, /* u8 */
|
||||||
|
TCA_ETS_QUANTA, /* nested TCA_ETS_QUANTA_BAND */
|
||||||
|
TCA_ETS_QUANTA_BAND, /* u32 */
|
||||||
|
TCA_ETS_PRIOMAP, /* nested TCA_ETS_PRIOMAP_BAND */
|
||||||
|
TCA_ETS_PRIOMAP_BAND, /* u8 */
|
||||||
|
__TCA_ETS_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TCA_ETS_MAX (__TCA_ETS_MAX - 1)
|
||||||
|
|
||||||
|
/* DUALPI2 */
|
||||||
|
enum tc_dualpi2_drop_overload {
|
||||||
|
TC_DUALPI2_DROP_OVERLOAD_OVERFLOW = 0,
|
||||||
|
TC_DUALPI2_DROP_OVERLOAD_DROP = 1,
|
||||||
|
__TCA_DUALPI2_DROP_OVERLOAD_MAX,
|
||||||
|
};
|
||||||
|
#define TCA_DUALPI2_DROP_OVERLOAD_MAX (__TCA_DUALPI2_DROP_OVERLOAD_MAX - 1)
|
||||||
|
|
||||||
|
enum tc_dualpi2_drop_early {
|
||||||
|
TC_DUALPI2_DROP_EARLY_DROP_DEQUEUE = 0,
|
||||||
|
TC_DUALPI2_DROP_EARLY_DROP_ENQUEUE = 1,
|
||||||
|
__TCA_DUALPI2_DROP_EARLY_MAX,
|
||||||
|
};
|
||||||
|
#define TCA_DUALPI2_DROP_EARLY_MAX (__TCA_DUALPI2_DROP_EARLY_MAX - 1)
|
||||||
|
|
||||||
|
enum tc_dualpi2_ecn_mask {
|
||||||
|
TC_DUALPI2_ECN_MASK_L4S_ECT = 1,
|
||||||
|
TC_DUALPI2_ECN_MASK_CLA_ECT = 2,
|
||||||
|
TC_DUALPI2_ECN_MASK_ANY_ECT = 3,
|
||||||
|
__TCA_DUALPI2_ECN_MASK_MAX,
|
||||||
|
};
|
||||||
|
#define TCA_DUALPI2_ECN_MASK_MAX (__TCA_DUALPI2_ECN_MASK_MAX - 1)
|
||||||
|
|
||||||
|
enum tc_dualpi2_split_gso {
|
||||||
|
TC_DUALPI2_SPLIT_GSO_NO_SPLIT_GSO = 0,
|
||||||
|
TC_DUALPI2_SPLIT_GSO_SPLIT_GSO = 1,
|
||||||
|
__TCA_DUALPI2_SPLIT_GSO_MAX,
|
||||||
|
};
|
||||||
|
#define TCA_DUALPI2_SPLIT_GSO_MAX (__TCA_DUALPI2_SPLIT_GSO_MAX - 1)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TCA_DUALPI2_UNSPEC,
|
||||||
|
TCA_DUALPI2_LIMIT, /* Packets */
|
||||||
|
TCA_DUALPI2_MEMORY_LIMIT, /* Bytes */
|
||||||
|
TCA_DUALPI2_TARGET, /* us */
|
||||||
|
TCA_DUALPI2_TUPDATE, /* us */
|
||||||
|
TCA_DUALPI2_ALPHA, /* Hz scaled up by 256 */
|
||||||
|
TCA_DUALPI2_BETA, /* Hz scaled up by 256 */
|
||||||
|
TCA_DUALPI2_STEP_THRESH_PKTS, /* Step threshold in packets */
|
||||||
|
TCA_DUALPI2_STEP_THRESH_US, /* Step threshold in microseconds */
|
||||||
|
TCA_DUALPI2_MIN_QLEN_STEP, /* Minimum qlen to apply STEP_THRESH */
|
||||||
|
TCA_DUALPI2_COUPLING, /* Coupling factor between queues */
|
||||||
|
TCA_DUALPI2_DROP_OVERLOAD, /* Whether to drop on overload */
|
||||||
|
TCA_DUALPI2_DROP_EARLY, /* Whether to drop on enqueue */
|
||||||
|
TCA_DUALPI2_C_PROTECTION, /* Percentage */
|
||||||
|
TCA_DUALPI2_ECN_MASK, /* L4S queue classification mask */
|
||||||
|
TCA_DUALPI2_SPLIT_GSO, /* Split GSO packets at enqueue */
|
||||||
|
TCA_DUALPI2_PAD,
|
||||||
|
__TCA_DUALPI2_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TCA_DUALPI2_MAX (__TCA_DUALPI2_MAX - 1)
|
||||||
|
|
||||||
|
struct tc_dualpi2_xstats {
|
||||||
|
__u32 prob; /* current probability */
|
||||||
|
__u32 delay_c; /* current delay in C queue */
|
||||||
|
__u32 delay_l; /* current delay in L queue */
|
||||||
|
__u32 packets_in_c; /* number of packets enqueued in C queue */
|
||||||
|
__u32 packets_in_l; /* number of packets enqueued in L queue */
|
||||||
|
__u32 maxq; /* maximum queue size */
|
||||||
|
__u32 ecn_mark; /* packets marked with ecn*/
|
||||||
|
__u32 step_marks; /* ECN marks due to the step AQM */
|
||||||
|
__s32 credit; /* current c_protection credit */
|
||||||
|
__u32 memory_used; /* Memory used by both queues */
|
||||||
|
__u32 max_memory_used; /* Maximum used memory */
|
||||||
|
__u32 memory_limit; /* Memory limit of both queues */
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
81
include/uapi/linux/stddef.h
Normal file
81
include/uapi/linux/stddef.h
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||||
|
#ifndef _LINUX_STDDEF_H
|
||||||
|
#define _LINUX_STDDEF_H
|
||||||
|
|
||||||
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __always_inline
|
||||||
|
#define __always_inline inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Not all C++ standards support type declarations inside an anonymous union */
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#define __struct_group_tag(TAG) TAG
|
||||||
|
#else
|
||||||
|
#define __struct_group_tag(TAG)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __struct_group() - Create a mirrored named and anonyomous struct
|
||||||
|
*
|
||||||
|
* @TAG: The tag name for the named sub-struct (usually empty)
|
||||||
|
* @NAME: The identifier name of the mirrored sub-struct
|
||||||
|
* @ATTRS: Any struct attributes (usually empty)
|
||||||
|
* @MEMBERS: The member declarations for the mirrored structs
|
||||||
|
*
|
||||||
|
* Used to create an anonymous union of two structs with identical layout
|
||||||
|
* and size: one anonymous and one named. The former's members can be used
|
||||||
|
* normally without sub-struct naming, and the latter can be used to
|
||||||
|
* reason about the start, end, and size of the group of struct members.
|
||||||
|
* The named struct can also be explicitly tagged for layer reuse (C only),
|
||||||
|
* as well as both having struct attributes appended.
|
||||||
|
*/
|
||||||
|
#define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \
|
||||||
|
union { \
|
||||||
|
struct { MEMBERS } ATTRS; \
|
||||||
|
struct __struct_group_tag(TAG) { MEMBERS } ATTRS NAME; \
|
||||||
|
} ATTRS
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
/* sizeof(struct{}) is 1 in C++, not 0, can't use C version of the macro. */
|
||||||
|
#define __DECLARE_FLEX_ARRAY(T, member) \
|
||||||
|
T member[0]
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* __DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union
|
||||||
|
*
|
||||||
|
* @TYPE: The type of each flexible array element
|
||||||
|
* @NAME: The name of the flexible array member
|
||||||
|
*
|
||||||
|
* In order to have a flexible array member in a union or alone in a
|
||||||
|
* struct, it needs to be wrapped in an anonymous struct with at least 1
|
||||||
|
* named member, but that member can be empty.
|
||||||
|
*/
|
||||||
|
#define __DECLARE_FLEX_ARRAY(TYPE, NAME) \
|
||||||
|
struct { \
|
||||||
|
struct { } __empty_ ## NAME; \
|
||||||
|
TYPE NAME[]; \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __counted_by
|
||||||
|
#define __counted_by(m)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __counted_by_le
|
||||||
|
#define __counted_by_le(m)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __counted_by_be
|
||||||
|
#define __counted_by_be(m)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __KERNEL__
|
||||||
|
#define __kernel_nonstring __nonstring
|
||||||
|
#else
|
||||||
|
#define __kernel_nonstring
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _LINUX_STDDEF_H */
|
||||||
@@ -35,44 +35,48 @@ if [[ "$SANITIZER" == undefined ]]; then
|
|||||||
CXXFLAGS+=" $UBSAN_FLAGS"
|
CXXFLAGS+=" $UBSAN_FLAGS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
export SKIP_LIBELF_REBUILD=${SKIP_LIBELF_REBUILD:=''}
|
||||||
|
|
||||||
# Ideally libbelf should be built using release tarballs available
|
# Ideally libbelf should be built using release tarballs available
|
||||||
# at https://sourceware.org/elfutils/ftp/. Unfortunately sometimes they
|
# at https://sourceware.org/elfutils/ftp/. Unfortunately sometimes they
|
||||||
# fail to compile (for example, elfutils-0.185 fails to compile with LDFLAGS enabled
|
# fail to compile (for example, elfutils-0.185 fails to compile with LDFLAGS enabled
|
||||||
# due to https://bugs.gentoo.org/794601) so let's just point the script to
|
# due to https://bugs.gentoo.org/794601) so let's just point the script to
|
||||||
# commits referring to versions of libelf that actually can be built
|
# commits referring to versions of libelf that actually can be built
|
||||||
rm -rf elfutils
|
if [[ ! -e elfutils || "$SKIP_LIBELF_REBUILD" == "" ]]; then
|
||||||
git clone https://sourceware.org/git/elfutils.git
|
rm -rf elfutils
|
||||||
(
|
git clone https://sourceware.org/git/elfutils.git
|
||||||
cd elfutils
|
(
|
||||||
git checkout 67a187d4c1790058fc7fd218317851cb68bb087c
|
cd elfutils
|
||||||
git log --oneline -1
|
git checkout 67a187d4c1790058fc7fd218317851cb68bb087c
|
||||||
|
git log --oneline -1
|
||||||
|
|
||||||
# ASan isn't compatible with -Wl,--no-undefined: https://github.com/google/sanitizers/issues/380
|
# ASan isn't compatible with -Wl,--no-undefined: https://github.com/google/sanitizers/issues/380
|
||||||
sed -i 's/^\(NO_UNDEFINED=\).*/\1/' configure.ac
|
sed -i 's/^\(NO_UNDEFINED=\).*/\1/' configure.ac
|
||||||
|
|
||||||
# ASan isn't compatible with -Wl,-z,defs either:
|
# ASan isn't compatible with -Wl,-z,defs either:
|
||||||
# https://clang.llvm.org/docs/AddressSanitizer.html#usage
|
# https://clang.llvm.org/docs/AddressSanitizer.html#usage
|
||||||
sed -i 's/^\(ZDEFS_LDFLAGS=\).*/\1/' configure.ac
|
sed -i 's/^\(ZDEFS_LDFLAGS=\).*/\1/' configure.ac
|
||||||
|
|
||||||
if [[ "$SANITIZER" == undefined ]]; then
|
if [[ "$SANITIZER" == undefined ]]; then
|
||||||
# That's basicaly what --enable-sanitize-undefined does to turn off unaligned access
|
# That's basicaly what --enable-sanitize-undefined does to turn off unaligned access
|
||||||
# elfutils heavily relies on on i386/x86_64 but without changing compiler flags along the way
|
# elfutils heavily relies on on i386/x86_64 but without changing compiler flags along the way
|
||||||
sed -i 's/\(check_undefined_val\)=[0-9]/\1=1/' configure.ac
|
sed -i 's/\(check_undefined_val\)=[0-9]/\1=1/' configure.ac
|
||||||
|
fi
|
||||||
|
|
||||||
|
autoreconf -i -f
|
||||||
|
if ! ./configure --enable-maintainer-mode --disable-debuginfod --disable-libdebuginfod \
|
||||||
|
--disable-demangler --without-bzlib --without-lzma --without-zstd \
|
||||||
|
CC="$CC" CFLAGS="-Wno-error $CFLAGS" CXX="$CXX" CXXFLAGS="-Wno-error $CXXFLAGS" LDFLAGS="$CFLAGS"; then
|
||||||
|
cat config.log
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
make -C config -j$(nproc) V=1
|
||||||
|
make -C lib -j$(nproc) V=1
|
||||||
|
make -C libelf -j$(nproc) V=1
|
||||||
|
)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
autoreconf -i -f
|
|
||||||
if ! ./configure --enable-maintainer-mode --disable-debuginfod --disable-libdebuginfod \
|
|
||||||
--disable-demangler --without-bzlib --without-lzma --without-zstd \
|
|
||||||
CC="$CC" CFLAGS="-Wno-error $CFLAGS" CXX="$CXX" CXXFLAGS="-Wno-error $CXXFLAGS" LDFLAGS="$CFLAGS"; then
|
|
||||||
cat config.log
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
make -C config -j$(nproc) V=1
|
|
||||||
make -C lib -j$(nproc) V=1
|
|
||||||
make -C libelf -j$(nproc) V=1
|
|
||||||
)
|
|
||||||
|
|
||||||
make -C src BUILD_STATIC_ONLY=y V=1 clean
|
make -C src BUILD_STATIC_ONLY=y V=1 clean
|
||||||
make -C src -j$(nproc) CFLAGS="-I$(pwd)/elfutils/libelf $CFLAGS" BUILD_STATIC_ONLY=y V=1
|
make -C src -j$(nproc) CFLAGS="-I$(pwd)/elfutils/libelf $CFLAGS" BUILD_STATIC_ONLY=y V=1
|
||||||
|
|
||||||
|
|||||||
@@ -39,18 +39,19 @@ trap "cd ${WORKDIR}; exit" INT TERM EXIT
|
|||||||
declare -A PATH_MAP
|
declare -A PATH_MAP
|
||||||
PATH_MAP=( \
|
PATH_MAP=( \
|
||||||
[tools/lib/bpf]=src \
|
[tools/lib/bpf]=src \
|
||||||
[tools/include/uapi/linux/bpf_common.h]=include/uapi/linux/bpf_common.h \
|
[include/uapi/linux/bpf_common.h]=include/uapi/linux/bpf_common.h \
|
||||||
[tools/include/uapi/linux/bpf.h]=include/uapi/linux/bpf.h \
|
[include/uapi/linux/bpf.h]=include/uapi/linux/bpf.h \
|
||||||
[tools/include/uapi/linux/btf.h]=include/uapi/linux/btf.h \
|
[include/uapi/linux/btf.h]=include/uapi/linux/btf.h \
|
||||||
[tools/include/uapi/linux/fcntl.h]=include/uapi/linux/fcntl.h \
|
[include/uapi/linux/fcntl.h]=include/uapi/linux/fcntl.h \
|
||||||
[tools/include/uapi/linux/openat2.h]=include/uapi/linux/openat2.h \
|
[include/uapi/linux/openat2.h]=include/uapi/linux/openat2.h \
|
||||||
[tools/include/uapi/linux/if_link.h]=include/uapi/linux/if_link.h \
|
[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 \
|
[include/uapi/linux/if_xdp.h]=include/uapi/linux/if_xdp.h \
|
||||||
[tools/include/uapi/linux/netdev.h]=include/uapi/linux/netdev.h \
|
[include/uapi/linux/netdev.h]=include/uapi/linux/netdev.h \
|
||||||
[tools/include/uapi/linux/netlink.h]=include/uapi/linux/netlink.h \
|
[include/uapi/linux/netlink.h]=include/uapi/linux/netlink.h \
|
||||||
[tools/include/uapi/linux/pkt_cls.h]=include/uapi/linux/pkt_cls.h \
|
[include/uapi/linux/pkt_cls.h]=include/uapi/linux/pkt_cls.h \
|
||||||
[tools/include/uapi/linux/pkt_sched.h]=include/uapi/linux/pkt_sched.h \
|
[include/uapi/linux/pkt_sched.h]=include/uapi/linux/pkt_sched.h \
|
||||||
[include/uapi/linux/perf_event.h]=include/uapi/linux/perf_event.h \
|
[include/uapi/linux/perf_event.h]=include/uapi/linux/perf_event.h \
|
||||||
|
[include/uapi/linux/stddef.h]=include/uapi/linux/stddef.h \
|
||||||
[Documentation/bpf/libbpf]=docs \
|
[Documentation/bpf/libbpf]=docs \
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -63,6 +64,7 @@ LIBBPF_TREE_FILTER="mkdir -p __libbpf/include/uapi/linux __libbpf/include/tools
|
|||||||
for p in "${!PATH_MAP[@]}"; do
|
for p in "${!PATH_MAP[@]}"; do
|
||||||
LIBBPF_TREE_FILTER+="git mv -kf ${p} __libbpf/${PATH_MAP[${p}]} && "$'\\\n'
|
LIBBPF_TREE_FILTER+="git mv -kf ${p} __libbpf/${PATH_MAP[${p}]} && "$'\\\n'
|
||||||
done
|
done
|
||||||
|
LIBBPF_TREE_FILTER+="find __libbpf/include/uapi/linux -type f -exec sed -i -e 's/_UAPI\(__\?LINUX\)/\1/g' -e 's@^#include <linux/compiler_types.h>@@' {} + && "$'\\\n'
|
||||||
LIBBPF_TREE_FILTER+="git rm --ignore-unmatch -f __libbpf/src/{Makefile,Build,test_libbpf.c,.gitignore} >/dev/null"
|
LIBBPF_TREE_FILTER+="git rm --ignore-unmatch -f __libbpf/src/{Makefile,Build,test_libbpf.c,.gitignore} >/dev/null"
|
||||||
|
|
||||||
cd_to()
|
cd_to()
|
||||||
@@ -347,7 +349,7 @@ diff -u ${TMP_DIR}/linux-view.ls ${TMP_DIR}/github-view.ls
|
|||||||
echo "Comparing file contents..."
|
echo "Comparing file contents..."
|
||||||
CONSISTENT=1
|
CONSISTENT=1
|
||||||
for F in $(cat ${TMP_DIR}/linux-view.ls); do
|
for F in $(cat ${TMP_DIR}/linux-view.ls); do
|
||||||
if ! diff -u "${LINUX_ABS_DIR}/${F}" "${GITHUB_ABS_DIR}/${F}"; then
|
if ! diff -u <(sed 's/_UAPI\(__\?LINUX\)/\1/' "${LINUX_ABS_DIR}/${F}") "${GITHUB_ABS_DIR}/${F}"; then
|
||||||
echo "${LINUX_ABS_DIR}/${F} and ${GITHUB_ABS_DIR}/${F} are different!"
|
echo "${LINUX_ABS_DIR}/${F} and ${GITHUB_ABS_DIR}/${F} are different!"
|
||||||
CONSISTENT=0
|
CONSISTENT=0
|
||||||
fi
|
fi
|
||||||
|
|||||||
13
src/Makefile
13
src/Makefile
@@ -9,7 +9,7 @@ else
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
LIBBPF_MAJOR_VERSION := 1
|
LIBBPF_MAJOR_VERSION := 1
|
||||||
LIBBPF_MINOR_VERSION := 5
|
LIBBPF_MINOR_VERSION := 7
|
||||||
LIBBPF_PATCH_VERSION := 0
|
LIBBPF_PATCH_VERSION := 0
|
||||||
LIBBPF_VERSION := $(LIBBPF_MAJOR_VERSION).$(LIBBPF_MINOR_VERSION).$(LIBBPF_PATCH_VERSION)
|
LIBBPF_VERSION := $(LIBBPF_MAJOR_VERSION).$(LIBBPF_MINOR_VERSION).$(LIBBPF_PATCH_VERSION)
|
||||||
LIBBPF_MAJMIN_VERSION := $(LIBBPF_MAJOR_VERSION).$(LIBBPF_MINOR_VERSION).0
|
LIBBPF_MAJMIN_VERSION := $(LIBBPF_MAJOR_VERSION).$(LIBBPF_MINOR_VERSION).0
|
||||||
@@ -26,6 +26,7 @@ endef
|
|||||||
|
|
||||||
$(call allow-override,CC,$(CROSS_COMPILE)cc)
|
$(call allow-override,CC,$(CROSS_COMPILE)cc)
|
||||||
$(call allow-override,LD,$(CROSS_COMPILE)ld)
|
$(call allow-override,LD,$(CROSS_COMPILE)ld)
|
||||||
|
PKG_CONFIG ?= pkg-config
|
||||||
|
|
||||||
TOPDIR = ..
|
TOPDIR = ..
|
||||||
|
|
||||||
@@ -41,10 +42,12 @@ ALL_CFLAGS += $(CFLAGS) \
|
|||||||
$(EXTRA_CFLAGS)
|
$(EXTRA_CFLAGS)
|
||||||
ALL_LDFLAGS += $(LDFLAGS) $(EXTRA_LDFLAGS)
|
ALL_LDFLAGS += $(LDFLAGS) $(EXTRA_LDFLAGS)
|
||||||
|
|
||||||
|
ifeq ($(shell command -v $(PKG_CONFIG) 2> /dev/null),)
|
||||||
|
NO_PKG_CONFIG := 1
|
||||||
|
endif
|
||||||
ifdef NO_PKG_CONFIG
|
ifdef NO_PKG_CONFIG
|
||||||
ALL_LDFLAGS += -lelf -lz
|
ALL_LDFLAGS += -lelf -lz
|
||||||
else
|
else
|
||||||
PKG_CONFIG ?= pkg-config
|
|
||||||
ALL_CFLAGS += $(shell $(PKG_CONFIG) --cflags libelf zlib)
|
ALL_CFLAGS += $(shell $(PKG_CONFIG) --cflags libelf zlib)
|
||||||
ALL_LDFLAGS += $(shell $(PKG_CONFIG) --libs libelf zlib)
|
ALL_LDFLAGS += $(shell $(PKG_CONFIG) --libs libelf zlib)
|
||||||
endif
|
endif
|
||||||
@@ -52,9 +55,9 @@ endif
|
|||||||
OBJDIR ?= .
|
OBJDIR ?= .
|
||||||
SHARED_OBJDIR := $(OBJDIR)/sharedobjs
|
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_utils.o netlink.o \
|
||||||
nlattr.o str_error.o libbpf_probes.o bpf_prog_linfo.o \
|
nlattr.o libbpf_probes.o bpf_prog_linfo.o \
|
||||||
btf_dump.o hashmap.o ringbuf.o strset.o linker.o gen_loader.o \
|
btf_dump.o hashmap.o ringbuf.o strset.o linker.o gen_loader.o \
|
||||||
relo_core.o usdt.o zip.o elf.o features.o btf_iter.o btf_relocate.o
|
relo_core.o usdt.o zip.o elf.o features.o btf_iter.o btf_relocate.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))
|
||||||
|
|||||||
97
src/bpf.c
97
src/bpf.c
@@ -154,7 +154,7 @@ int bump_rlimit_memlock(void)
|
|||||||
|
|
||||||
memlock_bumped = true;
|
memlock_bumped = true;
|
||||||
|
|
||||||
/* zero memlock_rlim_max disables auto-bumping RLIMIT_MEMLOCK */
|
/* zero memlock_rlim disables auto-bumping RLIMIT_MEMLOCK */
|
||||||
if (memlock_rlim == 0)
|
if (memlock_rlim == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -172,7 +172,7 @@ int bpf_map_create(enum bpf_map_type map_type,
|
|||||||
__u32 max_entries,
|
__u32 max_entries,
|
||||||
const struct bpf_map_create_opts *opts)
|
const struct bpf_map_create_opts *opts)
|
||||||
{
|
{
|
||||||
const size_t attr_sz = offsetofend(union bpf_attr, map_token_fd);
|
const size_t attr_sz = offsetofend(union bpf_attr, excl_prog_hash_size);
|
||||||
union bpf_attr attr;
|
union bpf_attr attr;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
@@ -203,6 +203,8 @@ int bpf_map_create(enum bpf_map_type map_type,
|
|||||||
attr.map_ifindex = OPTS_GET(opts, map_ifindex, 0);
|
attr.map_ifindex = OPTS_GET(opts, map_ifindex, 0);
|
||||||
|
|
||||||
attr.map_token_fd = OPTS_GET(opts, token_fd, 0);
|
attr.map_token_fd = OPTS_GET(opts, token_fd, 0);
|
||||||
|
attr.excl_prog_hash = ptr_to_u64(OPTS_GET(opts, excl_prog_hash, NULL));
|
||||||
|
attr.excl_prog_hash_size = OPTS_GET(opts, excl_prog_hash_size, 0);
|
||||||
|
|
||||||
fd = sys_bpf_fd(BPF_MAP_CREATE, &attr, attr_sz);
|
fd = sys_bpf_fd(BPF_MAP_CREATE, &attr, attr_sz);
|
||||||
return libbpf_err_errno(fd);
|
return libbpf_err_errno(fd);
|
||||||
@@ -238,7 +240,7 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
|
|||||||
const struct bpf_insn *insns, size_t insn_cnt,
|
const struct bpf_insn *insns, size_t insn_cnt,
|
||||||
struct bpf_prog_load_opts *opts)
|
struct bpf_prog_load_opts *opts)
|
||||||
{
|
{
|
||||||
const size_t attr_sz = offsetofend(union bpf_attr, prog_token_fd);
|
const size_t attr_sz = offsetofend(union bpf_attr, keyring_id);
|
||||||
void *finfo = NULL, *linfo = NULL;
|
void *finfo = NULL, *linfo = NULL;
|
||||||
const char *func_info, *line_info;
|
const char *func_info, *line_info;
|
||||||
__u32 log_size, log_level, attach_prog_fd, attach_btf_obj_fd;
|
__u32 log_size, log_level, attach_prog_fd, attach_btf_obj_fd;
|
||||||
@@ -311,6 +313,7 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
|
|||||||
attr.line_info_cnt = OPTS_GET(opts, line_info_cnt, 0);
|
attr.line_info_cnt = OPTS_GET(opts, line_info_cnt, 0);
|
||||||
|
|
||||||
attr.fd_array = ptr_to_u64(OPTS_GET(opts, fd_array, NULL));
|
attr.fd_array = ptr_to_u64(OPTS_GET(opts, fd_array, NULL));
|
||||||
|
attr.fd_array_cnt = OPTS_GET(opts, fd_array_cnt, 0);
|
||||||
|
|
||||||
if (log_level) {
|
if (log_level) {
|
||||||
attr.log_buf = ptr_to_u64(log_buf);
|
attr.log_buf = ptr_to_u64(log_buf);
|
||||||
@@ -776,6 +779,7 @@ int bpf_link_create(int prog_fd, int target_fd,
|
|||||||
return libbpf_err(-EINVAL);
|
return libbpf_err(-EINVAL);
|
||||||
break;
|
break;
|
||||||
case BPF_TRACE_UPROBE_MULTI:
|
case BPF_TRACE_UPROBE_MULTI:
|
||||||
|
case BPF_TRACE_UPROBE_SESSION:
|
||||||
attr.link_create.uprobe_multi.flags = OPTS_GET(opts, uprobe_multi.flags, 0);
|
attr.link_create.uprobe_multi.flags = OPTS_GET(opts, uprobe_multi.flags, 0);
|
||||||
attr.link_create.uprobe_multi.cnt = OPTS_GET(opts, uprobe_multi.cnt, 0);
|
attr.link_create.uprobe_multi.cnt = OPTS_GET(opts, uprobe_multi.cnt, 0);
|
||||||
attr.link_create.uprobe_multi.path = ptr_to_u64(OPTS_GET(opts, uprobe_multi.path, 0));
|
attr.link_create.uprobe_multi.path = ptr_to_u64(OPTS_GET(opts, uprobe_multi.path, 0));
|
||||||
@@ -790,6 +794,7 @@ int bpf_link_create(int prog_fd, int target_fd,
|
|||||||
case BPF_TRACE_FENTRY:
|
case BPF_TRACE_FENTRY:
|
||||||
case BPF_TRACE_FEXIT:
|
case BPF_TRACE_FEXIT:
|
||||||
case BPF_MODIFY_RETURN:
|
case BPF_MODIFY_RETURN:
|
||||||
|
case BPF_TRACE_FSESSION:
|
||||||
case BPF_LSM_MAC:
|
case BPF_LSM_MAC:
|
||||||
attr.link_create.tracing.cookie = OPTS_GET(opts, tracing.cookie, 0);
|
attr.link_create.tracing.cookie = OPTS_GET(opts, tracing.cookie, 0);
|
||||||
if (!OPTS_ZEROED(opts, tracing))
|
if (!OPTS_ZEROED(opts, tracing))
|
||||||
@@ -835,6 +840,50 @@ int bpf_link_create(int prog_fd, int target_fd,
|
|||||||
if (!OPTS_ZEROED(opts, netkit))
|
if (!OPTS_ZEROED(opts, netkit))
|
||||||
return libbpf_err(-EINVAL);
|
return libbpf_err(-EINVAL);
|
||||||
break;
|
break;
|
||||||
|
case BPF_CGROUP_INET_INGRESS:
|
||||||
|
case BPF_CGROUP_INET_EGRESS:
|
||||||
|
case BPF_CGROUP_INET_SOCK_CREATE:
|
||||||
|
case BPF_CGROUP_INET_SOCK_RELEASE:
|
||||||
|
case BPF_CGROUP_INET4_BIND:
|
||||||
|
case BPF_CGROUP_INET6_BIND:
|
||||||
|
case BPF_CGROUP_INET4_POST_BIND:
|
||||||
|
case BPF_CGROUP_INET6_POST_BIND:
|
||||||
|
case BPF_CGROUP_INET4_CONNECT:
|
||||||
|
case BPF_CGROUP_INET6_CONNECT:
|
||||||
|
case BPF_CGROUP_UNIX_CONNECT:
|
||||||
|
case BPF_CGROUP_INET4_GETPEERNAME:
|
||||||
|
case BPF_CGROUP_INET6_GETPEERNAME:
|
||||||
|
case BPF_CGROUP_UNIX_GETPEERNAME:
|
||||||
|
case BPF_CGROUP_INET4_GETSOCKNAME:
|
||||||
|
case BPF_CGROUP_INET6_GETSOCKNAME:
|
||||||
|
case BPF_CGROUP_UNIX_GETSOCKNAME:
|
||||||
|
case BPF_CGROUP_UDP4_SENDMSG:
|
||||||
|
case BPF_CGROUP_UDP6_SENDMSG:
|
||||||
|
case BPF_CGROUP_UNIX_SENDMSG:
|
||||||
|
case BPF_CGROUP_UDP4_RECVMSG:
|
||||||
|
case BPF_CGROUP_UDP6_RECVMSG:
|
||||||
|
case BPF_CGROUP_UNIX_RECVMSG:
|
||||||
|
case BPF_CGROUP_SOCK_OPS:
|
||||||
|
case BPF_CGROUP_DEVICE:
|
||||||
|
case BPF_CGROUP_SYSCTL:
|
||||||
|
case BPF_CGROUP_GETSOCKOPT:
|
||||||
|
case BPF_CGROUP_SETSOCKOPT:
|
||||||
|
case BPF_LSM_CGROUP:
|
||||||
|
relative_fd = OPTS_GET(opts, cgroup.relative_fd, 0);
|
||||||
|
relative_id = OPTS_GET(opts, cgroup.relative_id, 0);
|
||||||
|
if (relative_fd && relative_id)
|
||||||
|
return libbpf_err(-EINVAL);
|
||||||
|
if (relative_id) {
|
||||||
|
attr.link_create.cgroup.relative_id = relative_id;
|
||||||
|
attr.link_create.flags |= BPF_F_ID;
|
||||||
|
} else {
|
||||||
|
attr.link_create.cgroup.relative_fd = relative_fd;
|
||||||
|
}
|
||||||
|
attr.link_create.cgroup.expected_revision =
|
||||||
|
OPTS_GET(opts, cgroup.expected_revision, 0);
|
||||||
|
if (!OPTS_ZEROED(opts, cgroup))
|
||||||
|
return libbpf_err(-EINVAL);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (!OPTS_ZEROED(opts, flags))
|
if (!OPTS_ZEROED(opts, flags))
|
||||||
return libbpf_err(-EINVAL);
|
return libbpf_err(-EINVAL);
|
||||||
@@ -1095,7 +1144,7 @@ int bpf_map_get_fd_by_id(__u32 id)
|
|||||||
int bpf_btf_get_fd_by_id_opts(__u32 id,
|
int bpf_btf_get_fd_by_id_opts(__u32 id,
|
||||||
const struct bpf_get_fd_by_id_opts *opts)
|
const struct bpf_get_fd_by_id_opts *opts)
|
||||||
{
|
{
|
||||||
const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
|
const size_t attr_sz = offsetofend(union bpf_attr, fd_by_id_token_fd);
|
||||||
union bpf_attr attr;
|
union bpf_attr attr;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
@@ -1105,6 +1154,7 @@ int bpf_btf_get_fd_by_id_opts(__u32 id,
|
|||||||
memset(&attr, 0, attr_sz);
|
memset(&attr, 0, attr_sz);
|
||||||
attr.btf_id = id;
|
attr.btf_id = id;
|
||||||
attr.open_flags = OPTS_GET(opts, open_flags, 0);
|
attr.open_flags = OPTS_GET(opts, open_flags, 0);
|
||||||
|
attr.fd_by_id_token_fd = OPTS_GET(opts, token_fd, 0);
|
||||||
|
|
||||||
fd = sys_bpf_fd(BPF_BTF_GET_FD_BY_ID, &attr, attr_sz);
|
fd = sys_bpf_fd(BPF_BTF_GET_FD_BY_ID, &attr, attr_sz);
|
||||||
return libbpf_err_errno(fd);
|
return libbpf_err_errno(fd);
|
||||||
@@ -1328,3 +1378,42 @@ int bpf_token_create(int bpffs_fd, struct bpf_token_create_opts *opts)
|
|||||||
fd = sys_bpf_fd(BPF_TOKEN_CREATE, &attr, attr_sz);
|
fd = sys_bpf_fd(BPF_TOKEN_CREATE, &attr, attr_sz);
|
||||||
return libbpf_err_errno(fd);
|
return libbpf_err_errno(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bpf_prog_stream_read(int prog_fd, __u32 stream_id, void *buf, __u32 buf_len,
|
||||||
|
struct bpf_prog_stream_read_opts *opts)
|
||||||
|
{
|
||||||
|
const size_t attr_sz = offsetofend(union bpf_attr, prog_stream_read);
|
||||||
|
union bpf_attr attr;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!OPTS_VALID(opts, bpf_prog_stream_read_opts))
|
||||||
|
return libbpf_err(-EINVAL);
|
||||||
|
|
||||||
|
memset(&attr, 0, attr_sz);
|
||||||
|
attr.prog_stream_read.stream_buf = ptr_to_u64(buf);
|
||||||
|
attr.prog_stream_read.stream_buf_len = buf_len;
|
||||||
|
attr.prog_stream_read.stream_id = stream_id;
|
||||||
|
attr.prog_stream_read.prog_fd = prog_fd;
|
||||||
|
|
||||||
|
err = sys_bpf(BPF_PROG_STREAM_READ_BY_FD, &attr, attr_sz);
|
||||||
|
return libbpf_err_errno(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bpf_prog_assoc_struct_ops(int prog_fd, int map_fd,
|
||||||
|
struct bpf_prog_assoc_struct_ops_opts *opts)
|
||||||
|
{
|
||||||
|
const size_t attr_sz = offsetofend(union bpf_attr, prog_assoc_struct_ops);
|
||||||
|
union bpf_attr attr;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!OPTS_VALID(opts, bpf_prog_assoc_struct_ops_opts))
|
||||||
|
return libbpf_err(-EINVAL);
|
||||||
|
|
||||||
|
memset(&attr, 0, attr_sz);
|
||||||
|
attr.prog_assoc_struct_ops.map_fd = map_fd;
|
||||||
|
attr.prog_assoc_struct_ops.prog_fd = prog_fd;
|
||||||
|
attr.prog_assoc_struct_ops.flags = OPTS_GET(opts, flags, 0);
|
||||||
|
|
||||||
|
err = sys_bpf(BPF_PROG_ASSOC_STRUCT_OPS, &attr, attr_sz);
|
||||||
|
return libbpf_err_errno(err);
|
||||||
|
}
|
||||||
|
|||||||
72
src/bpf.h
72
src/bpf.h
@@ -54,9 +54,12 @@ struct bpf_map_create_opts {
|
|||||||
__s32 value_type_btf_obj_fd;
|
__s32 value_type_btf_obj_fd;
|
||||||
|
|
||||||
__u32 token_fd;
|
__u32 token_fd;
|
||||||
|
|
||||||
|
const void *excl_prog_hash;
|
||||||
|
__u32 excl_prog_hash_size;
|
||||||
size_t :0;
|
size_t :0;
|
||||||
};
|
};
|
||||||
#define bpf_map_create_opts__last_field token_fd
|
#define bpf_map_create_opts__last_field excl_prog_hash_size
|
||||||
|
|
||||||
LIBBPF_API int bpf_map_create(enum bpf_map_type map_type,
|
LIBBPF_API int bpf_map_create(enum bpf_map_type map_type,
|
||||||
const char *map_name,
|
const char *map_name,
|
||||||
@@ -100,16 +103,19 @@ struct bpf_prog_load_opts {
|
|||||||
__u32 log_level;
|
__u32 log_level;
|
||||||
__u32 log_size;
|
__u32 log_size;
|
||||||
char *log_buf;
|
char *log_buf;
|
||||||
/* output: actual total log contents size (including termintaing zero).
|
/* output: actual total log contents size (including terminating zero).
|
||||||
* It could be both larger than original log_size (if log was
|
* It could be both larger than original log_size (if log was
|
||||||
* truncated), or smaller (if log buffer wasn't filled completely).
|
* truncated), or smaller (if log buffer wasn't filled completely).
|
||||||
* If kernel doesn't support this feature, log_size is left unchanged.
|
* If kernel doesn't support this feature, log_size is left unchanged.
|
||||||
*/
|
*/
|
||||||
__u32 log_true_size;
|
__u32 log_true_size;
|
||||||
__u32 token_fd;
|
__u32 token_fd;
|
||||||
|
|
||||||
|
/* if set, provides the length of fd_array */
|
||||||
|
__u32 fd_array_cnt;
|
||||||
size_t :0;
|
size_t :0;
|
||||||
};
|
};
|
||||||
#define bpf_prog_load_opts__last_field token_fd
|
#define bpf_prog_load_opts__last_field fd_array_cnt
|
||||||
|
|
||||||
LIBBPF_API int bpf_prog_load(enum bpf_prog_type prog_type,
|
LIBBPF_API int bpf_prog_load(enum bpf_prog_type prog_type,
|
||||||
const char *prog_name, const char *license,
|
const char *prog_name, const char *license,
|
||||||
@@ -129,7 +135,7 @@ struct bpf_btf_load_opts {
|
|||||||
char *log_buf;
|
char *log_buf;
|
||||||
__u32 log_level;
|
__u32 log_level;
|
||||||
__u32 log_size;
|
__u32 log_size;
|
||||||
/* output: actual total log contents size (including termintaing zero).
|
/* output: actual total log contents size (including terminating zero).
|
||||||
* It could be both larger than original log_size (if log was
|
* It could be both larger than original log_size (if log was
|
||||||
* truncated), or smaller (if log buffer wasn't filled completely).
|
* truncated), or smaller (if log buffer wasn't filled completely).
|
||||||
* If kernel doesn't support this feature, log_size is left unchanged.
|
* If kernel doesn't support this feature, log_size is left unchanged.
|
||||||
@@ -283,6 +289,14 @@ LIBBPF_API int bpf_map_lookup_and_delete_batch(int fd, void *in_batch,
|
|||||||
* Update spin_lock-ed map elements. This must be
|
* Update spin_lock-ed map elements. This must be
|
||||||
* specified if the map value contains a spinlock.
|
* specified if the map value contains a spinlock.
|
||||||
*
|
*
|
||||||
|
* **BPF_F_CPU**
|
||||||
|
* As for percpu maps, update value on the specified CPU. And the cpu
|
||||||
|
* info is embedded into the high 32 bits of **opts->elem_flags**.
|
||||||
|
*
|
||||||
|
* **BPF_F_ALL_CPUS**
|
||||||
|
* As for percpu maps, update value across all CPUs. This flag cannot
|
||||||
|
* be used with BPF_F_CPU at the same time.
|
||||||
|
*
|
||||||
* @param fd BPF map file descriptor
|
* @param fd BPF map file descriptor
|
||||||
* @param keys pointer to an array of *count* keys
|
* @param keys pointer to an array of *count* keys
|
||||||
* @param values pointer to an array of *count* values
|
* @param values pointer to an array of *count* values
|
||||||
@@ -435,6 +449,11 @@ struct bpf_link_create_opts {
|
|||||||
__u32 relative_id;
|
__u32 relative_id;
|
||||||
__u64 expected_revision;
|
__u64 expected_revision;
|
||||||
} netkit;
|
} netkit;
|
||||||
|
struct {
|
||||||
|
__u32 relative_fd;
|
||||||
|
__u32 relative_id;
|
||||||
|
__u64 expected_revision;
|
||||||
|
} cgroup;
|
||||||
};
|
};
|
||||||
size_t :0;
|
size_t :0;
|
||||||
};
|
};
|
||||||
@@ -484,9 +503,10 @@ LIBBPF_API int bpf_link_get_next_id(__u32 start_id, __u32 *next_id);
|
|||||||
struct bpf_get_fd_by_id_opts {
|
struct bpf_get_fd_by_id_opts {
|
||||||
size_t sz; /* size of this struct for forward/backward compatibility */
|
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||||
__u32 open_flags; /* permissions requested for the operation on fd */
|
__u32 open_flags; /* permissions requested for the operation on fd */
|
||||||
|
__u32 token_fd;
|
||||||
size_t :0;
|
size_t :0;
|
||||||
};
|
};
|
||||||
#define bpf_get_fd_by_id_opts__last_field open_flags
|
#define bpf_get_fd_by_id_opts__last_field token_fd
|
||||||
|
|
||||||
LIBBPF_API int bpf_prog_get_fd_by_id(__u32 id);
|
LIBBPF_API int bpf_prog_get_fd_by_id(__u32 id);
|
||||||
LIBBPF_API int bpf_prog_get_fd_by_id_opts(__u32 id,
|
LIBBPF_API int bpf_prog_get_fd_by_id_opts(__u32 id,
|
||||||
@@ -700,6 +720,48 @@ struct bpf_token_create_opts {
|
|||||||
LIBBPF_API int bpf_token_create(int bpffs_fd,
|
LIBBPF_API int bpf_token_create(int bpffs_fd,
|
||||||
struct bpf_token_create_opts *opts);
|
struct bpf_token_create_opts *opts);
|
||||||
|
|
||||||
|
struct bpf_prog_stream_read_opts {
|
||||||
|
size_t sz;
|
||||||
|
size_t :0;
|
||||||
|
};
|
||||||
|
#define bpf_prog_stream_read_opts__last_field sz
|
||||||
|
/**
|
||||||
|
* @brief **bpf_prog_stream_read** reads data from the BPF stream of a given BPF
|
||||||
|
* program.
|
||||||
|
*
|
||||||
|
* @param prog_fd FD for the BPF program whose BPF stream is to be read.
|
||||||
|
* @param stream_id ID of the BPF stream to be read.
|
||||||
|
* @param buf Buffer to read data into from the BPF stream.
|
||||||
|
* @param buf_len Maximum number of bytes to read from the BPF stream.
|
||||||
|
* @param opts optional options, can be NULL
|
||||||
|
*
|
||||||
|
* @return The number of bytes read, on success; negative error code, otherwise
|
||||||
|
* (errno is also set to the error code)
|
||||||
|
*/
|
||||||
|
LIBBPF_API int bpf_prog_stream_read(int prog_fd, __u32 stream_id, void *buf, __u32 buf_len,
|
||||||
|
struct bpf_prog_stream_read_opts *opts);
|
||||||
|
|
||||||
|
struct bpf_prog_assoc_struct_ops_opts {
|
||||||
|
size_t sz;
|
||||||
|
__u32 flags;
|
||||||
|
size_t :0;
|
||||||
|
};
|
||||||
|
#define bpf_prog_assoc_struct_ops_opts__last_field flags
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief **bpf_prog_assoc_struct_ops** associates a BPF program with a
|
||||||
|
* struct_ops map.
|
||||||
|
*
|
||||||
|
* @param prog_fd FD for the BPF program
|
||||||
|
* @param map_fd FD for the struct_ops map to be associated with the BPF program
|
||||||
|
* @param opts optional options, can be NULL
|
||||||
|
*
|
||||||
|
* @return 0 on success; negative error code, otherwise (errno is also set to
|
||||||
|
* the error code)
|
||||||
|
*/
|
||||||
|
LIBBPF_API int bpf_prog_assoc_struct_ops(int prog_fd, int map_fd,
|
||||||
|
struct bpf_prog_assoc_struct_ops_opts *opts);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -388,7 +388,13 @@ extern void *bpf_rdonly_cast(const void *obj, __u32 btf_id) __ksym __weak;
|
|||||||
#define ___arrow10(a, b, c, d, e, f, g, h, i, j) a->b->c->d->e->f->g->h->i->j
|
#define ___arrow10(a, b, c, d, e, f, g, h, i, j) a->b->c->d->e->f->g->h->i->j
|
||||||
#define ___arrow(...) ___apply(___arrow, ___narg(__VA_ARGS__))(__VA_ARGS__)
|
#define ___arrow(...) ___apply(___arrow, ___narg(__VA_ARGS__))(__VA_ARGS__)
|
||||||
|
|
||||||
|
#if defined(__clang__) && (__clang_major__ >= 19)
|
||||||
|
#define ___type(...) __typeof_unqual__(___arrow(__VA_ARGS__))
|
||||||
|
#elif defined(__GNUC__) && (__GNUC__ >= 14)
|
||||||
|
#define ___type(...) __typeof_unqual__(___arrow(__VA_ARGS__))
|
||||||
|
#else
|
||||||
#define ___type(...) typeof(___arrow(__VA_ARGS__))
|
#define ___type(...) typeof(___arrow(__VA_ARGS__))
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ___read(read_fn, dst, src_type, src, accessor) \
|
#define ___read(read_fn, dst, src_type, src, accessor) \
|
||||||
read_fn((void *)(dst), sizeof(*(dst)), &((src_type)(src))->accessor)
|
read_fn((void *)(dst), sizeof(*(dst)), &((src_type)(src))->accessor)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#define __BPF_GEN_INTERNAL_H
|
#define __BPF_GEN_INTERNAL_H
|
||||||
|
|
||||||
#include "bpf.h"
|
#include "bpf.h"
|
||||||
|
#include "libbpf_internal.h"
|
||||||
|
|
||||||
struct ksym_relo_desc {
|
struct ksym_relo_desc {
|
||||||
const char *name;
|
const char *name;
|
||||||
@@ -34,6 +35,7 @@ struct bpf_gen {
|
|||||||
void *data_cur;
|
void *data_cur;
|
||||||
void *insn_start;
|
void *insn_start;
|
||||||
void *insn_cur;
|
void *insn_cur;
|
||||||
|
bool swapped_endian;
|
||||||
ssize_t cleanup_label;
|
ssize_t cleanup_label;
|
||||||
__u32 nr_progs;
|
__u32 nr_progs;
|
||||||
__u32 nr_maps;
|
__u32 nr_maps;
|
||||||
@@ -49,6 +51,7 @@ struct bpf_gen {
|
|||||||
__u32 nr_ksyms;
|
__u32 nr_ksyms;
|
||||||
int fd_array;
|
int fd_array;
|
||||||
int nr_fd_array;
|
int nr_fd_array;
|
||||||
|
int hash_insn_offset[SHA256_DWORD_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps);
|
void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps);
|
||||||
|
|||||||
@@ -44,6 +44,14 @@ struct bpf_dynptr;
|
|||||||
struct iphdr;
|
struct iphdr;
|
||||||
struct ipv6hdr;
|
struct ipv6hdr;
|
||||||
|
|
||||||
|
#ifndef __bpf_fastcall
|
||||||
|
#if __has_attribute(bpf_fastcall)
|
||||||
|
#define __bpf_fastcall __attribute__((bpf_fastcall))
|
||||||
|
#else
|
||||||
|
#define __bpf_fastcall
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bpf_map_lookup_elem
|
* bpf_map_lookup_elem
|
||||||
*
|
*
|
||||||
@@ -203,17 +211,21 @@ static __u32 (* const bpf_get_prandom_u32)(void) = (void *) 7;
|
|||||||
* Returns
|
* Returns
|
||||||
* The SMP id of the processor running the program.
|
* The SMP id of the processor running the program.
|
||||||
*/
|
*/
|
||||||
static __u32 (* const bpf_get_smp_processor_id)(void) = (void *) 8;
|
static __bpf_fastcall __u32 (* const bpf_get_smp_processor_id)(void) = (void *) 8;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bpf_skb_store_bytes
|
* bpf_skb_store_bytes
|
||||||
*
|
*
|
||||||
* Store *len* bytes from address *from* into the packet
|
* Store *len* bytes from address *from* into the packet
|
||||||
* associated to *skb*, at *offset*. *flags* are a combination of
|
* associated to *skb*, at *offset*. The *flags* are a combination
|
||||||
* **BPF_F_RECOMPUTE_CSUM** (automatically recompute the
|
* of the following values:
|
||||||
* checksum for the packet after storing the bytes) and
|
*
|
||||||
* **BPF_F_INVALIDATE_HASH** (set *skb*\ **->hash**, *skb*\
|
* **BPF_F_RECOMPUTE_CSUM**
|
||||||
* **->swhash** and *skb*\ **->l4hash** to 0).
|
* Automatically update *skb*\ **->csum** after storing the
|
||||||
|
* bytes.
|
||||||
|
* **BPF_F_INVALIDATE_HASH**
|
||||||
|
* Set *skb*\ **->hash**, *skb*\ **->swhash** and *skb*\
|
||||||
|
* **->l4hash** to 0.
|
||||||
*
|
*
|
||||||
* A call to this helper is susceptible to change the underlying
|
* A call to this helper is susceptible to change the underlying
|
||||||
* packet buffer. Therefore, at load time, all checks on pointers
|
* packet buffer. Therefore, at load time, all checks on pointers
|
||||||
@@ -273,7 +285,8 @@ static long (* const bpf_l3_csum_replace)(struct __sk_buff *skb, __u32 offset, _
|
|||||||
* untouched (unless **BPF_F_MARK_ENFORCE** is added as well), and
|
* untouched (unless **BPF_F_MARK_ENFORCE** is added as well), and
|
||||||
* for updates resulting in a null checksum the value is set to
|
* for updates resulting in a null checksum the value is set to
|
||||||
* **CSUM_MANGLED_0** instead. Flag **BPF_F_PSEUDO_HDR** indicates
|
* **CSUM_MANGLED_0** instead. Flag **BPF_F_PSEUDO_HDR** indicates
|
||||||
* the checksum is to be computed against a pseudo-header.
|
* that the modified header field is part of the pseudo-header.
|
||||||
|
* Flag **BPF_F_IPV6** should be set for IPv6 packets.
|
||||||
*
|
*
|
||||||
* This helper works in combination with **bpf_csum_diff**\ (),
|
* This helper works in combination with **bpf_csum_diff**\ (),
|
||||||
* which does not update the checksum in-place, but offers more
|
* which does not update the checksum in-place, but offers more
|
||||||
@@ -676,7 +689,7 @@ static __u32 (* const bpf_get_route_realm)(struct __sk_buff *skb) = (void *) 24;
|
|||||||
* into it. An example is available in file
|
* into it. An example is available in file
|
||||||
* *samples/bpf/trace_output_user.c* in the Linux kernel source
|
* *samples/bpf/trace_output_user.c* in the Linux kernel source
|
||||||
* tree (the eBPF program counterpart is in
|
* tree (the eBPF program counterpart is in
|
||||||
* *samples/bpf/trace_output_kern.c*).
|
* *samples/bpf/trace_output.bpf.c*).
|
||||||
*
|
*
|
||||||
* **bpf_perf_event_output**\ () achieves better performance
|
* **bpf_perf_event_output**\ () achieves better performance
|
||||||
* than **bpf_trace_printk**\ () for sharing data with user
|
* than **bpf_trace_printk**\ () for sharing data with user
|
||||||
@@ -1224,7 +1237,7 @@ static long (* const bpf_set_hash)(struct __sk_buff *skb, __u32 hash) = (void *)
|
|||||||
* **TCP_SYNCNT**, **TCP_USER_TIMEOUT**, **TCP_NOTSENT_LOWAT**,
|
* **TCP_SYNCNT**, **TCP_USER_TIMEOUT**, **TCP_NOTSENT_LOWAT**,
|
||||||
* **TCP_NODELAY**, **TCP_MAXSEG**, **TCP_WINDOW_CLAMP**,
|
* **TCP_NODELAY**, **TCP_MAXSEG**, **TCP_WINDOW_CLAMP**,
|
||||||
* **TCP_THIN_LINEAR_TIMEOUTS**, **TCP_BPF_DELACK_MAX**,
|
* **TCP_THIN_LINEAR_TIMEOUTS**, **TCP_BPF_DELACK_MAX**,
|
||||||
* **TCP_BPF_RTO_MIN**.
|
* **TCP_BPF_RTO_MIN**, **TCP_BPF_SOCK_OPS_CB_FLAGS**.
|
||||||
* * **IPPROTO_IP**, which supports *optname* **IP_TOS**.
|
* * **IPPROTO_IP**, which supports *optname* **IP_TOS**.
|
||||||
* * **IPPROTO_IPV6**, which supports the following *optname*\ s:
|
* * **IPPROTO_IPV6**, which supports the following *optname*\ s:
|
||||||
* **IPV6_TCLASS**, **IPV6_AUTOFLOWLABEL**.
|
* **IPV6_TCLASS**, **IPV6_AUTOFLOWLABEL**.
|
||||||
@@ -1511,10 +1524,6 @@ static long (* const bpf_getsockopt)(void *bpf_socket, int level, int optname, v
|
|||||||
* option, and in this case it only works on functions tagged with
|
* option, and in this case it only works on functions tagged with
|
||||||
* **ALLOW_ERROR_INJECTION** in the kernel code.
|
* **ALLOW_ERROR_INJECTION** in the kernel code.
|
||||||
*
|
*
|
||||||
* Also, the helper is only available for the architectures having
|
|
||||||
* the CONFIG_FUNCTION_ERROR_INJECTION option. As of this writing,
|
|
||||||
* x86 architecture is the only one to support this feature.
|
|
||||||
*
|
|
||||||
* Returns
|
* Returns
|
||||||
* 0
|
* 0
|
||||||
*/
|
*/
|
||||||
@@ -3549,7 +3558,7 @@ static int (* const bpf_inode_storage_delete)(void *map, void *inode) = (void *)
|
|||||||
* including the trailing NUL character. On error, a negative
|
* including the trailing NUL character. On error, a negative
|
||||||
* value.
|
* value.
|
||||||
*/
|
*/
|
||||||
static long (* const bpf_d_path)(struct path *path, char *buf, __u32 sz) = (void *) 147;
|
static long (* const bpf_d_path)(const struct path *path, char *buf, __u32 sz) = (void *) 147;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bpf_copy_from_user
|
* bpf_copy_from_user
|
||||||
@@ -3698,6 +3707,9 @@ static void *(* const bpf_this_cpu_ptr)(const void *percpu_ptr) = (void *) 154;
|
|||||||
* the netns switch takes place from ingress to ingress without
|
* the netns switch takes place from ingress to ingress without
|
||||||
* going through the CPU's backlog queue.
|
* going through the CPU's backlog queue.
|
||||||
*
|
*
|
||||||
|
* *skb*\ **->mark** and *skb*\ **->tstamp** are not cleared during
|
||||||
|
* the netns switch.
|
||||||
|
*
|
||||||
* The *flags* argument is reserved and must be 0. The helper is
|
* The *flags* argument is reserved and must be 0. The helper is
|
||||||
* currently only supported for tc BPF program types at the
|
* currently only supported for tc BPF program types at the
|
||||||
* ingress hook and for veth and netkit target device types. The
|
* ingress hook and for veth and netkit target device types. The
|
||||||
@@ -4220,7 +4232,7 @@ static long (* const bpf_find_vma)(struct task_struct *task, __u64 addr, void *c
|
|||||||
* Currently, the **flags** must be 0. Currently, nr_loops is
|
* Currently, the **flags** must be 0. Currently, nr_loops is
|
||||||
* limited to 1 << 23 (~8 million) loops.
|
* limited to 1 << 23 (~8 million) loops.
|
||||||
*
|
*
|
||||||
* long (\*callback_fn)(u32 index, void \*ctx);
|
* long (\*callback_fn)(u64 index, void \*ctx);
|
||||||
*
|
*
|
||||||
* where **index** is the current index in the loop. The index
|
* where **index** is the current index in the loop. The index
|
||||||
* is zero-indexed.
|
* is zero-indexed.
|
||||||
@@ -4424,9 +4436,10 @@ static long (* const bpf_ima_file_hash)(struct file *file, void *dst, __u32 size
|
|||||||
/*
|
/*
|
||||||
* bpf_kptr_xchg
|
* bpf_kptr_xchg
|
||||||
*
|
*
|
||||||
* Exchange kptr at pointer *map_value* with *ptr*, and return the
|
* Exchange kptr at pointer *dst* with *ptr*, and return the old value.
|
||||||
* old value. *ptr* can be NULL, otherwise it must be a referenced
|
* *dst* can be map value or local kptr. *ptr* can be NULL, otherwise
|
||||||
* pointer which will be released when this helper is called.
|
* it must be a referenced pointer which will be released when this helper
|
||||||
|
* is called.
|
||||||
*
|
*
|
||||||
* Returns
|
* Returns
|
||||||
* The old value of kptr (which can be NULL). The returned pointer
|
* The old value of kptr (which can be NULL). The returned pointer
|
||||||
@@ -4434,7 +4447,7 @@ static long (* const bpf_ima_file_hash)(struct file *file, void *dst, __u32 size
|
|||||||
* corresponding release function, or moved into a BPF map before
|
* corresponding release function, or moved into a BPF map before
|
||||||
* program exit.
|
* program exit.
|
||||||
*/
|
*/
|
||||||
static void *(* const bpf_kptr_xchg)(void *map_value, void *ptr) = (void *) 194;
|
static void *(* const bpf_kptr_xchg)(void *dst, void *ptr) = (void *) 194;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bpf_map_lookup_percpu_elem
|
* bpf_map_lookup_percpu_elem
|
||||||
@@ -4471,7 +4484,7 @@ static struct mptcp_sock *(* const bpf_skc_to_mptcp_sock)(void *sk) = (void *) 1
|
|||||||
* 0 on success, -E2BIG if the size exceeds DYNPTR_MAX_SIZE,
|
* 0 on success, -E2BIG if the size exceeds DYNPTR_MAX_SIZE,
|
||||||
* -EINVAL if flags is not 0.
|
* -EINVAL if flags is not 0.
|
||||||
*/
|
*/
|
||||||
static long (* const bpf_dynptr_from_mem)(void *data, __u32 size, __u64 flags, struct bpf_dynptr *ptr) = (void *) 197;
|
static long (* const bpf_dynptr_from_mem)(void *data, __u64 size, __u64 flags, struct bpf_dynptr *ptr) = (void *) 197;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bpf_ringbuf_reserve_dynptr
|
* bpf_ringbuf_reserve_dynptr
|
||||||
@@ -4529,7 +4542,7 @@ static void (* const bpf_ringbuf_discard_dynptr)(struct bpf_dynptr *ptr, __u64 f
|
|||||||
* of *src*'s data, -EINVAL if *src* is an invalid dynptr or if
|
* of *src*'s data, -EINVAL if *src* is an invalid dynptr or if
|
||||||
* *flags* is not 0.
|
* *flags* is not 0.
|
||||||
*/
|
*/
|
||||||
static long (* const bpf_dynptr_read)(void *dst, __u32 len, const struct bpf_dynptr *src, __u32 offset, __u64 flags) = (void *) 201;
|
static long (* const bpf_dynptr_read)(void *dst, __u64 len, const struct bpf_dynptr *src, __u64 offset, __u64 flags) = (void *) 201;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bpf_dynptr_write
|
* bpf_dynptr_write
|
||||||
@@ -4554,7 +4567,7 @@ static long (* const bpf_dynptr_read)(void *dst, __u32 len, const struct bpf_dyn
|
|||||||
* is a read-only dynptr or if *flags* is not correct. For skb-type dynptrs,
|
* is a read-only dynptr or if *flags* is not correct. For skb-type dynptrs,
|
||||||
* other errors correspond to errors returned by **bpf_skb_store_bytes**\ ().
|
* other errors correspond to errors returned by **bpf_skb_store_bytes**\ ().
|
||||||
*/
|
*/
|
||||||
static long (* const bpf_dynptr_write)(const struct bpf_dynptr *dst, __u32 offset, void *src, __u32 len, __u64 flags) = (void *) 202;
|
static long (* const bpf_dynptr_write)(const struct bpf_dynptr *dst, __u64 offset, void *src, __u64 len, __u64 flags) = (void *) 202;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bpf_dynptr_data
|
* bpf_dynptr_data
|
||||||
@@ -4572,7 +4585,7 @@ static long (* const bpf_dynptr_write)(const struct bpf_dynptr *dst, __u32 offse
|
|||||||
* read-only, if the dynptr is invalid, or if the offset and length
|
* read-only, if the dynptr is invalid, or if the offset and length
|
||||||
* is out of bounds.
|
* is out of bounds.
|
||||||
*/
|
*/
|
||||||
static void *(* const bpf_dynptr_data)(const struct bpf_dynptr *ptr, __u32 offset, __u32 len) = (void *) 203;
|
static void *(* const bpf_dynptr_data)(const struct bpf_dynptr *ptr, __u64 offset, __u64 len) = (void *) 203;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bpf_tcp_raw_gen_syncookie_ipv4
|
* bpf_tcp_raw_gen_syncookie_ipv4
|
||||||
|
|||||||
@@ -15,6 +15,14 @@
|
|||||||
#define __array(name, val) typeof(val) *name[]
|
#define __array(name, val) typeof(val) *name[]
|
||||||
#define __ulong(name, val) enum { ___bpf_concat(__unique_value, __COUNTER__) = val } name
|
#define __ulong(name, val) enum { ___bpf_concat(__unique_value, __COUNTER__) = val } name
|
||||||
|
|
||||||
|
#ifndef likely
|
||||||
|
#define likely(x) (__builtin_expect(!!(x), 1))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef unlikely
|
||||||
|
#define unlikely(x) (__builtin_expect(!!(x), 0))
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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
|
||||||
@@ -185,6 +193,7 @@ enum libbpf_tristate {
|
|||||||
#define __kptr_untrusted __attribute__((btf_type_tag("kptr_untrusted")))
|
#define __kptr_untrusted __attribute__((btf_type_tag("kptr_untrusted")))
|
||||||
#define __kptr __attribute__((btf_type_tag("kptr")))
|
#define __kptr __attribute__((btf_type_tag("kptr")))
|
||||||
#define __percpu_kptr __attribute__((btf_type_tag("percpu_kptr")))
|
#define __percpu_kptr __attribute__((btf_type_tag("percpu_kptr")))
|
||||||
|
#define __uptr __attribute__((btf_type_tag("uptr")))
|
||||||
|
|
||||||
#if defined (__clang__)
|
#if defined (__clang__)
|
||||||
#define bpf_ksym_exists(sym) ({ \
|
#define bpf_ksym_exists(sym) ({ \
|
||||||
@@ -206,6 +215,7 @@ enum libbpf_tristate {
|
|||||||
#define __arg_nonnull __attribute((btf_decl_tag("arg:nonnull")))
|
#define __arg_nonnull __attribute((btf_decl_tag("arg:nonnull")))
|
||||||
#define __arg_nullable __attribute((btf_decl_tag("arg:nullable")))
|
#define __arg_nullable __attribute((btf_decl_tag("arg:nullable")))
|
||||||
#define __arg_trusted __attribute((btf_decl_tag("arg:trusted")))
|
#define __arg_trusted __attribute((btf_decl_tag("arg:trusted")))
|
||||||
|
#define __arg_untrusted __attribute((btf_decl_tag("arg:untrusted")))
|
||||||
#define __arg_arena __attribute((btf_decl_tag("arg:arena")))
|
#define __arg_arena __attribute((btf_decl_tag("arg:arena")))
|
||||||
|
|
||||||
#ifndef ___bpf_concat
|
#ifndef ___bpf_concat
|
||||||
@@ -305,6 +315,22 @@ enum libbpf_tristate {
|
|||||||
___param, sizeof(___param)); \
|
___param, sizeof(___param)); \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
extern int bpf_stream_vprintk(int stream_id, const char *fmt__str, const void *args,
|
||||||
|
__u32 len__sz) __weak __ksym;
|
||||||
|
|
||||||
|
#define bpf_stream_printk(stream_id, 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_stream_vprintk(stream_id, ___fmt, ___param, sizeof(___param)); \
|
||||||
|
})
|
||||||
|
|
||||||
/* Use __bpf_printk when bpf_printk call has 3 or fewer fmt args
|
/* Use __bpf_printk when bpf_printk call has 3 or fewer fmt args
|
||||||
* Otherwise use __bpf_vprintk
|
* Otherwise use __bpf_vprintk
|
||||||
*/
|
*/
|
||||||
@@ -341,7 +367,7 @@ extern void bpf_iter_num_destroy(struct bpf_iter_num *it) __weak __ksym;
|
|||||||
* I.e., it looks almost like high-level for each loop in other languages,
|
* I.e., it looks almost like high-level for each loop in other languages,
|
||||||
* supports continue/break, and is verifiable by BPF verifier.
|
* supports continue/break, and is verifiable by BPF verifier.
|
||||||
*
|
*
|
||||||
* For iterating integers, the difference betwen bpf_for_each(num, i, N, M)
|
* For iterating integers, the difference between bpf_for_each(num, i, N, M)
|
||||||
* and bpf_for(i, N, M) is in that bpf_for() provides additional proof to
|
* and bpf_for(i, N, M) is in that bpf_for() provides additional proof to
|
||||||
* verifier that i is in [N, M) range, and in bpf_for_each() case i is `int
|
* verifier that i is in [N, M) range, and in bpf_for_each() case i is `int
|
||||||
* *`, not just `int`. So for integers bpf_for() is more convenient.
|
* *`, not just `int`. So for integers bpf_for() is more convenient.
|
||||||
|
|||||||
@@ -163,7 +163,7 @@
|
|||||||
|
|
||||||
struct pt_regs___s390 {
|
struct pt_regs___s390 {
|
||||||
unsigned long orig_gpr2;
|
unsigned long orig_gpr2;
|
||||||
};
|
} __attribute__((preserve_access_index));
|
||||||
|
|
||||||
/* s390 provides user_pt_regs instead of struct pt_regs to userspace */
|
/* s390 provides user_pt_regs instead of struct pt_regs to userspace */
|
||||||
#define __PT_REGS_CAST(x) ((const user_pt_regs *)(x))
|
#define __PT_REGS_CAST(x) ((const user_pt_regs *)(x))
|
||||||
@@ -179,7 +179,7 @@ struct pt_regs___s390 {
|
|||||||
#define __PT_PARM4_SYSCALL_REG __PT_PARM4_REG
|
#define __PT_PARM4_SYSCALL_REG __PT_PARM4_REG
|
||||||
#define __PT_PARM5_SYSCALL_REG __PT_PARM5_REG
|
#define __PT_PARM5_SYSCALL_REG __PT_PARM5_REG
|
||||||
#define __PT_PARM6_SYSCALL_REG gprs[7]
|
#define __PT_PARM6_SYSCALL_REG gprs[7]
|
||||||
#define PT_REGS_PARM1_SYSCALL(x) PT_REGS_PARM1_CORE_SYSCALL(x)
|
#define PT_REGS_PARM1_SYSCALL(x) (((const struct pt_regs___s390 *)(x))->__PT_PARM1_SYSCALL_REG)
|
||||||
#define PT_REGS_PARM1_CORE_SYSCALL(x) \
|
#define PT_REGS_PARM1_CORE_SYSCALL(x) \
|
||||||
BPF_CORE_READ((const struct pt_regs___s390 *)(x), __PT_PARM1_SYSCALL_REG)
|
BPF_CORE_READ((const struct pt_regs___s390 *)(x), __PT_PARM1_SYSCALL_REG)
|
||||||
|
|
||||||
@@ -222,7 +222,7 @@ struct pt_regs___s390 {
|
|||||||
|
|
||||||
struct pt_regs___arm64 {
|
struct pt_regs___arm64 {
|
||||||
unsigned long orig_x0;
|
unsigned long orig_x0;
|
||||||
};
|
} __attribute__((preserve_access_index));
|
||||||
|
|
||||||
/* arm64 provides struct user_pt_regs instead of struct pt_regs to userspace */
|
/* arm64 provides struct user_pt_regs instead of struct pt_regs to userspace */
|
||||||
#define __PT_REGS_CAST(x) ((const struct user_pt_regs *)(x))
|
#define __PT_REGS_CAST(x) ((const struct user_pt_regs *)(x))
|
||||||
@@ -241,7 +241,7 @@ struct pt_regs___arm64 {
|
|||||||
#define __PT_PARM4_SYSCALL_REG __PT_PARM4_REG
|
#define __PT_PARM4_SYSCALL_REG __PT_PARM4_REG
|
||||||
#define __PT_PARM5_SYSCALL_REG __PT_PARM5_REG
|
#define __PT_PARM5_SYSCALL_REG __PT_PARM5_REG
|
||||||
#define __PT_PARM6_SYSCALL_REG __PT_PARM6_REG
|
#define __PT_PARM6_SYSCALL_REG __PT_PARM6_REG
|
||||||
#define PT_REGS_PARM1_SYSCALL(x) PT_REGS_PARM1_CORE_SYSCALL(x)
|
#define PT_REGS_PARM1_SYSCALL(x) (((const struct pt_regs___arm64 *)(x))->__PT_PARM1_SYSCALL_REG)
|
||||||
#define PT_REGS_PARM1_CORE_SYSCALL(x) \
|
#define PT_REGS_PARM1_CORE_SYSCALL(x) \
|
||||||
BPF_CORE_READ((const struct pt_regs___arm64 *)(x), __PT_PARM1_SYSCALL_REG)
|
BPF_CORE_READ((const struct pt_regs___arm64 *)(x), __PT_PARM1_SYSCALL_REG)
|
||||||
|
|
||||||
@@ -311,7 +311,7 @@ struct pt_regs___arm64 {
|
|||||||
#define __PT_RET_REG regs[31]
|
#define __PT_RET_REG regs[31]
|
||||||
#define __PT_FP_REG __unsupported__
|
#define __PT_FP_REG __unsupported__
|
||||||
#define __PT_RC_REG gpr[3]
|
#define __PT_RC_REG gpr[3]
|
||||||
#define __PT_SP_REG sp
|
#define __PT_SP_REG gpr[1]
|
||||||
#define __PT_IP_REG nip
|
#define __PT_IP_REG nip
|
||||||
|
|
||||||
#elif defined(bpf_target_sparc)
|
#elif defined(bpf_target_sparc)
|
||||||
@@ -351,6 +351,10 @@ struct pt_regs___arm64 {
|
|||||||
* https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#risc-v-calling-conventions
|
* https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#risc-v-calling-conventions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct pt_regs___riscv {
|
||||||
|
unsigned long orig_a0;
|
||||||
|
} __attribute__((preserve_access_index));
|
||||||
|
|
||||||
/* riscv provides struct user_regs_struct instead of struct pt_regs to userspace */
|
/* riscv provides struct user_regs_struct instead of struct pt_regs to userspace */
|
||||||
#define __PT_REGS_CAST(x) ((const struct user_regs_struct *)(x))
|
#define __PT_REGS_CAST(x) ((const struct user_regs_struct *)(x))
|
||||||
#define __PT_PARM1_REG a0
|
#define __PT_PARM1_REG a0
|
||||||
@@ -362,12 +366,15 @@ struct pt_regs___arm64 {
|
|||||||
#define __PT_PARM7_REG a6
|
#define __PT_PARM7_REG a6
|
||||||
#define __PT_PARM8_REG a7
|
#define __PT_PARM8_REG a7
|
||||||
|
|
||||||
#define __PT_PARM1_SYSCALL_REG __PT_PARM1_REG
|
#define __PT_PARM1_SYSCALL_REG orig_a0
|
||||||
#define __PT_PARM2_SYSCALL_REG __PT_PARM2_REG
|
#define __PT_PARM2_SYSCALL_REG __PT_PARM2_REG
|
||||||
#define __PT_PARM3_SYSCALL_REG __PT_PARM3_REG
|
#define __PT_PARM3_SYSCALL_REG __PT_PARM3_REG
|
||||||
#define __PT_PARM4_SYSCALL_REG __PT_PARM4_REG
|
#define __PT_PARM4_SYSCALL_REG __PT_PARM4_REG
|
||||||
#define __PT_PARM5_SYSCALL_REG __PT_PARM5_REG
|
#define __PT_PARM5_SYSCALL_REG __PT_PARM5_REG
|
||||||
#define __PT_PARM6_SYSCALL_REG __PT_PARM6_REG
|
#define __PT_PARM6_SYSCALL_REG __PT_PARM6_REG
|
||||||
|
#define PT_REGS_PARM1_SYSCALL(x) (((const struct pt_regs___riscv *)(x))->__PT_PARM1_SYSCALL_REG)
|
||||||
|
#define PT_REGS_PARM1_CORE_SYSCALL(x) \
|
||||||
|
BPF_CORE_READ((const struct pt_regs___riscv *)(x), __PT_PARM1_SYSCALL_REG)
|
||||||
|
|
||||||
#define __PT_RET_REG ra
|
#define __PT_RET_REG ra
|
||||||
#define __PT_FP_REG s0
|
#define __PT_FP_REG s0
|
||||||
@@ -473,7 +480,7 @@ struct pt_regs;
|
|||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* Similarly, syscall-specific conventions might differ between function call
|
* Similarly, syscall-specific conventions might differ between function call
|
||||||
* conventions within each architecutre. All supported architectures pass
|
* conventions within each architecture. All supported architectures pass
|
||||||
* either 6 or 7 syscall arguments in registers.
|
* either 6 or 7 syscall arguments in registers.
|
||||||
*
|
*
|
||||||
* See syscall(2) manpage for succinct table with information on each arch.
|
* See syscall(2) manpage for succinct table with information on each arch.
|
||||||
@@ -515,7 +522,7 @@ struct pt_regs;
|
|||||||
#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = (ctx)->link; })
|
#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = (ctx)->link; })
|
||||||
#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_sparc)
|
#elif defined(bpf_target_sparc) || defined(bpf_target_arm64)
|
||||||
|
|
||||||
#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
|
||||||
@@ -651,7 +658,7 @@ struct pt_regs;
|
|||||||
* BPF_PROG is a convenience wrapper for generic tp_btf/fentry/fexit and
|
* BPF_PROG is a convenience wrapper for generic tp_btf/fentry/fexit and
|
||||||
* similar kinds of BPF programs, that accept input arguments as a single
|
* similar kinds of BPF programs, that accept input arguments as a single
|
||||||
* pointer to untyped u64 array, where each u64 can actually be a typed
|
* pointer to untyped u64 array, where each u64 can actually be a typed
|
||||||
* pointer or integer of different size. Instead of requring user to write
|
* pointer or integer of different size. Instead of requiring user to write
|
||||||
* manual casts and work with array elements by index, BPF_PROG macro
|
* manual casts and work with array elements by index, BPF_PROG macro
|
||||||
* allows user to declare a list of named and typed input arguments in the
|
* allows user to declare a list of named and typed input arguments in the
|
||||||
* same syntax as for normal C function. All the casting is hidden and
|
* same syntax as for normal C function. All the casting is hidden and
|
||||||
@@ -801,7 +808,7 @@ struct pt_regs;
|
|||||||
* tp_btf/fentry/fexit BPF programs. It hides the underlying platform-specific
|
* tp_btf/fentry/fexit BPF programs. It hides the underlying platform-specific
|
||||||
* low-level way of getting kprobe input arguments from struct pt_regs, and
|
* low-level way of getting kprobe input arguments from struct pt_regs, and
|
||||||
* provides a familiar typed and named function arguments syntax and
|
* provides a familiar typed and named function arguments syntax and
|
||||||
* semantics of accessing kprobe input paremeters.
|
* semantics of accessing kprobe input parameters.
|
||||||
*
|
*
|
||||||
* Original struct pt_regs* context is preserved as 'ctx' argument. This might
|
* Original struct pt_regs* context is preserved as 'ctx' argument. This might
|
||||||
* be necessary when using BPF helpers like bpf_perf_event_output().
|
* be necessary when using BPF helpers like bpf_perf_event_output().
|
||||||
|
|||||||
61
src/btf.h
61
src/btf.h
@@ -94,6 +94,7 @@ LIBBPF_API struct btf *btf__new_empty(void);
|
|||||||
* @brief **btf__new_empty_split()** creates an unpopulated BTF object from an
|
* @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
|
* ELF BTF section except with a base BTF on top of which split BTF should be
|
||||||
* based
|
* based
|
||||||
|
* @param base_btf base BTF object
|
||||||
* @return new BTF object instance which has to be eventually freed with
|
* @return new BTF object instance which has to be eventually freed with
|
||||||
* **btf__free()**
|
* **btf__free()**
|
||||||
*
|
*
|
||||||
@@ -115,6 +116,10 @@ LIBBPF_API struct btf *btf__new_empty_split(struct btf *base_btf);
|
|||||||
* When that split BTF is loaded against a (possibly changed) base, this
|
* When that split BTF is loaded against a (possibly changed) base, this
|
||||||
* distilled base BTF will help update references to that (possibly changed)
|
* distilled base BTF will help update references to that (possibly changed)
|
||||||
* base BTF.
|
* base BTF.
|
||||||
|
* @param src_btf source split BTF object
|
||||||
|
* @param new_base_btf pointer to where the new base BTF object pointer will be stored
|
||||||
|
* @param new_split_btf pointer to where the new split BTF object pointer will be stored
|
||||||
|
* @return 0 on success; negative error code, otherwise
|
||||||
*
|
*
|
||||||
* Both the new split and its associated new base BTF must be freed by
|
* Both the new split and its associated new base BTF must be freed by
|
||||||
* the caller.
|
* the caller.
|
||||||
@@ -167,6 +172,9 @@ LIBBPF_API const char *btf__str_by_offset(const struct btf *btf, __u32 offset);
|
|||||||
LIBBPF_API struct btf_ext *btf_ext__new(const __u8 *data, __u32 size);
|
LIBBPF_API struct btf_ext *btf_ext__new(const __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__raw_data(const struct btf_ext *btf_ext, __u32 *size);
|
LIBBPF_API const void *btf_ext__raw_data(const struct btf_ext *btf_ext, __u32 *size);
|
||||||
|
LIBBPF_API enum btf_endianness btf_ext__endianness(const struct btf_ext *btf_ext);
|
||||||
|
LIBBPF_API int btf_ext__set_endianness(struct btf_ext *btf_ext,
|
||||||
|
enum btf_endianness endian);
|
||||||
|
|
||||||
LIBBPF_API int btf__find_str(struct btf *btf, const char *s);
|
LIBBPF_API int btf__find_str(struct btf *btf, const char *s);
|
||||||
LIBBPF_API int btf__add_str(struct btf *btf, const char *s);
|
LIBBPF_API int btf__add_str(struct btf *btf, const char *s);
|
||||||
@@ -224,6 +232,7 @@ 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_const(struct btf *btf, int ref_type_id);
|
||||||
LIBBPF_API int btf__add_restrict(struct btf *btf, int ref_type_id);
|
LIBBPF_API int btf__add_restrict(struct btf *btf, int ref_type_id);
|
||||||
LIBBPF_API int btf__add_type_tag(struct btf *btf, const char *value, int ref_type_id);
|
LIBBPF_API int btf__add_type_tag(struct btf *btf, const char *value, int ref_type_id);
|
||||||
|
LIBBPF_API int btf__add_type_attr(struct btf *btf, const char *value, int ref_type_id);
|
||||||
|
|
||||||
/* func and func_proto construction APIs */
|
/* func and func_proto construction APIs */
|
||||||
LIBBPF_API int btf__add_func(struct btf *btf, const char *name,
|
LIBBPF_API int btf__add_func(struct btf *btf, const char *name,
|
||||||
@@ -240,6 +249,8 @@ LIBBPF_API int btf__add_datasec_var_info(struct btf *btf, int var_type_id,
|
|||||||
/* tag construction API */
|
/* tag construction API */
|
||||||
LIBBPF_API int btf__add_decl_tag(struct btf *btf, const char *value, int ref_type_id,
|
LIBBPF_API int btf__add_decl_tag(struct btf *btf, const char *value, int ref_type_id,
|
||||||
int component_idx);
|
int component_idx);
|
||||||
|
LIBBPF_API int btf__add_decl_attr(struct btf *btf, const char *value, int ref_type_id,
|
||||||
|
int component_idx);
|
||||||
|
|
||||||
struct btf_dedup_opts {
|
struct btf_dedup_opts {
|
||||||
size_t sz;
|
size_t sz;
|
||||||
@@ -258,6 +269,9 @@ LIBBPF_API int btf__dedup(struct btf *btf, const struct btf_dedup_opts *opts);
|
|||||||
* to base BTF kinds, and verify those references are compatible with
|
* to base BTF kinds, and verify those references are compatible with
|
||||||
* *base_btf*; if they are, *btf* is adjusted such that is re-parented to
|
* *base_btf*; if they are, *btf* is adjusted such that is re-parented to
|
||||||
* *base_btf* and type ids and strings are adjusted to accommodate this.
|
* *base_btf* and type ids and strings are adjusted to accommodate this.
|
||||||
|
* @param btf split BTF object to relocate
|
||||||
|
* @param base_btf base BTF object
|
||||||
|
* @return 0 on success; negative error code, otherwise
|
||||||
*
|
*
|
||||||
* If successful, 0 is returned and **btf** now has **base_btf** as its
|
* If successful, 0 is returned and **btf** now has **base_btf** as its
|
||||||
* base.
|
* base.
|
||||||
@@ -267,6 +281,48 @@ LIBBPF_API int btf__dedup(struct btf *btf, const struct btf_dedup_opts *opts);
|
|||||||
*/
|
*/
|
||||||
LIBBPF_API int btf__relocate(struct btf *btf, const struct btf *base_btf);
|
LIBBPF_API int btf__relocate(struct btf *btf, const struct btf *base_btf);
|
||||||
|
|
||||||
|
struct btf_permute_opts {
|
||||||
|
size_t sz;
|
||||||
|
/* optional .BTF.ext info along the main BTF info */
|
||||||
|
struct btf_ext *btf_ext;
|
||||||
|
size_t :0;
|
||||||
|
};
|
||||||
|
#define btf_permute_opts__last_field btf_ext
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief **btf__permute()** rearranges BTF types in-place according to a specified ID mapping
|
||||||
|
* @param btf BTF object to permute
|
||||||
|
* @param id_map Array mapping original type IDs to new IDs
|
||||||
|
* @param id_map_cnt Number of elements in @id_map
|
||||||
|
* @param opts Optional parameters, including BTF extension data for reference updates
|
||||||
|
* @return 0 on success, negative error code on failure
|
||||||
|
*
|
||||||
|
* **btf__permute()** reorders BTF types based on the provided @id_map array,
|
||||||
|
* updating all internal type references to maintain consistency. The function
|
||||||
|
* operates in-place, modifying the BTF object directly.
|
||||||
|
*
|
||||||
|
* For **base BTF**:
|
||||||
|
* - @id_map must include all types from ID 0 to `btf__type_cnt(btf) - 1`
|
||||||
|
* - @id_map_cnt must be `btf__type_cnt(btf)`
|
||||||
|
* - Mapping is defined as `id_map[original_id] = new_id`
|
||||||
|
* - `id_map[0]` must be 0 (void type cannot be moved)
|
||||||
|
*
|
||||||
|
* For **split BTF**:
|
||||||
|
* - @id_map must include only split types (types added on top of the base BTF)
|
||||||
|
* - @id_map_cnt must be `btf__type_cnt(btf) - btf__type_cnt(btf__base_btf(btf))`
|
||||||
|
* - Mapping is defined as `id_map[original_id - start_id] = new_id`
|
||||||
|
* - `start_id` equals `btf__type_cnt(btf__base_btf(btf))`
|
||||||
|
*
|
||||||
|
* After permutation, all type references within the BTF data and optional
|
||||||
|
* BTF extension (if provided via @opts) are updated automatically.
|
||||||
|
*
|
||||||
|
* On error, returns a negative error code and sets errno:
|
||||||
|
* - `-EINVAL`: Invalid parameters or invalid ID mapping
|
||||||
|
* - `-ENOMEM`: Memory allocation failure
|
||||||
|
*/
|
||||||
|
LIBBPF_API int btf__permute(struct btf *btf, __u32 *id_map, __u32 id_map_cnt,
|
||||||
|
const struct btf_permute_opts *opts);
|
||||||
|
|
||||||
struct btf_dump;
|
struct btf_dump;
|
||||||
|
|
||||||
struct btf_dump_opts {
|
struct btf_dump_opts {
|
||||||
@@ -286,7 +342,7 @@ LIBBPF_API void btf_dump__free(struct btf_dump *d);
|
|||||||
LIBBPF_API int btf_dump__dump_type(struct btf_dump *d, __u32 id);
|
LIBBPF_API int btf_dump__dump_type(struct btf_dump *d, __u32 id);
|
||||||
|
|
||||||
struct btf_dump_emit_type_decl_opts {
|
struct btf_dump_emit_type_decl_opts {
|
||||||
/* size of this struct, for forward/backward compatiblity */
|
/* size of this struct, for forward/backward compatibility */
|
||||||
size_t sz;
|
size_t sz;
|
||||||
/* optional field name for type declaration, e.g.:
|
/* optional field name for type declaration, e.g.:
|
||||||
* - struct my_struct <FNAME>
|
* - struct my_struct <FNAME>
|
||||||
@@ -320,9 +376,10 @@ struct btf_dump_type_data_opts {
|
|||||||
bool compact; /* no newlines/indentation */
|
bool compact; /* no newlines/indentation */
|
||||||
bool skip_names; /* skip member/type names */
|
bool skip_names; /* skip member/type names */
|
||||||
bool emit_zeroes; /* show 0-valued fields */
|
bool emit_zeroes; /* show 0-valued fields */
|
||||||
|
bool emit_strings; /* print char arrays as strings */
|
||||||
size_t :0;
|
size_t :0;
|
||||||
};
|
};
|
||||||
#define btf_dump_type_data_opts__last_field emit_zeroes
|
#define btf_dump_type_data_opts__last_field emit_strings
|
||||||
|
|
||||||
LIBBPF_API int
|
LIBBPF_API int
|
||||||
btf_dump__dump_type_data(struct btf_dump *d, __u32 id,
|
btf_dump__dump_type_data(struct btf_dump *d, __u32 id,
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ struct btf_dump_data {
|
|||||||
bool compact;
|
bool compact;
|
||||||
bool skip_names;
|
bool skip_names;
|
||||||
bool emit_zeroes;
|
bool emit_zeroes;
|
||||||
|
bool emit_strings;
|
||||||
__u8 indent_lvl; /* base indent level */
|
__u8 indent_lvl; /* base indent level */
|
||||||
char indent_str[BTF_DATA_INDENT_STR_LEN];
|
char indent_str[BTF_DATA_INDENT_STR_LEN];
|
||||||
/* below are used during iteration */
|
/* below are used during iteration */
|
||||||
@@ -225,6 +226,9 @@ static void btf_dump_free_names(struct hashmap *map)
|
|||||||
size_t bkt;
|
size_t bkt;
|
||||||
struct hashmap_entry *cur;
|
struct hashmap_entry *cur;
|
||||||
|
|
||||||
|
if (!map)
|
||||||
|
return;
|
||||||
|
|
||||||
hashmap__for_each_entry(map, cur, bkt)
|
hashmap__for_each_entry(map, cur, bkt)
|
||||||
free((void *)cur->pkey);
|
free((void *)cur->pkey);
|
||||||
|
|
||||||
@@ -304,7 +308,7 @@ int btf_dump__dump_type(struct btf_dump *d, __u32 id)
|
|||||||
* definition, in which case they have to be declared inline as part of field
|
* definition, in which case they have to be declared inline as part of field
|
||||||
* type declaration; or as a top-level anonymous enum, typically used for
|
* type declaration; or as a top-level anonymous enum, typically used for
|
||||||
* declaring global constants. It's impossible to distinguish between two
|
* declaring global constants. It's impossible to distinguish between two
|
||||||
* without knowning whether given enum type was referenced from other type:
|
* without knowing whether given enum type was referenced from other type:
|
||||||
* top-level anonymous enum won't be referenced by anything, while embedded
|
* top-level anonymous enum won't be referenced by anything, while embedded
|
||||||
* one will.
|
* one will.
|
||||||
*/
|
*/
|
||||||
@@ -867,8 +871,8 @@ static void btf_dump_emit_bit_padding(const struct btf_dump *d,
|
|||||||
} pads[] = {
|
} pads[] = {
|
||||||
{"long", d->ptr_sz * 8}, {"int", 32}, {"short", 16}, {"char", 8}
|
{"long", d->ptr_sz * 8}, {"int", 32}, {"short", 16}, {"char", 8}
|
||||||
};
|
};
|
||||||
int new_off, pad_bits, bits, i;
|
int new_off = 0, pad_bits = 0, bits, i;
|
||||||
const char *pad_type;
|
const char *pad_type = NULL;
|
||||||
|
|
||||||
if (cur_off >= next_off)
|
if (cur_off >= next_off)
|
||||||
return; /* no gap */
|
return; /* no gap */
|
||||||
@@ -1304,7 +1308,7 @@ static void btf_dump_emit_type_decl(struct btf_dump *d, __u32 id,
|
|||||||
* chain, restore stack, emit warning, and try to
|
* chain, restore stack, emit warning, and try to
|
||||||
* proceed nevertheless
|
* proceed nevertheless
|
||||||
*/
|
*/
|
||||||
pr_warn("not enough memory for decl stack:%d", err);
|
pr_warn("not enough memory for decl stack: %s\n", errstr(err));
|
||||||
d->decl_stack_cnt = stack_start;
|
d->decl_stack_cnt = stack_start;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1493,7 +1497,10 @@ static void btf_dump_emit_type_chain(struct btf_dump *d,
|
|||||||
case BTF_KIND_TYPE_TAG:
|
case BTF_KIND_TYPE_TAG:
|
||||||
btf_dump_emit_mods(d, decls);
|
btf_dump_emit_mods(d, decls);
|
||||||
name = btf_name_of(d, t->name_off);
|
name = btf_name_of(d, t->name_off);
|
||||||
btf_dump_printf(d, " __attribute__((btf_type_tag(\"%s\")))", name);
|
if (btf_kflag(t))
|
||||||
|
btf_dump_printf(d, " __attribute__((%s))", name);
|
||||||
|
else
|
||||||
|
btf_dump_printf(d, " __attribute__((btf_type_tag(\"%s\")))", name);
|
||||||
break;
|
break;
|
||||||
case BTF_KIND_ARRAY: {
|
case BTF_KIND_ARRAY: {
|
||||||
const struct btf_array *a = btf_array(t);
|
const struct btf_array *a = btf_array(t);
|
||||||
@@ -1755,9 +1762,18 @@ static int btf_dump_get_bitfield_value(struct btf_dump *d,
|
|||||||
__u16 left_shift_bits, right_shift_bits;
|
__u16 left_shift_bits, right_shift_bits;
|
||||||
const __u8 *bytes = data;
|
const __u8 *bytes = data;
|
||||||
__u8 nr_copy_bits;
|
__u8 nr_copy_bits;
|
||||||
|
__u8 start_bit, nr_bytes;
|
||||||
__u64 num = 0;
|
__u64 num = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* Calculate how many bytes cover the bitfield */
|
||||||
|
start_bit = bits_offset % 8;
|
||||||
|
nr_bytes = (start_bit + bit_sz + 7) / 8;
|
||||||
|
|
||||||
|
/* Bound check */
|
||||||
|
if (data + nr_bytes > d->typed_dump->data_end)
|
||||||
|
return -E2BIG;
|
||||||
|
|
||||||
/* Maximum supported bitfield size is 64 bits */
|
/* Maximum supported bitfield size is 64 bits */
|
||||||
if (t->size > 8) {
|
if (t->size > 8) {
|
||||||
pr_warn("unexpected bitfield size %d\n", t->size);
|
pr_warn("unexpected bitfield size %d\n", t->size);
|
||||||
@@ -2024,6 +2040,52 @@ static int btf_dump_var_data(struct btf_dump *d,
|
|||||||
return btf_dump_dump_type_data(d, NULL, t, type_id, data, 0, 0);
|
return btf_dump_dump_type_data(d, NULL, t, type_id, data, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int btf_dump_string_data(struct btf_dump *d,
|
||||||
|
const struct btf_type *t,
|
||||||
|
__u32 id,
|
||||||
|
const void *data)
|
||||||
|
{
|
||||||
|
const struct btf_array *array = btf_array(t);
|
||||||
|
const char *chars = data;
|
||||||
|
__u32 i;
|
||||||
|
|
||||||
|
/* Make sure it is a NUL-terminated string. */
|
||||||
|
for (i = 0; i < array->nelems; i++) {
|
||||||
|
if ((void *)(chars + i) >= d->typed_dump->data_end)
|
||||||
|
return -E2BIG;
|
||||||
|
if (chars[i] == '\0')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == array->nelems) {
|
||||||
|
/* The caller will print this as a regular array. */
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
btf_dump_data_pfx(d);
|
||||||
|
btf_dump_printf(d, "\"");
|
||||||
|
|
||||||
|
for (i = 0; i < array->nelems; i++) {
|
||||||
|
char c = chars[i];
|
||||||
|
|
||||||
|
if (c == '\0') {
|
||||||
|
/*
|
||||||
|
* When printing character arrays as strings, NUL bytes
|
||||||
|
* are always treated as string terminators; they are
|
||||||
|
* never printed.
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (isprint(c))
|
||||||
|
btf_dump_printf(d, "%c", c);
|
||||||
|
else
|
||||||
|
btf_dump_printf(d, "\\x%02x", (__u8)c);
|
||||||
|
}
|
||||||
|
|
||||||
|
btf_dump_printf(d, "\"");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int btf_dump_array_data(struct btf_dump *d,
|
static int btf_dump_array_data(struct btf_dump *d,
|
||||||
const struct btf_type *t,
|
const struct btf_type *t,
|
||||||
__u32 id,
|
__u32 id,
|
||||||
@@ -2051,8 +2113,13 @@ static int btf_dump_array_data(struct btf_dump *d,
|
|||||||
* char arrays, so if size is 1 and element is
|
* char arrays, so if size is 1 and element is
|
||||||
* printable as a char, we'll do that.
|
* printable as a char, we'll do that.
|
||||||
*/
|
*/
|
||||||
if (elem_size == 1)
|
if (elem_size == 1) {
|
||||||
|
if (d->typed_dump->emit_strings &&
|
||||||
|
btf_dump_string_data(d, t, id, data) == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
d->typed_dump->is_array_char = true;
|
d->typed_dump->is_array_char = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* note that we increment depth before calling btf_dump_print() below;
|
/* note that we increment depth before calling btf_dump_print() below;
|
||||||
@@ -2540,6 +2607,7 @@ int btf_dump__dump_type_data(struct btf_dump *d, __u32 id,
|
|||||||
d->typed_dump->compact = OPTS_GET(opts, compact, false);
|
d->typed_dump->compact = OPTS_GET(opts, compact, false);
|
||||||
d->typed_dump->skip_names = OPTS_GET(opts, skip_names, false);
|
d->typed_dump->skip_names = OPTS_GET(opts, skip_names, false);
|
||||||
d->typed_dump->emit_zeroes = OPTS_GET(opts, emit_zeroes, false);
|
d->typed_dump->emit_zeroes = OPTS_GET(opts, emit_zeroes, false);
|
||||||
|
d->typed_dump->emit_strings = OPTS_GET(opts, emit_strings, false);
|
||||||
|
|
||||||
ret = btf_dump_dump_type_data(d, NULL, t, id, data, 0, 0);
|
ret = btf_dump_dump_type_data(d, NULL, t, id, data, 0, 0);
|
||||||
|
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ static int btf_relocate_map_distilled_base(struct btf_relocate *r)
|
|||||||
* need to match both name and size, otherwise embedding the base
|
* need to match both name and size, otherwise embedding the base
|
||||||
* struct/union in the split type is invalid.
|
* struct/union in the split type is invalid.
|
||||||
*/
|
*/
|
||||||
for (id = r->nr_dist_base_types; id < r->nr_split_types; id++) {
|
for (id = r->nr_dist_base_types; id < r->nr_dist_base_types + r->nr_split_types; id++) {
|
||||||
err = btf_mark_embedded_composite_type_ids(r, id);
|
err = btf_mark_embedded_composite_type_ids(r, id);
|
||||||
if (err)
|
if (err)
|
||||||
goto done;
|
goto done;
|
||||||
@@ -428,7 +428,7 @@ static int btf_relocate_rewrite_strs(struct btf_relocate *r, __u32 i)
|
|||||||
} else {
|
} else {
|
||||||
off = r->str_map[*str_off];
|
off = r->str_map[*str_off];
|
||||||
if (!off) {
|
if (!off) {
|
||||||
pr_warn("string '%s' [offset %u] is not mapped to base BTF",
|
pr_warn("string '%s' [offset %u] is not mapped to base BTF\n",
|
||||||
btf__str_by_offset(r->btf, off), *str_off);
|
btf__str_by_offset(r->btf, off), *str_off);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
|
||||||
#include "libbpf_internal.h"
|
#include "libbpf_internal.h"
|
||||||
#include "str_error.h"
|
|
||||||
|
|
||||||
/* A SHT_GNU_versym section holds 16-bit words. This bit is set if
|
/* A SHT_GNU_versym section holds 16-bit words. This bit is set if
|
||||||
* the symbol is hidden and can only be seen when referenced using an
|
* the symbol is hidden and can only be seen when referenced using an
|
||||||
@@ -24,7 +23,6 @@
|
|||||||
|
|
||||||
int elf_open(const char *binary_path, struct elf_fd *elf_fd)
|
int elf_open(const char *binary_path, struct elf_fd *elf_fd)
|
||||||
{
|
{
|
||||||
char errmsg[STRERR_BUFSIZE];
|
|
||||||
int fd, ret;
|
int fd, ret;
|
||||||
Elf *elf;
|
Elf *elf;
|
||||||
|
|
||||||
@@ -38,8 +36,7 @@ int elf_open(const char *binary_path, struct elf_fd *elf_fd)
|
|||||||
fd = open(binary_path, O_RDONLY | O_CLOEXEC);
|
fd = open(binary_path, O_RDONLY | O_CLOEXEC);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
pr_warn("elf: failed to open %s: %s\n", binary_path,
|
pr_warn("elf: failed to open %s: %s\n", binary_path, errstr(ret));
|
||||||
libbpf_strerror_r(ret, errmsg, sizeof(errmsg)));
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
|
elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
#include "libbpf.h"
|
#include "libbpf.h"
|
||||||
#include "libbpf_common.h"
|
#include "libbpf_common.h"
|
||||||
#include "libbpf_internal.h"
|
#include "libbpf_internal.h"
|
||||||
#include "str_error.h"
|
|
||||||
|
|
||||||
static inline __u64 ptr_to_u64(const void *ptr)
|
static inline __u64 ptr_to_u64(const void *ptr)
|
||||||
{
|
{
|
||||||
@@ -47,7 +46,6 @@ static int probe_kern_prog_name(int token_fd)
|
|||||||
|
|
||||||
static int probe_kern_global_data(int token_fd)
|
static int probe_kern_global_data(int token_fd)
|
||||||
{
|
{
|
||||||
char *cp, errmsg[STRERR_BUFSIZE];
|
|
||||||
struct bpf_insn insns[] = {
|
struct bpf_insn insns[] = {
|
||||||
BPF_LD_MAP_VALUE(BPF_REG_1, 0, 16),
|
BPF_LD_MAP_VALUE(BPF_REG_1, 0, 16),
|
||||||
BPF_ST_MEM(BPF_DW, BPF_REG_1, 0, 42),
|
BPF_ST_MEM(BPF_DW, BPF_REG_1, 0, 42),
|
||||||
@@ -67,9 +65,8 @@ static int probe_kern_global_data(int token_fd)
|
|||||||
map = bpf_map_create(BPF_MAP_TYPE_ARRAY, "libbpf_global", sizeof(int), 32, 1, &map_opts);
|
map = bpf_map_create(BPF_MAP_TYPE_ARRAY, "libbpf_global", sizeof(int), 32, 1, &map_opts);
|
||||||
if (map < 0) {
|
if (map < 0) {
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
cp = libbpf_strerror_r(ret, errmsg, sizeof(errmsg));
|
pr_warn("Error in %s(): %s. Couldn't create simple array map.\n",
|
||||||
pr_warn("Error in %s():%s(%d). Couldn't create simple array map.\n",
|
__func__, errstr(ret));
|
||||||
__func__, cp, -ret);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,7 +264,6 @@ static int probe_kern_probe_read_kernel(int token_fd)
|
|||||||
|
|
||||||
static int probe_prog_bind_map(int token_fd)
|
static int probe_prog_bind_map(int token_fd)
|
||||||
{
|
{
|
||||||
char *cp, errmsg[STRERR_BUFSIZE];
|
|
||||||
struct bpf_insn insns[] = {
|
struct bpf_insn insns[] = {
|
||||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||||
BPF_EXIT_INSN(),
|
BPF_EXIT_INSN(),
|
||||||
@@ -285,9 +281,8 @@ static int probe_prog_bind_map(int token_fd)
|
|||||||
map = bpf_map_create(BPF_MAP_TYPE_ARRAY, "libbpf_det_bind", sizeof(int), 32, 1, &map_opts);
|
map = bpf_map_create(BPF_MAP_TYPE_ARRAY, "libbpf_det_bind", sizeof(int), 32, 1, &map_opts);
|
||||||
if (map < 0) {
|
if (map < 0) {
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
cp = libbpf_strerror_r(ret, errmsg, sizeof(errmsg));
|
pr_warn("Error in %s(): %s. Couldn't create simple array map.\n",
|
||||||
pr_warn("Error in %s():%s(%d). Couldn't create simple array map.\n",
|
__func__, errstr(ret));
|
||||||
__func__, cp, -ret);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -604,7 +599,8 @@ bool feat_supported(struct kern_feature_cache *cache, enum kern_feature_id feat_
|
|||||||
} else if (ret == 0) {
|
} else if (ret == 0) {
|
||||||
WRITE_ONCE(cache->res[feat_id], FEAT_MISSING);
|
WRITE_ONCE(cache->res[feat_id], FEAT_MISSING);
|
||||||
} else {
|
} else {
|
||||||
pr_warn("Detection of kernel %s support failed: %d\n", feat->desc, ret);
|
pr_warn("Detection of kernel %s support failed: %s\n",
|
||||||
|
feat->desc, errstr(ret));
|
||||||
WRITE_ONCE(cache->res[feat_id], FEAT_MISSING);
|
WRITE_ONCE(cache->res[feat_id], FEAT_MISSING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
234
src/gen_loader.c
234
src/gen_loader.c
@@ -4,6 +4,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <asm/byteorder.h>
|
||||||
#include <linux/filter.h>
|
#include <linux/filter.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include "btf.h"
|
#include "btf.h"
|
||||||
@@ -13,7 +14,6 @@
|
|||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
#include "bpf_gen_internal.h"
|
#include "bpf_gen_internal.h"
|
||||||
#include "skel_internal.h"
|
#include "skel_internal.h"
|
||||||
#include <asm/byteorder.h>
|
|
||||||
|
|
||||||
#define MAX_USED_MAPS 64
|
#define MAX_USED_MAPS 64
|
||||||
#define MAX_USED_PROGS 32
|
#define MAX_USED_PROGS 32
|
||||||
@@ -109,6 +109,7 @@ static void emit2(struct bpf_gen *gen, struct bpf_insn insn1, struct bpf_insn in
|
|||||||
|
|
||||||
static int add_data(struct bpf_gen *gen, const void *data, __u32 size);
|
static int add_data(struct bpf_gen *gen, const void *data, __u32 size);
|
||||||
static void emit_sys_close_blob(struct bpf_gen *gen, int blob_off);
|
static void emit_sys_close_blob(struct bpf_gen *gen, int blob_off);
|
||||||
|
static void emit_signature_match(struct bpf_gen *gen);
|
||||||
|
|
||||||
void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps)
|
void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps)
|
||||||
{
|
{
|
||||||
@@ -151,6 +152,8 @@ void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps
|
|||||||
/* R7 contains the error code from sys_bpf. Copy it into R0 and exit. */
|
/* 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_MOV64_REG(BPF_REG_0, BPF_REG_7));
|
||||||
emit(gen, BPF_EXIT_INSN());
|
emit(gen, BPF_EXIT_INSN());
|
||||||
|
if (OPTS_GET(gen->opts, gen_hash, false))
|
||||||
|
emit_signature_match(gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_data(struct bpf_gen *gen, const void *data, __u32 size)
|
static int add_data(struct bpf_gen *gen, const void *data, __u32 size)
|
||||||
@@ -367,6 +370,8 @@ static void emit_sys_close_blob(struct bpf_gen *gen, int blob_off)
|
|||||||
__emit_sys_close(gen);
|
__emit_sys_close(gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void compute_sha_update_offsets(struct bpf_gen *gen);
|
||||||
|
|
||||||
int bpf_gen__finish(struct bpf_gen *gen, int nr_progs, int nr_maps)
|
int bpf_gen__finish(struct bpf_gen *gen, int nr_progs, int nr_maps)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -393,7 +398,10 @@ int bpf_gen__finish(struct bpf_gen *gen, int nr_progs, int nr_maps)
|
|||||||
blob_fd_array_off(gen, i));
|
blob_fd_array_off(gen, i));
|
||||||
emit(gen, BPF_MOV64_IMM(BPF_REG_0, 0));
|
emit(gen, BPF_MOV64_IMM(BPF_REG_0, 0));
|
||||||
emit(gen, BPF_EXIT_INSN());
|
emit(gen, BPF_EXIT_INSN());
|
||||||
pr_debug("gen: finish %d\n", gen->error);
|
if (OPTS_GET(gen->opts, gen_hash, false))
|
||||||
|
compute_sha_update_offsets(gen);
|
||||||
|
|
||||||
|
pr_debug("gen: finish %s\n", errstr(gen->error));
|
||||||
if (!gen->error) {
|
if (!gen->error) {
|
||||||
struct gen_loader_opts *opts = gen->opts;
|
struct gen_loader_opts *opts = gen->opts;
|
||||||
|
|
||||||
@@ -401,6 +409,15 @@ int bpf_gen__finish(struct bpf_gen *gen, int nr_progs, int nr_maps)
|
|||||||
opts->insns_sz = gen->insn_cur - gen->insn_start;
|
opts->insns_sz = gen->insn_cur - gen->insn_start;
|
||||||
opts->data = gen->data_start;
|
opts->data = gen->data_start;
|
||||||
opts->data_sz = gen->data_cur - gen->data_start;
|
opts->data_sz = gen->data_cur - gen->data_start;
|
||||||
|
|
||||||
|
/* use target endianness for embedded loader */
|
||||||
|
if (gen->swapped_endian) {
|
||||||
|
struct bpf_insn *insn = (struct bpf_insn *)opts->insns;
|
||||||
|
int insn_cnt = opts->insns_sz / sizeof(struct bpf_insn);
|
||||||
|
|
||||||
|
for (i = 0; i < insn_cnt; i++)
|
||||||
|
bpf_insn_bswap(insn++);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return gen->error;
|
return gen->error;
|
||||||
}
|
}
|
||||||
@@ -414,6 +431,44 @@ void bpf_gen__free(struct bpf_gen *gen)
|
|||||||
free(gen);
|
free(gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fields of bpf_attr are set to values in native byte-order before being
|
||||||
|
* written to the target-bound data blob, and may need endian conversion.
|
||||||
|
* This macro allows providing the correct value in situ more simply than
|
||||||
|
* writing a separate converter for *all fields* of *all records* included
|
||||||
|
* in union bpf_attr. Note that sizeof(rval) should match the assignment
|
||||||
|
* target to avoid runtime problems.
|
||||||
|
*/
|
||||||
|
#define tgt_endian(rval) ({ \
|
||||||
|
typeof(rval) _val = (rval); \
|
||||||
|
if (gen->swapped_endian) { \
|
||||||
|
switch (sizeof(_val)) { \
|
||||||
|
case 1: break; \
|
||||||
|
case 2: _val = bswap_16(_val); break; \
|
||||||
|
case 4: _val = bswap_32(_val); break; \
|
||||||
|
case 8: _val = bswap_64(_val); break; \
|
||||||
|
default: pr_warn("unsupported bswap size!\n"); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
_val; \
|
||||||
|
})
|
||||||
|
|
||||||
|
static void compute_sha_update_offsets(struct bpf_gen *gen)
|
||||||
|
{
|
||||||
|
__u64 sha[SHA256_DWORD_SIZE];
|
||||||
|
__u64 sha_dw;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
libbpf_sha256(gen->data_start, gen->data_cur - gen->data_start, (__u8 *)sha);
|
||||||
|
for (i = 0; i < SHA256_DWORD_SIZE; i++) {
|
||||||
|
struct bpf_insn *insn =
|
||||||
|
(struct bpf_insn *)(gen->insn_start + gen->hash_insn_offset[i]);
|
||||||
|
sha_dw = tgt_endian(sha[i]);
|
||||||
|
insn[0].imm = (__u32)sha_dw;
|
||||||
|
insn[1].imm = sha_dw >> 32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void bpf_gen__load_btf(struct bpf_gen *gen, const void *btf_raw_data,
|
void bpf_gen__load_btf(struct bpf_gen *gen, const void *btf_raw_data,
|
||||||
__u32 btf_raw_size)
|
__u32 btf_raw_size)
|
||||||
{
|
{
|
||||||
@@ -422,11 +477,12 @@ void bpf_gen__load_btf(struct bpf_gen *gen, const void *btf_raw_data,
|
|||||||
union bpf_attr attr;
|
union bpf_attr attr;
|
||||||
|
|
||||||
memset(&attr, 0, attr_size);
|
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);
|
btf_data = add_data(gen, btf_raw_data, btf_raw_size);
|
||||||
|
|
||||||
attr.btf_size = btf_raw_size;
|
attr.btf_size = tgt_endian(btf_raw_size);
|
||||||
btf_load_attr = add_data(gen, &attr, attr_size);
|
btf_load_attr = add_data(gen, &attr, attr_size);
|
||||||
|
pr_debug("gen: load_btf: off %d size %d, attr: off %d size %d\n",
|
||||||
|
btf_data, btf_raw_size, btf_load_attr, attr_size);
|
||||||
|
|
||||||
/* populate union bpf_attr with user provided log details */
|
/* populate union bpf_attr with user provided log details */
|
||||||
move_ctx2blob(gen, attr_field(btf_load_attr, btf_log_level), 4,
|
move_ctx2blob(gen, attr_field(btf_load_attr, btf_log_level), 4,
|
||||||
@@ -457,28 +513,29 @@ void bpf_gen__map_create(struct bpf_gen *gen,
|
|||||||
union bpf_attr attr;
|
union bpf_attr attr;
|
||||||
|
|
||||||
memset(&attr, 0, attr_size);
|
memset(&attr, 0, attr_size);
|
||||||
attr.map_type = map_type;
|
attr.map_type = tgt_endian(map_type);
|
||||||
attr.key_size = key_size;
|
attr.key_size = tgt_endian(key_size);
|
||||||
attr.value_size = value_size;
|
attr.value_size = tgt_endian(value_size);
|
||||||
attr.map_flags = map_attr->map_flags;
|
attr.map_flags = tgt_endian(map_attr->map_flags);
|
||||||
attr.map_extra = map_attr->map_extra;
|
attr.map_extra = tgt_endian(map_attr->map_extra);
|
||||||
if (map_name)
|
if (map_name)
|
||||||
libbpf_strlcpy(attr.map_name, map_name, sizeof(attr.map_name));
|
libbpf_strlcpy(attr.map_name, map_name, sizeof(attr.map_name));
|
||||||
attr.numa_node = map_attr->numa_node;
|
attr.numa_node = tgt_endian(map_attr->numa_node);
|
||||||
attr.map_ifindex = map_attr->map_ifindex;
|
attr.map_ifindex = tgt_endian(map_attr->map_ifindex);
|
||||||
attr.max_entries = max_entries;
|
attr.max_entries = tgt_endian(max_entries);
|
||||||
attr.btf_key_type_id = map_attr->btf_key_type_id;
|
attr.btf_key_type_id = tgt_endian(map_attr->btf_key_type_id);
|
||||||
attr.btf_value_type_id = map_attr->btf_value_type_id;
|
attr.btf_value_type_id = tgt_endian(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_type, attr.btf_value_type_id);
|
|
||||||
|
|
||||||
map_create_attr = add_data(gen, &attr, attr_size);
|
map_create_attr = add_data(gen, &attr, attr_size);
|
||||||
if (attr.btf_value_type_id)
|
pr_debug("gen: map_create: %s idx %d type %d value_type_id %d, attr: off %d size %d\n",
|
||||||
|
map_name, map_idx, map_type, map_attr->btf_value_type_id,
|
||||||
|
map_create_attr, attr_size);
|
||||||
|
|
||||||
|
if (map_attr->btf_value_type_id)
|
||||||
/* populate union bpf_attr with btf_fd saved in the stack earlier */
|
/* populate union bpf_attr with btf_fd saved in the stack earlier */
|
||||||
move_stack2blob(gen, attr_field(map_create_attr, btf_fd), 4,
|
move_stack2blob(gen, attr_field(map_create_attr, btf_fd), 4,
|
||||||
stack_off(btf_fd));
|
stack_off(btf_fd));
|
||||||
switch (attr.map_type) {
|
switch (map_type) {
|
||||||
case BPF_MAP_TYPE_ARRAY_OF_MAPS:
|
case BPF_MAP_TYPE_ARRAY_OF_MAPS:
|
||||||
case BPF_MAP_TYPE_HASH_OF_MAPS:
|
case BPF_MAP_TYPE_HASH_OF_MAPS:
|
||||||
move_stack2blob(gen, attr_field(map_create_attr, inner_map_fd), 4,
|
move_stack2blob(gen, attr_field(map_create_attr, inner_map_fd), 4,
|
||||||
@@ -498,8 +555,8 @@ void bpf_gen__map_create(struct bpf_gen *gen,
|
|||||||
/* emit MAP_CREATE command */
|
/* emit MAP_CREATE command */
|
||||||
emit_sys_bpf(gen, BPF_MAP_CREATE, map_create_attr, attr_size);
|
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",
|
debug_ret(gen, "map_create %s idx %d type %d value_size %d value_btf_id %d",
|
||||||
attr.map_name, map_idx, map_type, value_size,
|
map_name, map_idx, map_type, value_size,
|
||||||
attr.btf_value_type_id);
|
map_attr->btf_value_type_id);
|
||||||
emit_check_err(gen);
|
emit_check_err(gen);
|
||||||
/* remember map_fd in the stack, if successful */
|
/* remember map_fd in the stack, if successful */
|
||||||
if (map_idx < 0) {
|
if (map_idx < 0) {
|
||||||
@@ -523,6 +580,29 @@ void bpf_gen__map_create(struct bpf_gen *gen,
|
|||||||
emit_sys_close_stack(gen, stack_off(inner_map_fd));
|
emit_sys_close_stack(gen, stack_off(inner_map_fd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void emit_signature_match(struct bpf_gen *gen)
|
||||||
|
{
|
||||||
|
__s64 off;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < SHA256_DWORD_SIZE; i++) {
|
||||||
|
emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX,
|
||||||
|
0, 0, 0, 0));
|
||||||
|
emit(gen, BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, i * sizeof(__u64)));
|
||||||
|
gen->hash_insn_offset[i] = gen->insn_cur - gen->insn_start;
|
||||||
|
emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_3, 0, 0, 0, 0, 0));
|
||||||
|
|
||||||
|
off = -(gen->insn_cur - gen->insn_start - gen->cleanup_label) / 8 - 1;
|
||||||
|
if (is_simm16(off)) {
|
||||||
|
emit(gen, BPF_MOV64_IMM(BPF_REG_7, -EINVAL));
|
||||||
|
emit(gen, BPF_JMP_REG(BPF_JNE, BPF_REG_2, BPF_REG_3, off));
|
||||||
|
} else {
|
||||||
|
gen->error = -ERANGE;
|
||||||
|
emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0, -1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void bpf_gen__record_attach_target(struct bpf_gen *gen, const char *attach_name,
|
void bpf_gen__record_attach_target(struct bpf_gen *gen, const char *attach_name,
|
||||||
enum bpf_attach_type type)
|
enum bpf_attach_type type)
|
||||||
{
|
{
|
||||||
@@ -784,12 +864,12 @@ log:
|
|||||||
emit_ksym_relo_log(gen, relo, kdesc->ref);
|
emit_ksym_relo_log(gen, relo, kdesc->ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __u32 src_reg_mask(void)
|
static __u32 src_reg_mask(struct bpf_gen *gen)
|
||||||
{
|
{
|
||||||
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
#if defined(__LITTLE_ENDIAN_BITFIELD) /* src_reg,dst_reg,... */
|
||||||
return 0x0f; /* src_reg,dst_reg,... */
|
return gen->swapped_endian ? 0xf0 : 0x0f;
|
||||||
#elif defined(__BIG_ENDIAN_BITFIELD)
|
#elif defined(__BIG_ENDIAN_BITFIELD) /* dst_reg,src_reg,... */
|
||||||
return 0xf0; /* dst_reg,src_reg,... */
|
return gen->swapped_endian ? 0x0f : 0xf0;
|
||||||
#else
|
#else
|
||||||
#error "Unsupported bit endianness, cannot proceed"
|
#error "Unsupported bit endianness, cannot proceed"
|
||||||
#endif
|
#endif
|
||||||
@@ -840,7 +920,7 @@ static void emit_relo_ksym_btf(struct bpf_gen *gen, struct ksym_relo_desc *relo,
|
|||||||
emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0, 3));
|
emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0, 3));
|
||||||
clear_src_reg:
|
clear_src_reg:
|
||||||
/* clear bpf_object__relocate_data's src_reg assignment, otherwise we get a verifier failure */
|
/* clear bpf_object__relocate_data's src_reg assignment, otherwise we get a verifier failure */
|
||||||
reg_mask = src_reg_mask();
|
reg_mask = src_reg_mask(gen);
|
||||||
emit(gen, BPF_LDX_MEM(BPF_B, BPF_REG_9, BPF_REG_8, offsetofend(struct bpf_insn, code)));
|
emit(gen, BPF_LDX_MEM(BPF_B, BPF_REG_9, BPF_REG_8, offsetofend(struct bpf_insn, code)));
|
||||||
emit(gen, BPF_ALU32_IMM(BPF_AND, BPF_REG_9, reg_mask));
|
emit(gen, BPF_ALU32_IMM(BPF_AND, BPF_REG_9, reg_mask));
|
||||||
emit(gen, BPF_STX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, offsetofend(struct bpf_insn, code)));
|
emit(gen, BPF_STX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, offsetofend(struct bpf_insn, code)));
|
||||||
@@ -931,48 +1011,94 @@ static void cleanup_relos(struct bpf_gen *gen, int insns)
|
|||||||
cleanup_core_relo(gen);
|
cleanup_core_relo(gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Convert func, line, and core relo info blobs to target endianness */
|
||||||
|
static void info_blob_bswap(struct bpf_gen *gen, int func_info, int line_info,
|
||||||
|
int core_relos, struct bpf_prog_load_opts *load_attr)
|
||||||
|
{
|
||||||
|
struct bpf_func_info *fi = gen->data_start + func_info;
|
||||||
|
struct bpf_line_info *li = gen->data_start + line_info;
|
||||||
|
struct bpf_core_relo *cr = gen->data_start + core_relos;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < load_attr->func_info_cnt; i++)
|
||||||
|
bpf_func_info_bswap(fi++);
|
||||||
|
|
||||||
|
for (i = 0; i < load_attr->line_info_cnt; i++)
|
||||||
|
bpf_line_info_bswap(li++);
|
||||||
|
|
||||||
|
for (i = 0; i < gen->core_relo_cnt; i++)
|
||||||
|
bpf_core_relo_bswap(cr++);
|
||||||
|
}
|
||||||
|
|
||||||
void bpf_gen__prog_load(struct bpf_gen *gen,
|
void bpf_gen__prog_load(struct bpf_gen *gen,
|
||||||
enum bpf_prog_type prog_type, const char *prog_name,
|
enum bpf_prog_type prog_type, const char *prog_name,
|
||||||
const char *license, struct bpf_insn *insns, size_t insn_cnt,
|
const char *license, struct bpf_insn *insns, size_t insn_cnt,
|
||||||
struct bpf_prog_load_opts *load_attr, int prog_idx)
|
struct bpf_prog_load_opts *load_attr, int prog_idx)
|
||||||
{
|
{
|
||||||
|
int func_info_tot_sz = load_attr->func_info_cnt *
|
||||||
|
load_attr->func_info_rec_size;
|
||||||
|
int line_info_tot_sz = load_attr->line_info_cnt *
|
||||||
|
load_attr->line_info_rec_size;
|
||||||
|
int core_relo_tot_sz = gen->core_relo_cnt *
|
||||||
|
sizeof(struct bpf_core_relo);
|
||||||
int prog_load_attr, license_off, insns_off, func_info, line_info, core_relos;
|
int prog_load_attr, license_off, insns_off, func_info, line_info, core_relos;
|
||||||
int attr_size = offsetofend(union bpf_attr, core_relo_rec_size);
|
int attr_size = offsetofend(union bpf_attr, core_relo_rec_size);
|
||||||
union bpf_attr attr;
|
union bpf_attr attr;
|
||||||
|
|
||||||
memset(&attr, 0, attr_size);
|
memset(&attr, 0, attr_size);
|
||||||
pr_debug("gen: prog_load: type %d insns_cnt %zd progi_idx %d\n",
|
|
||||||
prog_type, insn_cnt, prog_idx);
|
|
||||||
/* add license string to blob of bytes */
|
/* add license string to blob of bytes */
|
||||||
license_off = add_data(gen, license, strlen(license) + 1);
|
license_off = add_data(gen, license, strlen(license) + 1);
|
||||||
/* add insns to blob of bytes */
|
/* add insns to blob of bytes */
|
||||||
insns_off = add_data(gen, insns, insn_cnt * sizeof(struct bpf_insn));
|
insns_off = add_data(gen, insns, insn_cnt * sizeof(struct bpf_insn));
|
||||||
|
pr_debug("gen: prog_load: prog_idx %d type %d insn off %d insns_cnt %zd license off %d\n",
|
||||||
|
prog_idx, prog_type, insns_off, insn_cnt, license_off);
|
||||||
|
|
||||||
attr.prog_type = prog_type;
|
/* convert blob insns to target endianness */
|
||||||
attr.expected_attach_type = load_attr->expected_attach_type;
|
if (gen->swapped_endian) {
|
||||||
attr.attach_btf_id = load_attr->attach_btf_id;
|
struct bpf_insn *insn = gen->data_start + insns_off;
|
||||||
attr.prog_ifindex = load_attr->prog_ifindex;
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < insn_cnt; i++, insn++)
|
||||||
|
bpf_insn_bswap(insn);
|
||||||
|
}
|
||||||
|
|
||||||
|
attr.prog_type = tgt_endian(prog_type);
|
||||||
|
attr.expected_attach_type = tgt_endian(load_attr->expected_attach_type);
|
||||||
|
attr.attach_btf_id = tgt_endian(load_attr->attach_btf_id);
|
||||||
|
attr.prog_ifindex = tgt_endian(load_attr->prog_ifindex);
|
||||||
attr.kern_version = 0;
|
attr.kern_version = 0;
|
||||||
attr.insn_cnt = (__u32)insn_cnt;
|
attr.insn_cnt = tgt_endian((__u32)insn_cnt);
|
||||||
attr.prog_flags = load_attr->prog_flags;
|
attr.prog_flags = tgt_endian(load_attr->prog_flags);
|
||||||
|
|
||||||
attr.func_info_rec_size = load_attr->func_info_rec_size;
|
attr.func_info_rec_size = tgt_endian(load_attr->func_info_rec_size);
|
||||||
attr.func_info_cnt = load_attr->func_info_cnt;
|
attr.func_info_cnt = tgt_endian(load_attr->func_info_cnt);
|
||||||
func_info = add_data(gen, load_attr->func_info,
|
func_info = add_data(gen, load_attr->func_info, func_info_tot_sz);
|
||||||
attr.func_info_cnt * attr.func_info_rec_size);
|
pr_debug("gen: prog_load: func_info: off %d cnt %d rec size %d\n",
|
||||||
|
func_info, load_attr->func_info_cnt,
|
||||||
|
load_attr->func_info_rec_size);
|
||||||
|
|
||||||
attr.line_info_rec_size = load_attr->line_info_rec_size;
|
attr.line_info_rec_size = tgt_endian(load_attr->line_info_rec_size);
|
||||||
attr.line_info_cnt = load_attr->line_info_cnt;
|
attr.line_info_cnt = tgt_endian(load_attr->line_info_cnt);
|
||||||
line_info = add_data(gen, load_attr->line_info,
|
line_info = add_data(gen, load_attr->line_info, line_info_tot_sz);
|
||||||
attr.line_info_cnt * attr.line_info_rec_size);
|
pr_debug("gen: prog_load: line_info: off %d cnt %d rec size %d\n",
|
||||||
|
line_info, load_attr->line_info_cnt,
|
||||||
|
load_attr->line_info_rec_size);
|
||||||
|
|
||||||
attr.core_relo_rec_size = sizeof(struct bpf_core_relo);
|
attr.core_relo_rec_size = tgt_endian((__u32)sizeof(struct bpf_core_relo));
|
||||||
attr.core_relo_cnt = gen->core_relo_cnt;
|
attr.core_relo_cnt = tgt_endian(gen->core_relo_cnt);
|
||||||
core_relos = add_data(gen, gen->core_relos,
|
core_relos = add_data(gen, gen->core_relos, core_relo_tot_sz);
|
||||||
attr.core_relo_cnt * attr.core_relo_rec_size);
|
pr_debug("gen: prog_load: core_relos: off %d cnt %d rec size %zd\n",
|
||||||
|
core_relos, gen->core_relo_cnt,
|
||||||
|
sizeof(struct bpf_core_relo));
|
||||||
|
|
||||||
|
/* convert all info blobs to target endianness */
|
||||||
|
if (gen->swapped_endian)
|
||||||
|
info_blob_bswap(gen, func_info, line_info, core_relos, load_attr);
|
||||||
|
|
||||||
libbpf_strlcpy(attr.prog_name, prog_name, sizeof(attr.prog_name));
|
libbpf_strlcpy(attr.prog_name, prog_name, sizeof(attr.prog_name));
|
||||||
prog_load_attr = add_data(gen, &attr, attr_size);
|
prog_load_attr = add_data(gen, &attr, attr_size);
|
||||||
|
pr_debug("gen: prog_load: attr: off %d size %d\n",
|
||||||
|
prog_load_attr, attr_size);
|
||||||
|
|
||||||
/* populate union bpf_attr with a pointer to license */
|
/* populate union bpf_attr with a pointer to license */
|
||||||
emit_rel_store(gen, attr_field(prog_load_attr, license), license_off);
|
emit_rel_store(gen, attr_field(prog_load_attr, license), license_off);
|
||||||
@@ -1040,7 +1166,6 @@ void bpf_gen__map_update_elem(struct bpf_gen *gen, int map_idx, void *pvalue,
|
|||||||
int zero = 0;
|
int zero = 0;
|
||||||
|
|
||||||
memset(&attr, 0, attr_size);
|
memset(&attr, 0, attr_size);
|
||||||
pr_debug("gen: map_update_elem: idx %d\n", map_idx);
|
|
||||||
|
|
||||||
value = add_data(gen, pvalue, value_size);
|
value = add_data(gen, pvalue, value_size);
|
||||||
key = add_data(gen, &zero, sizeof(zero));
|
key = add_data(gen, &zero, sizeof(zero));
|
||||||
@@ -1068,6 +1193,8 @@ void bpf_gen__map_update_elem(struct bpf_gen *gen, int map_idx, void *pvalue,
|
|||||||
emit(gen, BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel));
|
emit(gen, BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel));
|
||||||
|
|
||||||
map_update_attr = add_data(gen, &attr, attr_size);
|
map_update_attr = add_data(gen, &attr, attr_size);
|
||||||
|
pr_debug("gen: map_update_elem: idx %d, value: off %d size %d, attr: off %d size %d\n",
|
||||||
|
map_idx, value, value_size, map_update_attr, attr_size);
|
||||||
move_blob2blob(gen, attr_field(map_update_attr, map_fd), 4,
|
move_blob2blob(gen, attr_field(map_update_attr, map_fd), 4,
|
||||||
blob_fd_array_off(gen, map_idx));
|
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, key), key);
|
||||||
@@ -1084,14 +1211,16 @@ void bpf_gen__populate_outer_map(struct bpf_gen *gen, int outer_map_idx, int slo
|
|||||||
int attr_size = offsetofend(union bpf_attr, flags);
|
int attr_size = offsetofend(union bpf_attr, flags);
|
||||||
int map_update_attr, key;
|
int map_update_attr, key;
|
||||||
union bpf_attr attr;
|
union bpf_attr attr;
|
||||||
|
int tgt_slot;
|
||||||
|
|
||||||
memset(&attr, 0, attr_size);
|
memset(&attr, 0, attr_size);
|
||||||
pr_debug("gen: populate_outer_map: outer %d key %d inner %d\n",
|
|
||||||
outer_map_idx, slot, inner_map_idx);
|
|
||||||
|
|
||||||
key = add_data(gen, &slot, sizeof(slot));
|
tgt_slot = tgt_endian(slot);
|
||||||
|
key = add_data(gen, &tgt_slot, sizeof(tgt_slot));
|
||||||
|
|
||||||
map_update_attr = add_data(gen, &attr, attr_size);
|
map_update_attr = add_data(gen, &attr, attr_size);
|
||||||
|
pr_debug("gen: populate_outer_map: outer %d key %d inner %d, attr: off %d size %d\n",
|
||||||
|
outer_map_idx, slot, inner_map_idx, map_update_attr, attr_size);
|
||||||
move_blob2blob(gen, attr_field(map_update_attr, map_fd), 4,
|
move_blob2blob(gen, attr_field(map_update_attr, map_fd), 4,
|
||||||
blob_fd_array_off(gen, outer_map_idx));
|
blob_fd_array_off(gen, outer_map_idx));
|
||||||
emit_rel_store(gen, attr_field(map_update_attr, key), key);
|
emit_rel_store(gen, attr_field(map_update_attr, key), key);
|
||||||
@@ -1112,8 +1241,9 @@ void bpf_gen__map_freeze(struct bpf_gen *gen, int map_idx)
|
|||||||
union bpf_attr attr;
|
union bpf_attr attr;
|
||||||
|
|
||||||
memset(&attr, 0, attr_size);
|
memset(&attr, 0, attr_size);
|
||||||
pr_debug("gen: map_freeze: idx %d\n", map_idx);
|
|
||||||
map_freeze_attr = add_data(gen, &attr, attr_size);
|
map_freeze_attr = add_data(gen, &attr, attr_size);
|
||||||
|
pr_debug("gen: map_freeze: idx %d, attr: off %d size %d\n",
|
||||||
|
map_idx, map_freeze_attr, attr_size);
|
||||||
move_blob2blob(gen, attr_field(map_freeze_attr, map_fd), 4,
|
move_blob2blob(gen, attr_field(map_freeze_attr, map_fd), 4,
|
||||||
blob_fd_array_off(gen, map_idx));
|
blob_fd_array_off(gen, map_idx));
|
||||||
/* emit MAP_FREEZE command */
|
/* emit MAP_FREEZE command */
|
||||||
|
|||||||
@@ -166,8 +166,8 @@ bool hashmap_find(const struct hashmap *map, long key, long *value);
|
|||||||
* @bkt: integer used as a bucket loop cursor
|
* @bkt: integer used as a bucket loop cursor
|
||||||
*/
|
*/
|
||||||
#define hashmap__for_each_entry(map, cur, bkt) \
|
#define hashmap__for_each_entry(map, cur, bkt) \
|
||||||
for (bkt = 0; bkt < map->cap; bkt++) \
|
for (bkt = 0; bkt < (map)->cap; bkt++) \
|
||||||
for (cur = map->buckets[bkt]; cur; cur = cur->next)
|
for (cur = (map)->buckets[bkt]; cur; cur = cur->next)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* hashmap__for_each_entry_safe - iterate over all entries in hashmap, safe
|
* hashmap__for_each_entry_safe - iterate over all entries in hashmap, safe
|
||||||
@@ -178,8 +178,8 @@ bool hashmap_find(const struct hashmap *map, long key, long *value);
|
|||||||
* @bkt: integer used as a bucket loop cursor
|
* @bkt: integer used as a bucket loop cursor
|
||||||
*/
|
*/
|
||||||
#define hashmap__for_each_entry_safe(map, cur, tmp, bkt) \
|
#define hashmap__for_each_entry_safe(map, cur, tmp, bkt) \
|
||||||
for (bkt = 0; bkt < map->cap; bkt++) \
|
for (bkt = 0; bkt < (map)->cap; bkt++) \
|
||||||
for (cur = map->buckets[bkt]; \
|
for (cur = (map)->buckets[bkt]; \
|
||||||
cur && ({tmp = cur->next; true; }); \
|
cur && ({tmp = cur->next; true; }); \
|
||||||
cur = tmp)
|
cur = tmp)
|
||||||
|
|
||||||
@@ -190,19 +190,19 @@ bool hashmap_find(const struct hashmap *map, long key, long *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 = (map)->buckets \
|
||||||
? map->buckets[hash_bits(map->hash_fn((_key), map->ctx), map->cap_bits)] \
|
? (map)->buckets[hash_bits((map)->hash_fn((_key), (map)->ctx), (map)->cap_bits)] \
|
||||||
: NULL; \
|
: 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 = (map)->buckets \
|
||||||
? map->buckets[hash_bits(map->hash_fn((_key), map->ctx), map->cap_bits)] \
|
? (map)->buckets[hash_bits((map)->hash_fn((_key), (map)->ctx), (map)->cap_bits)] \
|
||||||
: NULL; \
|
: 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))
|
||||||
|
|
||||||
#endif /* __LIBBPF_HASHMAP_H */
|
#endif /* __LIBBPF_HASHMAP_H */
|
||||||
|
|||||||
1486
src/libbpf.c
1486
src/libbpf.c
File diff suppressed because it is too large
Load Diff
188
src/libbpf.h
188
src/libbpf.h
@@ -24,8 +24,25 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief **libbpf_major_version()** provides the major version of libbpf.
|
||||||
|
* @return An integer, the major version number
|
||||||
|
*/
|
||||||
LIBBPF_API __u32 libbpf_major_version(void);
|
LIBBPF_API __u32 libbpf_major_version(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief **libbpf_minor_version()** provides the minor version of libbpf.
|
||||||
|
* @return An integer, the minor version number
|
||||||
|
*/
|
||||||
LIBBPF_API __u32 libbpf_minor_version(void);
|
LIBBPF_API __u32 libbpf_minor_version(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief **libbpf_version_string()** provides the version of libbpf in a
|
||||||
|
* human-readable form, e.g., "v1.7".
|
||||||
|
* @return Pointer to a static string containing the version
|
||||||
|
*
|
||||||
|
* The format is *not* a part of a stable API and may change in the future.
|
||||||
|
*/
|
||||||
LIBBPF_API const char *libbpf_version_string(void);
|
LIBBPF_API const char *libbpf_version_string(void);
|
||||||
|
|
||||||
enum libbpf_errno {
|
enum libbpf_errno {
|
||||||
@@ -49,6 +66,14 @@ enum libbpf_errno {
|
|||||||
__LIBBPF_ERRNO__END,
|
__LIBBPF_ERRNO__END,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief **libbpf_strerror()** converts the provided error code into a
|
||||||
|
* human-readable string.
|
||||||
|
* @param err The error code to convert
|
||||||
|
* @param buf Pointer to a buffer where the error message will be stored
|
||||||
|
* @param size The number of bytes in the buffer
|
||||||
|
* @return 0, on success; negative error code, otherwise
|
||||||
|
*/
|
||||||
LIBBPF_API int libbpf_strerror(int err, char *buf, size_t size);
|
LIBBPF_API int libbpf_strerror(int err, char *buf, size_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -152,7 +177,7 @@ struct bpf_object_open_opts {
|
|||||||
* log_buf and log_level settings.
|
* log_buf and log_level settings.
|
||||||
*
|
*
|
||||||
* If specified, this log buffer will be passed for:
|
* If specified, this log buffer will be passed for:
|
||||||
* - each BPF progral load (BPF_PROG_LOAD) attempt, unless overriden
|
* - each BPF progral load (BPF_PROG_LOAD) attempt, unless overridden
|
||||||
* with bpf_program__set_log() on per-program level, to get
|
* with bpf_program__set_log() on per-program level, to get
|
||||||
* BPF verifier log output.
|
* BPF verifier log output.
|
||||||
* - during BPF object's BTF load into kernel (BPF_BTF_LOAD) to get
|
* - during BPF object's BTF load into kernel (BPF_BTF_LOAD) to get
|
||||||
@@ -241,6 +266,19 @@ LIBBPF_API struct bpf_object *
|
|||||||
bpf_object__open_mem(const void *obj_buf, size_t obj_buf_sz,
|
bpf_object__open_mem(const void *obj_buf, size_t obj_buf_sz,
|
||||||
const struct bpf_object_open_opts *opts);
|
const struct bpf_object_open_opts *opts);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief **bpf_object__prepare()** prepares BPF object for loading:
|
||||||
|
* performs ELF processing, relocations, prepares final state of BPF program
|
||||||
|
* instructions (accessible with bpf_program__insns()), creates and
|
||||||
|
* (potentially) pins maps. Leaves BPF object in the state ready for program
|
||||||
|
* loading.
|
||||||
|
* @param obj Pointer to a valid BPF object instance returned by
|
||||||
|
* **bpf_object__open*()** API
|
||||||
|
* @return 0, on success; negative error code, otherwise, error code is
|
||||||
|
* stored in errno
|
||||||
|
*/
|
||||||
|
LIBBPF_API int bpf_object__prepare(struct bpf_object *obj);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief **bpf_object__load()** loads BPF object into kernel.
|
* @brief **bpf_object__load()** loads BPF object into kernel.
|
||||||
* @param obj Pointer to a valid BPF object instance returned by
|
* @param obj Pointer to a valid BPF object instance returned by
|
||||||
@@ -294,6 +332,14 @@ 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);
|
LIBBPF_API int bpf_object__set_kversion(struct bpf_object *obj, __u32 kern_version);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief **bpf_object__token_fd** is an accessor for BPF token FD associated
|
||||||
|
* with BPF object.
|
||||||
|
* @param obj Pointer to a valid BPF object
|
||||||
|
* @return BPF token FD or -1, if it wasn't set
|
||||||
|
*/
|
||||||
|
LIBBPF_API int bpf_object__token_fd(const struct bpf_object *obj);
|
||||||
|
|
||||||
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);
|
||||||
LIBBPF_API int bpf_object__btf_fd(const struct bpf_object *obj);
|
LIBBPF_API int bpf_object__btf_fd(const struct bpf_object *obj);
|
||||||
@@ -402,7 +448,7 @@ LIBBPF_API int bpf_program__pin(struct bpf_program *prog, const char *path);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief **bpf_program__unpin()** unpins the BPF program from a file
|
* @brief **bpf_program__unpin()** unpins the BPF program from a file
|
||||||
* in the BPFFS specified by a path. This decrements the programs
|
* in the BPFFS specified by a path. This decrements program's in-kernel
|
||||||
* reference count.
|
* reference count.
|
||||||
*
|
*
|
||||||
* The file pinning the BPF program can also be unlinked by a different
|
* The file pinning the BPF program can also be unlinked by a different
|
||||||
@@ -435,14 +481,12 @@ LIBBPF_API int bpf_link__pin(struct bpf_link *link, const char *path);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief **bpf_link__unpin()** unpins the BPF link from a file
|
* @brief **bpf_link__unpin()** unpins the BPF link from a file
|
||||||
* in the BPFFS specified by a path. This decrements the links
|
* in the BPFFS. This decrements link's in-kernel reference count.
|
||||||
* reference count.
|
|
||||||
*
|
*
|
||||||
* The file pinning the BPF link can also be unlinked by a different
|
* The file pinning the BPF link can also be unlinked by a different
|
||||||
* process in which case this function will return an error.
|
* process in which case this function will return an error.
|
||||||
*
|
*
|
||||||
* @param prog BPF program to unpin
|
* @param link BPF link to unpin
|
||||||
* @param path file path to the pin in a BPF file system
|
|
||||||
* @return 0, on success; negative error code, otherwise
|
* @return 0, on success; negative error code, otherwise
|
||||||
*/
|
*/
|
||||||
LIBBPF_API int bpf_link__unpin(struct bpf_link *link);
|
LIBBPF_API int bpf_link__unpin(struct bpf_link *link);
|
||||||
@@ -455,7 +499,7 @@ LIBBPF_API int bpf_link__destroy(struct bpf_link *link);
|
|||||||
/**
|
/**
|
||||||
* @brief **bpf_program__attach()** is a generic function for attaching
|
* @brief **bpf_program__attach()** is a generic function for attaching
|
||||||
* a BPF program based on auto-detection of program type, attach type,
|
* a BPF program based on auto-detection of program type, attach type,
|
||||||
* and extra paremeters, where applicable.
|
* and extra parameters, where applicable.
|
||||||
*
|
*
|
||||||
* @param prog BPF program to attach
|
* @param prog BPF program to attach
|
||||||
* @return Reference to the newly created BPF link; or NULL is returned on error,
|
* @return Reference to the newly created BPF link; or NULL is returned on error,
|
||||||
@@ -478,9 +522,11 @@ struct bpf_perf_event_opts {
|
|||||||
__u64 bpf_cookie;
|
__u64 bpf_cookie;
|
||||||
/* don't use BPF link when attach BPF program */
|
/* don't use BPF link when attach BPF program */
|
||||||
bool force_ioctl_attach;
|
bool force_ioctl_attach;
|
||||||
|
/* don't automatically enable the event */
|
||||||
|
bool dont_enable;
|
||||||
size_t :0;
|
size_t :0;
|
||||||
};
|
};
|
||||||
#define bpf_perf_event_opts__last_field force_ioctl_attach
|
#define bpf_perf_event_opts__last_field dont_enable
|
||||||
|
|
||||||
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(const struct bpf_program *prog, int pfd);
|
||||||
@@ -544,10 +590,12 @@ struct bpf_kprobe_multi_opts {
|
|||||||
bool retprobe;
|
bool retprobe;
|
||||||
/* create session kprobes */
|
/* create session kprobes */
|
||||||
bool session;
|
bool session;
|
||||||
|
/* enforce unique match */
|
||||||
|
bool unique_match;
|
||||||
size_t :0;
|
size_t :0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define bpf_kprobe_multi_opts__last_field session
|
#define bpf_kprobe_multi_opts__last_field unique_match
|
||||||
|
|
||||||
LIBBPF_API struct bpf_link *
|
LIBBPF_API struct bpf_link *
|
||||||
bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
|
bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
|
||||||
@@ -569,10 +617,12 @@ struct bpf_uprobe_multi_opts {
|
|||||||
size_t cnt;
|
size_t cnt;
|
||||||
/* create return uprobes */
|
/* create return uprobes */
|
||||||
bool retprobe;
|
bool retprobe;
|
||||||
|
/* create session kprobes */
|
||||||
|
bool session;
|
||||||
size_t :0;
|
size_t :0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define bpf_uprobe_multi_opts__last_field retprobe
|
#define bpf_uprobe_multi_opts__last_field session
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief **bpf_program__attach_uprobe_multi()** attaches a BPF program
|
* @brief **bpf_program__attach_uprobe_multi()** attaches a BPF program
|
||||||
@@ -679,7 +729,7 @@ struct bpf_uprobe_opts {
|
|||||||
/**
|
/**
|
||||||
* @brief **bpf_program__attach_uprobe()** attaches a BPF program
|
* @brief **bpf_program__attach_uprobe()** attaches a BPF program
|
||||||
* to the userspace function which is found by binary path and
|
* to the userspace function which is found by binary path and
|
||||||
* offset. You can optionally specify a particular proccess to attach
|
* offset. You can optionally specify a particular process to attach
|
||||||
* to. You can also optionally attach the program to the function
|
* to. You can also optionally attach the program to the function
|
||||||
* exit instead of entry.
|
* exit instead of entry.
|
||||||
*
|
*
|
||||||
@@ -852,6 +902,21 @@ LIBBPF_API struct bpf_link *
|
|||||||
bpf_program__attach_netkit(const struct bpf_program *prog, int ifindex,
|
bpf_program__attach_netkit(const struct bpf_program *prog, int ifindex,
|
||||||
const struct bpf_netkit_opts *opts);
|
const struct bpf_netkit_opts *opts);
|
||||||
|
|
||||||
|
struct bpf_cgroup_opts {
|
||||||
|
/* size of this struct, for forward/backward compatibility */
|
||||||
|
size_t sz;
|
||||||
|
__u32 flags;
|
||||||
|
__u32 relative_fd;
|
||||||
|
__u32 relative_id;
|
||||||
|
__u64 expected_revision;
|
||||||
|
size_t :0;
|
||||||
|
};
|
||||||
|
#define bpf_cgroup_opts__last_field expected_revision
|
||||||
|
|
||||||
|
LIBBPF_API struct bpf_link *
|
||||||
|
bpf_program__attach_cgroup_opts(const struct bpf_program *prog, int cgroup_fd,
|
||||||
|
const struct bpf_cgroup_opts *opts);
|
||||||
|
|
||||||
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(const struct bpf_map *map);
|
||||||
@@ -915,6 +980,12 @@ LIBBPF_API int bpf_program__set_log_level(struct bpf_program *prog, __u32 log_le
|
|||||||
LIBBPF_API const char *bpf_program__log_buf(const struct bpf_program *prog, size_t *log_size);
|
LIBBPF_API const char *bpf_program__log_buf(const struct bpf_program *prog, size_t *log_size);
|
||||||
LIBBPF_API int bpf_program__set_log_buf(struct bpf_program *prog, char *log_buf, size_t log_size);
|
LIBBPF_API int bpf_program__set_log_buf(struct bpf_program *prog, char *log_buf, size_t log_size);
|
||||||
|
|
||||||
|
LIBBPF_API struct bpf_func_info *bpf_program__func_info(const struct bpf_program *prog);
|
||||||
|
LIBBPF_API __u32 bpf_program__func_info_cnt(const struct bpf_program *prog);
|
||||||
|
|
||||||
|
LIBBPF_API struct bpf_line_info *bpf_program__line_info(const struct bpf_program *prog);
|
||||||
|
LIBBPF_API __u32 bpf_program__line_info_cnt(const struct bpf_program *prog);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief **bpf_program__set_attach_target()** sets BTF-based attach target
|
* @brief **bpf_program__set_attach_target()** sets BTF-based attach target
|
||||||
* for supported BPF program types:
|
* for supported BPF program types:
|
||||||
@@ -922,14 +993,35 @@ LIBBPF_API int bpf_program__set_log_buf(struct bpf_program *prog, char *log_buf,
|
|||||||
* - fentry/fexit/fmod_ret;
|
* - fentry/fexit/fmod_ret;
|
||||||
* - lsm;
|
* - lsm;
|
||||||
* - freplace.
|
* - freplace.
|
||||||
* @param prog BPF program to set the attach type for
|
* @param prog BPF program to configure; must be not yet loaded.
|
||||||
* @param type attach type to set the BPF map to have
|
* @param attach_prog_fd FD of target BPF program (for freplace/extension).
|
||||||
|
* If >0 and func name omitted, defers BTF ID resolution.
|
||||||
|
* @param attach_func_name Target function name. Used either with
|
||||||
|
* attach_prog_fd to find destination BTF type ID in that BPF program, or
|
||||||
|
* alone (no attach_prog_fd) to resolve kernel (vmlinux/module) BTF ID.
|
||||||
|
* Must be provided if attach_prog_fd is 0.
|
||||||
* @return error code; or 0 if no error occurred.
|
* @return error code; or 0 if no error occurred.
|
||||||
*/
|
*/
|
||||||
LIBBPF_API int
|
LIBBPF_API int
|
||||||
bpf_program__set_attach_target(struct bpf_program *prog, int attach_prog_fd,
|
bpf_program__set_attach_target(struct bpf_program *prog, int attach_prog_fd,
|
||||||
const char *attach_func_name);
|
const char *attach_func_name);
|
||||||
|
|
||||||
|
struct bpf_prog_assoc_struct_ops_opts; /* defined in bpf.h */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief **bpf_program__assoc_struct_ops()** associates a BPF program with a
|
||||||
|
* struct_ops map.
|
||||||
|
*
|
||||||
|
* @param prog BPF program
|
||||||
|
* @param map struct_ops map to be associated with the BPF program
|
||||||
|
* @param opts optional options, can be NULL
|
||||||
|
*
|
||||||
|
* @return 0, on success; negative error code, otherwise
|
||||||
|
*/
|
||||||
|
LIBBPF_API int
|
||||||
|
bpf_program__assoc_struct_ops(struct bpf_program *prog, struct bpf_map *map,
|
||||||
|
struct bpf_prog_assoc_struct_ops_opts *opts);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief **bpf_object__find_map_by_name()** returns BPF map of
|
* @brief **bpf_object__find_map_by_name()** returns BPF map of
|
||||||
* the given name, if it exists within the passed BPF object
|
* the given name, if it exists within the passed BPF object
|
||||||
@@ -1025,6 +1117,7 @@ LIBBPF_API __u32 bpf_map__value_size(const struct bpf_map *map);
|
|||||||
/**
|
/**
|
||||||
* @brief **bpf_map__set_value_size()** sets map value size.
|
* @brief **bpf_map__set_value_size()** sets map value size.
|
||||||
* @param map the BPF map instance
|
* @param map the BPF map instance
|
||||||
|
* @param size the new value size
|
||||||
* @return 0, on success; negative error, otherwise
|
* @return 0, on success; negative error, otherwise
|
||||||
*
|
*
|
||||||
* There is a special case for maps with associated memory-mapped regions, like
|
* There is a special case for maps with associated memory-mapped regions, like
|
||||||
@@ -1123,13 +1216,14 @@ LIBBPF_API struct bpf_map *bpf_map__inner_map(struct bpf_map *map);
|
|||||||
* @param key_sz size in bytes of key data, needs to match BPF map definition's **key_size**
|
* @param key_sz size in bytes of key data, needs to match BPF map definition's **key_size**
|
||||||
* @param value pointer to memory in which looked up value will be stored
|
* @param value pointer to memory in which looked up value will be stored
|
||||||
* @param value_sz size in byte of value data memory; it has to match BPF map
|
* @param value_sz size in byte of value data memory; it has to match BPF map
|
||||||
* definition's **value_size**. For per-CPU BPF maps value size has to be
|
* definition's **value_size**. For per-CPU BPF maps, value size can be
|
||||||
* a product of BPF map value size and number of possible CPUs in the system
|
* `value_size` if either **BPF_F_CPU** or **BPF_F_ALL_CPUS** is specified
|
||||||
* (could be fetched with **libbpf_num_possible_cpus()**). Note also that for
|
* in **flags**, otherwise a product of BPF map value size and number of
|
||||||
* per-CPU values value size has to be aligned up to closest 8 bytes for
|
* possible CPUs in the system (could be fetched with
|
||||||
* alignment reasons, so expected size is: `round_up(value_size, 8)
|
* **libbpf_num_possible_cpus()**). Note also that for per-CPU values value
|
||||||
* * libbpf_num_possible_cpus()`.
|
* size has to be aligned up to closest 8 bytes, so expected size is:
|
||||||
* @flags extra flags passed to kernel for this operation
|
* `round_up(value_size, 8) * libbpf_num_possible_cpus()`.
|
||||||
|
* @param flags extra flags passed to kernel for this operation
|
||||||
* @return 0, on success; negative error, otherwise
|
* @return 0, on success; negative error, otherwise
|
||||||
*
|
*
|
||||||
* **bpf_map__lookup_elem()** is high-level equivalent of
|
* **bpf_map__lookup_elem()** is high-level equivalent of
|
||||||
@@ -1146,14 +1240,8 @@ LIBBPF_API int bpf_map__lookup_elem(const struct bpf_map *map,
|
|||||||
* @param key pointer to memory containing bytes of the key
|
* @param key pointer to memory containing bytes of the key
|
||||||
* @param key_sz size in bytes of key data, needs to match BPF map definition's **key_size**
|
* @param key_sz size in bytes of key data, needs to match BPF map definition's **key_size**
|
||||||
* @param value pointer to memory containing bytes of the value
|
* @param value pointer to memory containing bytes of the value
|
||||||
* @param value_sz size in byte of value data memory; it has to match BPF map
|
* @param value_sz refer to **bpf_map__lookup_elem**'s description.'
|
||||||
* definition's **value_size**. For per-CPU BPF maps value size has to be
|
* @param flags extra flags passed to kernel for this operation
|
||||||
* a product of BPF map value size and number of possible CPUs in the system
|
|
||||||
* (could be fetched with **libbpf_num_possible_cpus()**). Note also that for
|
|
||||||
* per-CPU values value size has to be aligned up to closest 8 bytes for
|
|
||||||
* alignment reasons, so expected size is: `round_up(value_size, 8)
|
|
||||||
* * libbpf_num_possible_cpus()`.
|
|
||||||
* @flags extra flags passed to kernel for this operation
|
|
||||||
* @return 0, on success; negative error, otherwise
|
* @return 0, on success; negative error, otherwise
|
||||||
*
|
*
|
||||||
* **bpf_map__update_elem()** is high-level equivalent of
|
* **bpf_map__update_elem()** is high-level equivalent of
|
||||||
@@ -1169,7 +1257,7 @@ LIBBPF_API int bpf_map__update_elem(const struct bpf_map *map,
|
|||||||
* @param map BPF map to delete element from
|
* @param map BPF map to delete element from
|
||||||
* @param key pointer to memory containing bytes of the key
|
* @param key pointer to memory containing bytes of the key
|
||||||
* @param key_sz size in bytes of key data, needs to match BPF map definition's **key_size**
|
* @param key_sz size in bytes of key data, needs to match BPF map definition's **key_size**
|
||||||
* @flags extra flags passed to kernel for this operation
|
* @param flags extra flags passed to kernel for this operation
|
||||||
* @return 0, on success; negative error, otherwise
|
* @return 0, on success; negative error, otherwise
|
||||||
*
|
*
|
||||||
* **bpf_map__delete_elem()** is high-level equivalent of
|
* **bpf_map__delete_elem()** is high-level equivalent of
|
||||||
@@ -1192,7 +1280,7 @@ LIBBPF_API int bpf_map__delete_elem(const struct bpf_map *map,
|
|||||||
* per-CPU values value size has to be aligned up to closest 8 bytes for
|
* per-CPU values value size has to be aligned up to closest 8 bytes for
|
||||||
* alignment reasons, so expected size is: `round_up(value_size, 8)
|
* alignment reasons, so expected size is: `round_up(value_size, 8)
|
||||||
* * libbpf_num_possible_cpus()`.
|
* * libbpf_num_possible_cpus()`.
|
||||||
* @flags extra flags passed to kernel for this operation
|
* @param flags extra flags passed to kernel for this operation
|
||||||
* @return 0, on success; negative error, otherwise
|
* @return 0, on success; negative error, otherwise
|
||||||
*
|
*
|
||||||
* **bpf_map__lookup_and_delete_elem()** is high-level equivalent of
|
* **bpf_map__lookup_and_delete_elem()** is high-level equivalent of
|
||||||
@@ -1218,6 +1306,28 @@ LIBBPF_API int bpf_map__lookup_and_delete_elem(const struct bpf_map *map,
|
|||||||
*/
|
*/
|
||||||
LIBBPF_API int bpf_map__get_next_key(const struct bpf_map *map,
|
LIBBPF_API int bpf_map__get_next_key(const struct bpf_map *map,
|
||||||
const void *cur_key, void *next_key, size_t key_sz);
|
const void *cur_key, void *next_key, size_t key_sz);
|
||||||
|
/**
|
||||||
|
* @brief **bpf_map__set_exclusive_program()** sets a map to be exclusive to the
|
||||||
|
* specified program. This must be called *before* the map is created.
|
||||||
|
*
|
||||||
|
* @param map BPF map to make exclusive.
|
||||||
|
* @param prog BPF program to be the exclusive user of the map. Must belong
|
||||||
|
* to the same bpf_object as the map.
|
||||||
|
* @return 0 on success; a negative error code otherwise.
|
||||||
|
*
|
||||||
|
* This function must be called after the BPF object is opened but before
|
||||||
|
* it is loaded. Once the object is loaded, only the specified program
|
||||||
|
* will be able to access the map's contents.
|
||||||
|
*/
|
||||||
|
LIBBPF_API int bpf_map__set_exclusive_program(struct bpf_map *map, struct bpf_program *prog);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief **bpf_map__exclusive_program()** returns the exclusive program
|
||||||
|
* that is registered with the map (if any).
|
||||||
|
* @param map BPF map to which the exclusive program is registered.
|
||||||
|
* @return the registered exclusive program.
|
||||||
|
*/
|
||||||
|
LIBBPF_API struct bpf_program *bpf_map__exclusive_program(struct bpf_map *map);
|
||||||
|
|
||||||
struct bpf_xdp_set_link_opts {
|
struct bpf_xdp_set_link_opts {
|
||||||
size_t sz;
|
size_t sz;
|
||||||
@@ -1258,6 +1368,7 @@ enum bpf_tc_attach_point {
|
|||||||
BPF_TC_INGRESS = 1 << 0,
|
BPF_TC_INGRESS = 1 << 0,
|
||||||
BPF_TC_EGRESS = 1 << 1,
|
BPF_TC_EGRESS = 1 << 1,
|
||||||
BPF_TC_CUSTOM = 1 << 2,
|
BPF_TC_CUSTOM = 1 << 2,
|
||||||
|
BPF_TC_QDISC = 1 << 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BPF_TC_PARENT(a, b) \
|
#define BPF_TC_PARENT(a, b) \
|
||||||
@@ -1272,9 +1383,11 @@ struct bpf_tc_hook {
|
|||||||
int ifindex;
|
int ifindex;
|
||||||
enum bpf_tc_attach_point attach_point;
|
enum bpf_tc_attach_point attach_point;
|
||||||
__u32 parent;
|
__u32 parent;
|
||||||
|
__u32 handle;
|
||||||
|
const char *qdisc;
|
||||||
size_t :0;
|
size_t :0;
|
||||||
};
|
};
|
||||||
#define bpf_tc_hook__last_field parent
|
#define bpf_tc_hook__last_field qdisc
|
||||||
|
|
||||||
struct bpf_tc_opts {
|
struct bpf_tc_opts {
|
||||||
size_t sz;
|
size_t sz;
|
||||||
@@ -1539,6 +1652,7 @@ struct perf_buffer_opts {
|
|||||||
* @param sample_cb function called on each received data record
|
* @param sample_cb function called on each received data record
|
||||||
* @param lost_cb function called when record loss has occurred
|
* @param lost_cb function called when record loss has occurred
|
||||||
* @param ctx user-provided extra context passed into *sample_cb* and *lost_cb*
|
* @param ctx user-provided extra context passed into *sample_cb* and *lost_cb*
|
||||||
|
* @param opts optional parameters for the perf buffer, can be null
|
||||||
* @return a new instance of struct perf_buffer on success, NULL on error with
|
* @return a new instance of struct perf_buffer on success, NULL on error with
|
||||||
* *errno* containing an error code
|
* *errno* containing an error code
|
||||||
*/
|
*/
|
||||||
@@ -1593,11 +1707,11 @@ LIBBPF_API int perf_buffer__buffer_fd(const struct perf_buffer *pb, size_t buf_i
|
|||||||
* memory region of the ring buffer.
|
* memory region of the ring buffer.
|
||||||
* This ring buffer can be used to implement a custom events consumer.
|
* This ring buffer can be used to implement a custom events consumer.
|
||||||
* The ring buffer starts with the *struct perf_event_mmap_page*, which
|
* The ring buffer starts with the *struct perf_event_mmap_page*, which
|
||||||
* holds the ring buffer managment fields, when accessing the header
|
* holds the ring buffer management fields, when accessing the header
|
||||||
* structure it's important to be SMP aware.
|
* structure it's important to be SMP aware.
|
||||||
* You can refer to *perf_event_read_simple* for a simple example.
|
* You can refer to *perf_event_read_simple* for a simple example.
|
||||||
* @param pb the perf buffer structure
|
* @param pb the perf buffer structure
|
||||||
* @param buf_idx the buffer index to retreive
|
* @param buf_idx the buffer index to retrieve
|
||||||
* @param buf (out) gets the base pointer of the mmap()'ed memory
|
* @param buf (out) gets the base pointer of the mmap()'ed memory
|
||||||
* @param buf_size (out) gets the size of the mmap()'ed region
|
* @param buf_size (out) gets the size of the mmap()'ed region
|
||||||
* @return 0 on success, negative error code for failure
|
* @return 0 on success, negative error code for failure
|
||||||
@@ -1759,9 +1873,10 @@ struct gen_loader_opts {
|
|||||||
const char *insns;
|
const char *insns;
|
||||||
__u32 data_sz;
|
__u32 data_sz;
|
||||||
__u32 insns_sz;
|
__u32 insns_sz;
|
||||||
|
bool gen_hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define gen_loader_opts__last_field insns_sz
|
#define gen_loader_opts__last_field gen_hash
|
||||||
LIBBPF_API int bpf_object__gen_loader(struct bpf_object *obj,
|
LIBBPF_API int bpf_object__gen_loader(struct bpf_object *obj,
|
||||||
struct gen_loader_opts *opts);
|
struct gen_loader_opts *opts);
|
||||||
|
|
||||||
@@ -1786,9 +1901,14 @@ struct bpf_linker_file_opts {
|
|||||||
struct bpf_linker;
|
struct bpf_linker;
|
||||||
|
|
||||||
LIBBPF_API struct bpf_linker *bpf_linker__new(const char *filename, struct bpf_linker_opts *opts);
|
LIBBPF_API struct bpf_linker *bpf_linker__new(const char *filename, struct bpf_linker_opts *opts);
|
||||||
|
LIBBPF_API struct bpf_linker *bpf_linker__new_fd(int fd, struct bpf_linker_opts *opts);
|
||||||
LIBBPF_API int bpf_linker__add_file(struct bpf_linker *linker,
|
LIBBPF_API int bpf_linker__add_file(struct bpf_linker *linker,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
const struct bpf_linker_file_opts *opts);
|
const struct bpf_linker_file_opts *opts);
|
||||||
|
LIBBPF_API int bpf_linker__add_fd(struct bpf_linker *linker, int fd,
|
||||||
|
const struct bpf_linker_file_opts *opts);
|
||||||
|
LIBBPF_API int bpf_linker__add_buf(struct bpf_linker *linker, void *buf, size_t buf_sz,
|
||||||
|
const struct bpf_linker_file_opts *opts);
|
||||||
LIBBPF_API int bpf_linker__finalize(struct bpf_linker *linker);
|
LIBBPF_API int bpf_linker__finalize(struct bpf_linker *linker);
|
||||||
LIBBPF_API void bpf_linker__free(struct bpf_linker *linker);
|
LIBBPF_API void bpf_linker__free(struct bpf_linker *linker);
|
||||||
|
|
||||||
|
|||||||
@@ -421,9 +421,37 @@ LIBBPF_1.5.0 {
|
|||||||
global:
|
global:
|
||||||
btf__distill_base;
|
btf__distill_base;
|
||||||
btf__relocate;
|
btf__relocate;
|
||||||
|
btf_ext__endianness;
|
||||||
|
btf_ext__set_endianness;
|
||||||
bpf_map__autoattach;
|
bpf_map__autoattach;
|
||||||
bpf_map__set_autoattach;
|
bpf_map__set_autoattach;
|
||||||
|
bpf_object__token_fd;
|
||||||
bpf_program__attach_sockmap;
|
bpf_program__attach_sockmap;
|
||||||
ring__consume_n;
|
ring__consume_n;
|
||||||
ring_buffer__consume_n;
|
ring_buffer__consume_n;
|
||||||
} LIBBPF_1.4.0;
|
} LIBBPF_1.4.0;
|
||||||
|
|
||||||
|
LIBBPF_1.6.0 {
|
||||||
|
global:
|
||||||
|
bpf_linker__add_buf;
|
||||||
|
bpf_linker__add_fd;
|
||||||
|
bpf_linker__new_fd;
|
||||||
|
bpf_object__prepare;
|
||||||
|
bpf_prog_stream_read;
|
||||||
|
bpf_program__attach_cgroup_opts;
|
||||||
|
bpf_program__func_info;
|
||||||
|
bpf_program__func_info_cnt;
|
||||||
|
bpf_program__line_info;
|
||||||
|
bpf_program__line_info_cnt;
|
||||||
|
btf__add_decl_attr;
|
||||||
|
btf__add_type_attr;
|
||||||
|
} LIBBPF_1.5.0;
|
||||||
|
|
||||||
|
LIBBPF_1.7.0 {
|
||||||
|
global:
|
||||||
|
bpf_map__set_exclusive_program;
|
||||||
|
bpf_map__exclusive_program;
|
||||||
|
bpf_prog_assoc_struct_ops;
|
||||||
|
bpf_program__assoc_struct_ops;
|
||||||
|
btf__permute;
|
||||||
|
} LIBBPF_1.6.0;
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
|
|
||||||
* Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
|
|
||||||
* Copyright (C) 2015 Huawei Inc.
|
|
||||||
* Copyright (C) 2017 Nicira, Inc.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#undef _GNU_SOURCE
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "libbpf.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
|
|
||||||
|
|
||||||
#define ERRNO_OFFSET(e) ((e) - __LIBBPF_ERRNO__START)
|
|
||||||
#define ERRCODE_OFFSET(c) ERRNO_OFFSET(LIBBPF_ERRNO__##c)
|
|
||||||
#define NR_ERRNO (__LIBBPF_ERRNO__END - __LIBBPF_ERRNO__START)
|
|
||||||
|
|
||||||
static const char *libbpf_strerror_table[NR_ERRNO] = {
|
|
||||||
[ERRCODE_OFFSET(LIBELF)] = "Something wrong in libelf",
|
|
||||||
[ERRCODE_OFFSET(FORMAT)] = "BPF object format invalid",
|
|
||||||
[ERRCODE_OFFSET(KVERSION)] = "'version' section incorrect or lost",
|
|
||||||
[ERRCODE_OFFSET(ENDIAN)] = "Endian mismatch",
|
|
||||||
[ERRCODE_OFFSET(INTERNAL)] = "Internal error in libbpf",
|
|
||||||
[ERRCODE_OFFSET(RELOC)] = "Relocation failed",
|
|
||||||
[ERRCODE_OFFSET(VERIFY)] = "Kernel verifier blocks program loading",
|
|
||||||
[ERRCODE_OFFSET(PROG2BIG)] = "Program too big",
|
|
||||||
[ERRCODE_OFFSET(KVER)] = "Incorrect kernel version",
|
|
||||||
[ERRCODE_OFFSET(PROGTYPE)] = "Kernel doesn't support this program type",
|
|
||||||
[ERRCODE_OFFSET(WRNGPID)] = "Wrong pid in netlink message",
|
|
||||||
[ERRCODE_OFFSET(INVSEQ)] = "Invalid netlink sequence",
|
|
||||||
[ERRCODE_OFFSET(NLPARSE)] = "Incorrect netlink message parsing",
|
|
||||||
};
|
|
||||||
|
|
||||||
int libbpf_strerror(int err, char *buf, size_t size)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (!buf || !size)
|
|
||||||
return libbpf_err(-EINVAL);
|
|
||||||
|
|
||||||
err = err > 0 ? err : -err;
|
|
||||||
|
|
||||||
if (err < __LIBBPF_ERRNO__START) {
|
|
||||||
ret = strerror_r(err, buf, size);
|
|
||||||
buf[size - 1] = '\0';
|
|
||||||
return libbpf_err_errno(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err < __LIBBPF_ERRNO__END) {
|
|
||||||
const char *msg;
|
|
||||||
|
|
||||||
msg = libbpf_strerror_table[ERRNO_OFFSET(err)];
|
|
||||||
ret = snprintf(buf, size, "%s", msg);
|
|
||||||
buf[size - 1] = '\0';
|
|
||||||
/* The length of the buf and msg is positive.
|
|
||||||
* A negative number may be returned only when the
|
|
||||||
* size exceeds INT_MAX. Not likely to appear.
|
|
||||||
*/
|
|
||||||
if (ret >= size)
|
|
||||||
return libbpf_err(-ERANGE);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = snprintf(buf, size, "Unknown libbpf error %d", err);
|
|
||||||
buf[size - 1] = '\0';
|
|
||||||
if (ret >= size)
|
|
||||||
return libbpf_err(-ERANGE);
|
|
||||||
return libbpf_err(-ENOENT);
|
|
||||||
}
|
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
#define __LIBBPF_LIBBPF_INTERNAL_H
|
#define __LIBBPF_LIBBPF_INTERNAL_H
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <byteswap.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
@@ -73,6 +74,8 @@
|
|||||||
#define ELF64_ST_VISIBILITY(o) ((o) & 0x03)
|
#define ELF64_ST_VISIBILITY(o) ((o) & 0x03)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define JUMPTABLES_SEC ".jumptables"
|
||||||
|
|
||||||
#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))
|
||||||
#define BTF_TYPE_ENC(name, info, size_or_type) (name), (info), (size_or_type)
|
#define BTF_TYPE_ENC(name, info, size_or_type) (name), (info), (size_or_type)
|
||||||
@@ -171,6 +174,16 @@ 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__)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief **libbpf_errstr()** returns string corresponding to numeric errno
|
||||||
|
* @param err negative numeric errno
|
||||||
|
* @return pointer to string representation of the errno, that is invalidated
|
||||||
|
* upon the next call.
|
||||||
|
*/
|
||||||
|
const char *libbpf_errstr(int err);
|
||||||
|
|
||||||
|
#define errstr(err) libbpf_errstr(err)
|
||||||
|
|
||||||
#ifndef __has_builtin
|
#ifndef __has_builtin
|
||||||
#define __has_builtin(x) 0
|
#define __has_builtin(x) 0
|
||||||
#endif
|
#endif
|
||||||
@@ -408,6 +421,7 @@ int libbpf__load_raw_btf(const char *raw_types, size_t types_len,
|
|||||||
int btf_load_into_kernel(struct btf *btf,
|
int btf_load_into_kernel(struct btf *btf,
|
||||||
char *log_buf, size_t log_sz, __u32 log_level,
|
char *log_buf, size_t log_sz, __u32 log_level,
|
||||||
int token_fd);
|
int token_fd);
|
||||||
|
struct btf *btf_load_from_kernel(__u32 id, struct btf *base_btf, int token_fd);
|
||||||
|
|
||||||
struct btf *btf_get_from_fd(int btf_fd, struct btf *base_btf);
|
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,
|
void btf_get_kernel_prefix_kind(enum bpf_attach_type attach_type,
|
||||||
@@ -448,11 +462,11 @@ struct btf_ext_info {
|
|||||||
*
|
*
|
||||||
* The func_info subsection layout:
|
* The func_info subsection layout:
|
||||||
* record size for struct bpf_func_info in the func_info subsection
|
* record size for struct bpf_func_info in the func_info subsection
|
||||||
* struct btf_sec_func_info for section #1
|
* struct btf_ext_info_sec for section #1
|
||||||
* a list of bpf_func_info records 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
|
* where struct bpf_func_info mimics one in include/uapi/linux/bpf.h
|
||||||
* but may not be identical
|
* but may not be identical
|
||||||
* struct btf_sec_func_info for section #2
|
* struct btf_ext_info_sec for section #2
|
||||||
* a list of bpf_func_info records for section #2
|
* a list of bpf_func_info records for section #2
|
||||||
* ......
|
* ......
|
||||||
*
|
*
|
||||||
@@ -484,6 +498,8 @@ struct btf_ext {
|
|||||||
struct btf_ext_header *hdr;
|
struct btf_ext_header *hdr;
|
||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
void *data_swapped;
|
||||||
|
bool swapped_endian;
|
||||||
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 core_relo_info;
|
||||||
@@ -511,6 +527,32 @@ struct bpf_line_info_min {
|
|||||||
__u32 line_col;
|
__u32 line_col;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Functions to byte-swap info records */
|
||||||
|
|
||||||
|
typedef void (*info_rec_bswap_fn)(void *);
|
||||||
|
|
||||||
|
static inline void bpf_func_info_bswap(struct bpf_func_info *i)
|
||||||
|
{
|
||||||
|
i->insn_off = bswap_32(i->insn_off);
|
||||||
|
i->type_id = bswap_32(i->type_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bpf_line_info_bswap(struct bpf_line_info *i)
|
||||||
|
{
|
||||||
|
i->insn_off = bswap_32(i->insn_off);
|
||||||
|
i->file_name_off = bswap_32(i->file_name_off);
|
||||||
|
i->line_off = bswap_32(i->line_off);
|
||||||
|
i->line_col = bswap_32(i->line_col);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bpf_core_relo_bswap(struct bpf_core_relo *i)
|
||||||
|
{
|
||||||
|
i->insn_off = bswap_32(i->insn_off);
|
||||||
|
i->type_id = bswap_32(i->type_id);
|
||||||
|
i->access_str_off = bswap_32(i->access_str_off);
|
||||||
|
i->kind = bswap_32(i->kind);
|
||||||
|
}
|
||||||
|
|
||||||
enum btf_field_iter_kind {
|
enum btf_field_iter_kind {
|
||||||
BTF_FIELD_ITER_IDS,
|
BTF_FIELD_ITER_IDS,
|
||||||
BTF_FIELD_ITER_STRS,
|
BTF_FIELD_ITER_STRS,
|
||||||
@@ -588,6 +630,16 @@ static inline bool is_ldimm64_insn(struct bpf_insn *insn)
|
|||||||
return insn->code == (BPF_LD | BPF_IMM | BPF_DW);
|
return insn->code == (BPF_LD | BPF_IMM | BPF_DW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void bpf_insn_bswap(struct bpf_insn *insn)
|
||||||
|
{
|
||||||
|
__u8 tmp_reg = insn->dst_reg;
|
||||||
|
|
||||||
|
insn->dst_reg = insn->src_reg;
|
||||||
|
insn->src_reg = tmp_reg;
|
||||||
|
insn->off = bswap_16(insn->off);
|
||||||
|
insn->imm = bswap_32(insn->imm);
|
||||||
|
}
|
||||||
|
|
||||||
/* Unconditionally dup FD, ensuring it doesn't use [0, 2] range.
|
/* Unconditionally dup FD, ensuring it doesn't use [0, 2] range.
|
||||||
* Original FD is not closed or altered in any other way.
|
* Original FD is not closed or altered in any other way.
|
||||||
* Preserves original FD value, if it's invalid (negative).
|
* Preserves original FD value, if it's invalid (negative).
|
||||||
@@ -627,6 +679,15 @@ static inline int sys_dup3(int oldfd, int newfd, int flags)
|
|||||||
return syscall(__NR_dup3, oldfd, newfd, flags);
|
return syscall(__NR_dup3, oldfd, newfd, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Some versions of Android don't provide memfd_create() in their libc
|
||||||
|
* implementation, so avoid complications and just go straight to Linux
|
||||||
|
* syscall.
|
||||||
|
*/
|
||||||
|
static inline int sys_memfd_create(const char *name, unsigned flags)
|
||||||
|
{
|
||||||
|
return syscall(__NR_memfd_create, name, flags);
|
||||||
|
}
|
||||||
|
|
||||||
/* Point *fixed_fd* to the same file that *tmp_fd* points to.
|
/* Point *fixed_fd* to the same file that *tmp_fd* points to.
|
||||||
* Regardless of success, *tmp_fd* is closed.
|
* Regardless of success, *tmp_fd* is closed.
|
||||||
* Whatever *fixed_fd* pointed to is closed silently.
|
* Whatever *fixed_fd* pointed to is closed silently.
|
||||||
@@ -663,6 +724,11 @@ static inline bool is_pow_of_2(size_t x)
|
|||||||
return x && (x & (x - 1)) == 0;
|
return x && (x & (x - 1)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline __u32 ror32(__u32 v, int bits)
|
||||||
|
{
|
||||||
|
return (v >> bits) | (v << (32 - bits));
|
||||||
|
}
|
||||||
|
|
||||||
#define PROG_LOAD_ATTEMPTS 5
|
#define PROG_LOAD_ATTEMPTS 5
|
||||||
int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts);
|
int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts);
|
||||||
|
|
||||||
@@ -687,4 +753,8 @@ int elf_resolve_pattern_offsets(const char *binary_path, const char *pattern,
|
|||||||
|
|
||||||
int probe_fd(int fd);
|
int probe_fd(int fd);
|
||||||
|
|
||||||
|
#define SHA256_DIGEST_LENGTH 32
|
||||||
|
#define SHA256_DWORD_SIZE SHA256_DIGEST_LENGTH / sizeof(__u64)
|
||||||
|
|
||||||
|
void libbpf_sha256(const void *data, size_t len, __u8 out[SHA256_DIGEST_LENGTH]);
|
||||||
#endif /* __LIBBPF_LIBBPF_INTERNAL_H */
|
#endif /* __LIBBPF_LIBBPF_INTERNAL_H */
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ enum libbpf_strict_mode {
|
|||||||
* first BPF program or map creation operation. This is done only if
|
* first BPF program or map creation operation. This is done only if
|
||||||
* kernel is too old to support memcg-based memory accounting for BPF
|
* kernel is too old to support memcg-based memory accounting for BPF
|
||||||
* subsystem. By default, RLIMIT_MEMLOCK limit is set to RLIM_INFINITY,
|
* subsystem. By default, RLIMIT_MEMLOCK limit is set to RLIM_INFINITY,
|
||||||
* but it can be overriden with libbpf_set_memlock_rlim() API.
|
* but it can be overridden with libbpf_set_memlock_rlim() API.
|
||||||
* Note that libbpf_set_memlock_rlim() needs to be called before
|
* Note that libbpf_set_memlock_rlim() needs to be called before
|
||||||
* the very first bpf_prog_load(), bpf_map_create() or bpf_object__load()
|
* the very first bpf_prog_load(), bpf_map_create() or bpf_object__load()
|
||||||
* operation.
|
* operation.
|
||||||
@@ -97,7 +97,7 @@ LIBBPF_API int libbpf_set_strict_mode(enum libbpf_strict_mode mode);
|
|||||||
* @brief **libbpf_get_error()** extracts the error code from the passed
|
* @brief **libbpf_get_error()** extracts the error code from the passed
|
||||||
* pointer
|
* pointer
|
||||||
* @param ptr pointer returned from libbpf API function
|
* @param ptr pointer returned from libbpf API function
|
||||||
* @return error code; or 0 if no error occured
|
* @return error code; or 0 if no error occurred
|
||||||
*
|
*
|
||||||
* Note, as of libbpf 1.0 this function is not necessary and not recommended
|
* Note, as of libbpf 1.0 this function is not necessary and not recommended
|
||||||
* to be used. Libbpf doesn't return error code embedded into the pointer
|
* to be used. Libbpf doesn't return error code embedded into the pointer
|
||||||
|
|||||||
@@ -364,6 +364,10 @@ static int probe_map_create(enum bpf_map_type map_type)
|
|||||||
case BPF_MAP_TYPE_SOCKHASH:
|
case BPF_MAP_TYPE_SOCKHASH:
|
||||||
case BPF_MAP_TYPE_REUSEPORT_SOCKARRAY:
|
case BPF_MAP_TYPE_REUSEPORT_SOCKARRAY:
|
||||||
break;
|
break;
|
||||||
|
case BPF_MAP_TYPE_INSN_ARRAY:
|
||||||
|
key_size = sizeof(__u32);
|
||||||
|
value_size = sizeof(struct bpf_insn_array_value);
|
||||||
|
break;
|
||||||
case BPF_MAP_TYPE_UNSPEC:
|
case BPF_MAP_TYPE_UNSPEC:
|
||||||
default:
|
default:
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|||||||
256
src/libbpf_utils.c
Normal file
256
src/libbpf_utils.c
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
|
||||||
|
* Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
|
||||||
|
* Copyright (C) 2015 Huawei Inc.
|
||||||
|
* Copyright (C) 2017 Nicira, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef _GNU_SOURCE
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
|
||||||
|
#include "libbpf.h"
|
||||||
|
#include "libbpf_internal.h"
|
||||||
|
|
||||||
|
#ifndef ENOTSUPP
|
||||||
|
#define ENOTSUPP 524
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* make sure libbpf doesn't use kernel-only integer typedefs */
|
||||||
|
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
|
||||||
|
|
||||||
|
#define ERRNO_OFFSET(e) ((e) - __LIBBPF_ERRNO__START)
|
||||||
|
#define ERRCODE_OFFSET(c) ERRNO_OFFSET(LIBBPF_ERRNO__##c)
|
||||||
|
#define NR_ERRNO (__LIBBPF_ERRNO__END - __LIBBPF_ERRNO__START)
|
||||||
|
|
||||||
|
static const char *libbpf_strerror_table[NR_ERRNO] = {
|
||||||
|
[ERRCODE_OFFSET(LIBELF)] = "Something wrong in libelf",
|
||||||
|
[ERRCODE_OFFSET(FORMAT)] = "BPF object format invalid",
|
||||||
|
[ERRCODE_OFFSET(KVERSION)] = "'version' section incorrect or lost",
|
||||||
|
[ERRCODE_OFFSET(ENDIAN)] = "Endian mismatch",
|
||||||
|
[ERRCODE_OFFSET(INTERNAL)] = "Internal error in libbpf",
|
||||||
|
[ERRCODE_OFFSET(RELOC)] = "Relocation failed",
|
||||||
|
[ERRCODE_OFFSET(VERIFY)] = "Kernel verifier blocks program loading",
|
||||||
|
[ERRCODE_OFFSET(PROG2BIG)] = "Program too big",
|
||||||
|
[ERRCODE_OFFSET(KVER)] = "Incorrect kernel version",
|
||||||
|
[ERRCODE_OFFSET(PROGTYPE)] = "Kernel doesn't support this program type",
|
||||||
|
[ERRCODE_OFFSET(WRNGPID)] = "Wrong pid in netlink message",
|
||||||
|
[ERRCODE_OFFSET(INVSEQ)] = "Invalid netlink sequence",
|
||||||
|
[ERRCODE_OFFSET(NLPARSE)] = "Incorrect netlink message parsing",
|
||||||
|
};
|
||||||
|
|
||||||
|
int libbpf_strerror(int err, char *buf, size_t size)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!buf || !size)
|
||||||
|
return libbpf_err(-EINVAL);
|
||||||
|
|
||||||
|
err = err > 0 ? err : -err;
|
||||||
|
|
||||||
|
if (err < __LIBBPF_ERRNO__START) {
|
||||||
|
ret = strerror_r(err, buf, size);
|
||||||
|
buf[size - 1] = '\0';
|
||||||
|
return libbpf_err_errno(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err < __LIBBPF_ERRNO__END) {
|
||||||
|
const char *msg;
|
||||||
|
|
||||||
|
msg = libbpf_strerror_table[ERRNO_OFFSET(err)];
|
||||||
|
ret = snprintf(buf, size, "%s", msg);
|
||||||
|
buf[size - 1] = '\0';
|
||||||
|
/* The length of the buf and msg is positive.
|
||||||
|
* A negative number may be returned only when the
|
||||||
|
* size exceeds INT_MAX. Not likely to appear.
|
||||||
|
*/
|
||||||
|
if (ret >= size)
|
||||||
|
return libbpf_err(-ERANGE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = snprintf(buf, size, "Unknown libbpf error %d", err);
|
||||||
|
buf[size - 1] = '\0';
|
||||||
|
if (ret >= size)
|
||||||
|
return libbpf_err(-ERANGE);
|
||||||
|
return libbpf_err(-ENOENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *libbpf_errstr(int err)
|
||||||
|
{
|
||||||
|
static __thread char buf[12];
|
||||||
|
|
||||||
|
if (err > 0)
|
||||||
|
err = -err;
|
||||||
|
|
||||||
|
switch (err) {
|
||||||
|
case -E2BIG: return "-E2BIG";
|
||||||
|
case -EACCES: return "-EACCES";
|
||||||
|
case -EADDRINUSE: return "-EADDRINUSE";
|
||||||
|
case -EADDRNOTAVAIL: return "-EADDRNOTAVAIL";
|
||||||
|
case -EAGAIN: return "-EAGAIN";
|
||||||
|
case -EALREADY: return "-EALREADY";
|
||||||
|
case -EBADF: return "-EBADF";
|
||||||
|
case -EBADFD: return "-EBADFD";
|
||||||
|
case -EBUSY: return "-EBUSY";
|
||||||
|
case -ECANCELED: return "-ECANCELED";
|
||||||
|
case -ECHILD: return "-ECHILD";
|
||||||
|
case -EDEADLK: return "-EDEADLK";
|
||||||
|
case -EDOM: return "-EDOM";
|
||||||
|
case -EEXIST: return "-EEXIST";
|
||||||
|
case -EFAULT: return "-EFAULT";
|
||||||
|
case -EFBIG: return "-EFBIG";
|
||||||
|
case -EILSEQ: return "-EILSEQ";
|
||||||
|
case -EINPROGRESS: return "-EINPROGRESS";
|
||||||
|
case -EINTR: return "-EINTR";
|
||||||
|
case -EINVAL: return "-EINVAL";
|
||||||
|
case -EIO: return "-EIO";
|
||||||
|
case -EISDIR: return "-EISDIR";
|
||||||
|
case -ELOOP: return "-ELOOP";
|
||||||
|
case -EMFILE: return "-EMFILE";
|
||||||
|
case -EMLINK: return "-EMLINK";
|
||||||
|
case -EMSGSIZE: return "-EMSGSIZE";
|
||||||
|
case -ENAMETOOLONG: return "-ENAMETOOLONG";
|
||||||
|
case -ENFILE: return "-ENFILE";
|
||||||
|
case -ENODATA: return "-ENODATA";
|
||||||
|
case -ENODEV: return "-ENODEV";
|
||||||
|
case -ENOENT: return "-ENOENT";
|
||||||
|
case -ENOEXEC: return "-ENOEXEC";
|
||||||
|
case -ENOLINK: return "-ENOLINK";
|
||||||
|
case -ENOMEM: return "-ENOMEM";
|
||||||
|
case -ENOSPC: return "-ENOSPC";
|
||||||
|
case -ENOTBLK: return "-ENOTBLK";
|
||||||
|
case -ENOTDIR: return "-ENOTDIR";
|
||||||
|
case -ENOTSUPP: return "-ENOTSUPP";
|
||||||
|
case -ENOTTY: return "-ENOTTY";
|
||||||
|
case -ENXIO: return "-ENXIO";
|
||||||
|
case -EOPNOTSUPP: return "-EOPNOTSUPP";
|
||||||
|
case -EOVERFLOW: return "-EOVERFLOW";
|
||||||
|
case -EPERM: return "-EPERM";
|
||||||
|
case -EPIPE: return "-EPIPE";
|
||||||
|
case -EPROTO: return "-EPROTO";
|
||||||
|
case -EPROTONOSUPPORT: return "-EPROTONOSUPPORT";
|
||||||
|
case -ERANGE: return "-ERANGE";
|
||||||
|
case -EROFS: return "-EROFS";
|
||||||
|
case -ESPIPE: return "-ESPIPE";
|
||||||
|
case -ESRCH: return "-ESRCH";
|
||||||
|
case -ETXTBSY: return "-ETXTBSY";
|
||||||
|
case -EUCLEAN: return "-EUCLEAN";
|
||||||
|
case -EXDEV: return "-EXDEV";
|
||||||
|
default:
|
||||||
|
snprintf(buf, sizeof(buf), "%d", err);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __u32 get_unaligned_be32(const void *p)
|
||||||
|
{
|
||||||
|
__be32 val;
|
||||||
|
|
||||||
|
memcpy(&val, p, sizeof(val));
|
||||||
|
return be32_to_cpu(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void put_unaligned_be32(__u32 val, void *p)
|
||||||
|
{
|
||||||
|
__be32 be_val = cpu_to_be32(val);
|
||||||
|
|
||||||
|
memcpy(p, &be_val, sizeof(be_val));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SHA256_BLOCK_LENGTH 64
|
||||||
|
#define Ch(x, y, z) (((x) & (y)) ^ (~(x) & (z)))
|
||||||
|
#define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
|
||||||
|
#define Sigma_0(x) (ror32((x), 2) ^ ror32((x), 13) ^ ror32((x), 22))
|
||||||
|
#define Sigma_1(x) (ror32((x), 6) ^ ror32((x), 11) ^ ror32((x), 25))
|
||||||
|
#define sigma_0(x) (ror32((x), 7) ^ ror32((x), 18) ^ ((x) >> 3))
|
||||||
|
#define sigma_1(x) (ror32((x), 17) ^ ror32((x), 19) ^ ((x) >> 10))
|
||||||
|
|
||||||
|
static const __u32 sha256_K[64] = {
|
||||||
|
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
|
||||||
|
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||||
|
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
|
||||||
|
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||||
|
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
|
||||||
|
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||||
|
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
|
||||||
|
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||||
|
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
|
||||||
|
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||||
|
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SHA256_ROUND(i, a, b, c, d, e, f, g, h) \
|
||||||
|
{ \
|
||||||
|
__u32 tmp = h + Sigma_1(e) + Ch(e, f, g) + sha256_K[i] + w[i]; \
|
||||||
|
d += tmp; \
|
||||||
|
h = tmp + Sigma_0(a) + Maj(a, b, c); \
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sha256_blocks(__u32 state[8], const __u8 *data, size_t nblocks)
|
||||||
|
{
|
||||||
|
while (nblocks--) {
|
||||||
|
__u32 a = state[0];
|
||||||
|
__u32 b = state[1];
|
||||||
|
__u32 c = state[2];
|
||||||
|
__u32 d = state[3];
|
||||||
|
__u32 e = state[4];
|
||||||
|
__u32 f = state[5];
|
||||||
|
__u32 g = state[6];
|
||||||
|
__u32 h = state[7];
|
||||||
|
__u32 w[64];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
w[i] = get_unaligned_be32(&data[4 * i]);
|
||||||
|
for (; i < ARRAY_SIZE(w); i++)
|
||||||
|
w[i] = sigma_1(w[i - 2]) + w[i - 7] +
|
||||||
|
sigma_0(w[i - 15]) + w[i - 16];
|
||||||
|
for (i = 0; i < ARRAY_SIZE(w); i += 8) {
|
||||||
|
SHA256_ROUND(i + 0, a, b, c, d, e, f, g, h);
|
||||||
|
SHA256_ROUND(i + 1, h, a, b, c, d, e, f, g);
|
||||||
|
SHA256_ROUND(i + 2, g, h, a, b, c, d, e, f);
|
||||||
|
SHA256_ROUND(i + 3, f, g, h, a, b, c, d, e);
|
||||||
|
SHA256_ROUND(i + 4, e, f, g, h, a, b, c, d);
|
||||||
|
SHA256_ROUND(i + 5, d, e, f, g, h, a, b, c);
|
||||||
|
SHA256_ROUND(i + 6, c, d, e, f, g, h, a, b);
|
||||||
|
SHA256_ROUND(i + 7, b, c, d, e, f, g, h, a);
|
||||||
|
}
|
||||||
|
state[0] += a;
|
||||||
|
state[1] += b;
|
||||||
|
state[2] += c;
|
||||||
|
state[3] += d;
|
||||||
|
state[4] += e;
|
||||||
|
state[5] += f;
|
||||||
|
state[6] += g;
|
||||||
|
state[7] += h;
|
||||||
|
data += SHA256_BLOCK_LENGTH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void libbpf_sha256(const void *data, size_t len, __u8 out[SHA256_DIGEST_LENGTH])
|
||||||
|
{
|
||||||
|
__u32 state[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
||||||
|
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
|
||||||
|
const __be64 bitcount = cpu_to_be64((__u64)len * 8);
|
||||||
|
__u8 final_data[2 * SHA256_BLOCK_LENGTH] = { 0 };
|
||||||
|
size_t final_len = len % SHA256_BLOCK_LENGTH;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
sha256_blocks(state, data, len / SHA256_BLOCK_LENGTH);
|
||||||
|
|
||||||
|
memcpy(final_data, data + len - final_len, final_len);
|
||||||
|
final_data[final_len] = 0x80;
|
||||||
|
final_len = roundup(final_len + 9, SHA256_BLOCK_LENGTH);
|
||||||
|
memcpy(&final_data[final_len - 8], &bitcount, 8);
|
||||||
|
|
||||||
|
sha256_blocks(state, final_data, final_len / SHA256_BLOCK_LENGTH);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(state); i++)
|
||||||
|
put_unaligned_be32(state[i], &out[4 * i]);
|
||||||
|
}
|
||||||
@@ -4,6 +4,6 @@
|
|||||||
#define __LIBBPF_VERSION_H
|
#define __LIBBPF_VERSION_H
|
||||||
|
|
||||||
#define LIBBPF_MAJOR_VERSION 1
|
#define LIBBPF_MAJOR_VERSION 1
|
||||||
#define LIBBPF_MINOR_VERSION 5
|
#define LIBBPF_MINOR_VERSION 7
|
||||||
|
|
||||||
#endif /* __LIBBPF_VERSION_H */
|
#endif /* __LIBBPF_VERSION_H */
|
||||||
|
|||||||
353
src/linker.c
353
src/linker.c
@@ -4,6 +4,10 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2021 Facebook
|
* Copyright (c) 2021 Facebook
|
||||||
*/
|
*/
|
||||||
|
#ifndef _GNU_SOURCE
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -16,6 +20,7 @@
|
|||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
#include <libelf.h>
|
#include <libelf.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
#include "libbpf.h"
|
#include "libbpf.h"
|
||||||
#include "btf.h"
|
#include "btf.h"
|
||||||
#include "libbpf_internal.h"
|
#include "libbpf_internal.h"
|
||||||
@@ -135,6 +140,7 @@ struct bpf_linker {
|
|||||||
int fd;
|
int fd;
|
||||||
Elf *elf;
|
Elf *elf;
|
||||||
Elf64_Ehdr *elf_hdr;
|
Elf64_Ehdr *elf_hdr;
|
||||||
|
bool swapped_endian;
|
||||||
|
|
||||||
/* Output sections metadata */
|
/* Output sections metadata */
|
||||||
struct dst_sec *secs;
|
struct dst_sec *secs;
|
||||||
@@ -150,15 +156,19 @@ struct bpf_linker {
|
|||||||
/* global (including extern) ELF symbols */
|
/* global (including extern) ELF symbols */
|
||||||
int glob_sym_cnt;
|
int glob_sym_cnt;
|
||||||
struct glob_sym *glob_syms;
|
struct glob_sym *glob_syms;
|
||||||
|
|
||||||
|
bool fd_is_owned;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define pr_warn_elf(fmt, ...) \
|
#define pr_warn_elf(fmt, ...) \
|
||||||
libbpf_print(LIBBPF_WARN, "libbpf: " fmt ": %s\n", ##__VA_ARGS__, elf_errmsg(-1))
|
libbpf_print(LIBBPF_WARN, "libbpf: " fmt ": %s\n", ##__VA_ARGS__, elf_errmsg(-1))
|
||||||
|
|
||||||
static int init_output_elf(struct bpf_linker *linker, const char *file);
|
static int init_output_elf(struct bpf_linker *linker);
|
||||||
|
|
||||||
static int linker_load_obj_file(struct bpf_linker *linker, const char *filename,
|
static int bpf_linker_add_file(struct bpf_linker *linker, int fd,
|
||||||
const struct bpf_linker_file_opts *opts,
|
const char *filename);
|
||||||
|
|
||||||
|
static int linker_load_obj_file(struct bpf_linker *linker,
|
||||||
struct src_obj *obj);
|
struct src_obj *obj);
|
||||||
static int linker_sanity_check_elf(struct src_obj *obj);
|
static int linker_sanity_check_elf(struct src_obj *obj);
|
||||||
static int linker_sanity_check_elf_symtab(struct src_obj *obj, struct src_sec *sec);
|
static int linker_sanity_check_elf_symtab(struct src_obj *obj, struct src_sec *sec);
|
||||||
@@ -189,7 +199,7 @@ void bpf_linker__free(struct bpf_linker *linker)
|
|||||||
if (linker->elf)
|
if (linker->elf)
|
||||||
elf_end(linker->elf);
|
elf_end(linker->elf);
|
||||||
|
|
||||||
if (linker->fd >= 0)
|
if (linker->fd >= 0 && linker->fd_is_owned)
|
||||||
close(linker->fd);
|
close(linker->fd);
|
||||||
|
|
||||||
strset__free(linker->strtab_strs);
|
strset__free(linker->strtab_strs);
|
||||||
@@ -231,9 +241,63 @@ struct bpf_linker *bpf_linker__new(const char *filename, struct bpf_linker_opts
|
|||||||
if (!linker)
|
if (!linker)
|
||||||
return errno = ENOMEM, NULL;
|
return errno = ENOMEM, NULL;
|
||||||
|
|
||||||
linker->fd = -1;
|
linker->filename = strdup(filename);
|
||||||
|
if (!linker->filename) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
err = init_output_elf(linker, filename);
|
linker->fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644);
|
||||||
|
if (linker->fd < 0) {
|
||||||
|
err = -errno;
|
||||||
|
pr_warn("failed to create '%s': %d\n", filename, err);
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
linker->fd_is_owned = true;
|
||||||
|
|
||||||
|
err = init_output_elf(linker);
|
||||||
|
if (err)
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
|
return linker;
|
||||||
|
|
||||||
|
err_out:
|
||||||
|
bpf_linker__free(linker);
|
||||||
|
return errno = -err, NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bpf_linker *bpf_linker__new_fd(int fd, struct bpf_linker_opts *opts)
|
||||||
|
{
|
||||||
|
struct bpf_linker *linker;
|
||||||
|
char filename[32];
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
return errno = EINVAL, NULL;
|
||||||
|
|
||||||
|
if (!OPTS_VALID(opts, bpf_linker_opts))
|
||||||
|
return errno = EINVAL, NULL;
|
||||||
|
|
||||||
|
if (elf_version(EV_CURRENT) == EV_NONE) {
|
||||||
|
pr_warn_elf("libelf initialization failed");
|
||||||
|
return errno = EINVAL, NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
linker = calloc(1, sizeof(*linker));
|
||||||
|
if (!linker)
|
||||||
|
return errno = ENOMEM, NULL;
|
||||||
|
|
||||||
|
snprintf(filename, sizeof(filename), "fd:%d", fd);
|
||||||
|
linker->filename = strdup(filename);
|
||||||
|
if (!linker->filename) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
linker->fd = fd;
|
||||||
|
linker->fd_is_owned = false;
|
||||||
|
|
||||||
|
err = init_output_elf(linker);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
|
|
||||||
@@ -292,23 +356,12 @@ static Elf64_Sym *add_new_sym(struct bpf_linker *linker, size_t *sym_idx)
|
|||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int init_output_elf(struct bpf_linker *linker, const char *file)
|
static int init_output_elf(struct bpf_linker *linker)
|
||||||
{
|
{
|
||||||
int err, str_off;
|
int err, str_off;
|
||||||
Elf64_Sym *init_sym;
|
Elf64_Sym *init_sym;
|
||||||
struct dst_sec *sec;
|
struct dst_sec *sec;
|
||||||
|
|
||||||
linker->filename = strdup(file);
|
|
||||||
if (!linker->filename)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
linker->fd = open(file, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644);
|
|
||||||
if (linker->fd < 0) {
|
|
||||||
err = -errno;
|
|
||||||
pr_warn("failed to create '%s': %d\n", file, err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
linker->elf = elf_begin(linker->fd, ELF_C_WRITE, NULL);
|
linker->elf = elf_begin(linker->fd, ELF_C_WRITE, NULL);
|
||||||
if (!linker->elf) {
|
if (!linker->elf) {
|
||||||
pr_warn_elf("failed to create ELF object");
|
pr_warn_elf("failed to create ELF object");
|
||||||
@@ -324,13 +377,8 @@ static int init_output_elf(struct bpf_linker *linker, const char *file)
|
|||||||
|
|
||||||
linker->elf_hdr->e_machine = EM_BPF;
|
linker->elf_hdr->e_machine = EM_BPF;
|
||||||
linker->elf_hdr->e_type = ET_REL;
|
linker->elf_hdr->e_type = ET_REL;
|
||||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
/* Set unknown ELF endianness, assign later from input files */
|
||||||
linker->elf_hdr->e_ident[EI_DATA] = ELFDATA2LSB;
|
linker->elf_hdr->e_ident[EI_DATA] = ELFDATANONE;
|
||||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
|
||||||
linker->elf_hdr->e_ident[EI_DATA] = ELFDATA2MSB;
|
|
||||||
#else
|
|
||||||
#error "Unknown __BYTE_ORDER__"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* STRTAB */
|
/* STRTAB */
|
||||||
/* initialize strset with an empty string to conform to ELF */
|
/* initialize strset with an empty string to conform to ELF */
|
||||||
@@ -396,6 +444,8 @@ static int init_output_elf(struct bpf_linker *linker, const char *file)
|
|||||||
pr_warn_elf("failed to create SYMTAB data");
|
pr_warn_elf("failed to create SYMTAB data");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
/* Ensure libelf translates byte-order of symbol records */
|
||||||
|
sec->data->d_type = ELF_T_SYM;
|
||||||
|
|
||||||
str_off = strset__add_str(linker->strtab_strs, sec->sec_name);
|
str_off = strset__add_str(linker->strtab_strs, sec->sec_name);
|
||||||
if (str_off < 0)
|
if (str_off < 0)
|
||||||
@@ -437,19 +487,16 @@ static int init_output_elf(struct bpf_linker *linker, const char *file)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bpf_linker__add_file(struct bpf_linker *linker, const char *filename,
|
static int bpf_linker_add_file(struct bpf_linker *linker, int fd,
|
||||||
const struct bpf_linker_file_opts *opts)
|
const char *filename)
|
||||||
{
|
{
|
||||||
struct src_obj obj = {};
|
struct src_obj obj = {};
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (!OPTS_VALID(opts, bpf_linker_file_opts))
|
obj.filename = filename;
|
||||||
return libbpf_err(-EINVAL);
|
obj.fd = fd;
|
||||||
|
|
||||||
if (!linker->elf)
|
err = err ?: linker_load_obj_file(linker, &obj);
|
||||||
return libbpf_err(-EINVAL);
|
|
||||||
|
|
||||||
err = err ?: linker_load_obj_file(linker, filename, opts, &obj);
|
|
||||||
err = err ?: linker_append_sec_data(linker, &obj);
|
err = err ?: linker_append_sec_data(linker, &obj);
|
||||||
err = err ?: linker_append_elf_syms(linker, &obj);
|
err = err ?: linker_append_elf_syms(linker, &obj);
|
||||||
err = err ?: linker_append_elf_relos(linker, &obj);
|
err = err ?: linker_append_elf_relos(linker, &obj);
|
||||||
@@ -464,12 +511,91 @@ int bpf_linker__add_file(struct bpf_linker *linker, const char *filename,
|
|||||||
free(obj.sym_map);
|
free(obj.sym_map);
|
||||||
if (obj.elf)
|
if (obj.elf)
|
||||||
elf_end(obj.elf);
|
elf_end(obj.elf);
|
||||||
if (obj.fd >= 0)
|
|
||||||
close(obj.fd);
|
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bpf_linker__add_file(struct bpf_linker *linker, const char *filename,
|
||||||
|
const struct bpf_linker_file_opts *opts)
|
||||||
|
{
|
||||||
|
int fd, err;
|
||||||
|
|
||||||
|
if (!OPTS_VALID(opts, bpf_linker_file_opts))
|
||||||
|
return libbpf_err(-EINVAL);
|
||||||
|
|
||||||
|
if (!linker->elf)
|
||||||
|
return libbpf_err(-EINVAL);
|
||||||
|
|
||||||
|
fd = open(filename, O_RDONLY | O_CLOEXEC);
|
||||||
|
if (fd < 0) {
|
||||||
|
err = -errno;
|
||||||
|
pr_warn("failed to open file '%s': %s\n", filename, errstr(err));
|
||||||
|
return libbpf_err(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bpf_linker_add_file(linker, fd, filename);
|
||||||
|
close(fd);
|
||||||
return libbpf_err(err);
|
return libbpf_err(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bpf_linker__add_fd(struct bpf_linker *linker, int fd,
|
||||||
|
const struct bpf_linker_file_opts *opts)
|
||||||
|
{
|
||||||
|
char filename[32];
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!OPTS_VALID(opts, bpf_linker_file_opts))
|
||||||
|
return libbpf_err(-EINVAL);
|
||||||
|
|
||||||
|
if (!linker->elf)
|
||||||
|
return libbpf_err(-EINVAL);
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
return libbpf_err(-EINVAL);
|
||||||
|
|
||||||
|
snprintf(filename, sizeof(filename), "fd:%d", fd);
|
||||||
|
err = bpf_linker_add_file(linker, fd, filename);
|
||||||
|
return libbpf_err(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bpf_linker__add_buf(struct bpf_linker *linker, void *buf, size_t buf_sz,
|
||||||
|
const struct bpf_linker_file_opts *opts)
|
||||||
|
{
|
||||||
|
char filename[32];
|
||||||
|
int fd, written, ret;
|
||||||
|
|
||||||
|
if (!OPTS_VALID(opts, bpf_linker_file_opts))
|
||||||
|
return libbpf_err(-EINVAL);
|
||||||
|
|
||||||
|
if (!linker->elf)
|
||||||
|
return libbpf_err(-EINVAL);
|
||||||
|
|
||||||
|
snprintf(filename, sizeof(filename), "mem:%p+%zu", buf, buf_sz);
|
||||||
|
|
||||||
|
fd = sys_memfd_create(filename, 0);
|
||||||
|
if (fd < 0) {
|
||||||
|
ret = -errno;
|
||||||
|
pr_warn("failed to create memfd '%s': %s\n", filename, errstr(ret));
|
||||||
|
return libbpf_err(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
written = 0;
|
||||||
|
while (written < buf_sz) {
|
||||||
|
ret = write(fd, buf, buf_sz);
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = -errno;
|
||||||
|
pr_warn("failed to write '%s': %s\n", filename, errstr(ret));
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
written += ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = bpf_linker_add_file(linker, fd, filename);
|
||||||
|
err_out:
|
||||||
|
close(fd);
|
||||||
|
return libbpf_err(ret);
|
||||||
|
}
|
||||||
|
|
||||||
static bool is_dwarf_sec_name(const char *name)
|
static bool is_dwarf_sec_name(const char *name)
|
||||||
{
|
{
|
||||||
/* approximation, but the actual list is too long */
|
/* approximation, but the actual list is too long */
|
||||||
@@ -535,65 +661,69 @@ static struct src_sec *add_src_sec(struct src_obj *obj, const char *sec_name)
|
|||||||
return sec;
|
return sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int linker_load_obj_file(struct bpf_linker *linker, const char *filename,
|
static int linker_load_obj_file(struct bpf_linker *linker,
|
||||||
const struct bpf_linker_file_opts *opts,
|
|
||||||
struct src_obj *obj)
|
struct src_obj *obj)
|
||||||
{
|
{
|
||||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
|
||||||
const int host_endianness = ELFDATA2LSB;
|
|
||||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
|
||||||
const int host_endianness = ELFDATA2MSB;
|
|
||||||
#else
|
|
||||||
#error "Unknown __BYTE_ORDER__"
|
|
||||||
#endif
|
|
||||||
int err = 0;
|
int err = 0;
|
||||||
Elf_Scn *scn;
|
Elf_Scn *scn;
|
||||||
Elf_Data *data;
|
Elf_Data *data;
|
||||||
Elf64_Ehdr *ehdr;
|
Elf64_Ehdr *ehdr;
|
||||||
Elf64_Shdr *shdr;
|
Elf64_Shdr *shdr;
|
||||||
struct src_sec *sec;
|
struct src_sec *sec;
|
||||||
|
unsigned char obj_byteorder;
|
||||||
|
unsigned char link_byteorder = linker->elf_hdr->e_ident[EI_DATA];
|
||||||
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||||
|
const unsigned char host_byteorder = ELFDATA2LSB;
|
||||||
|
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
|
const unsigned char host_byteorder = ELFDATA2MSB;
|
||||||
|
#else
|
||||||
|
#error "Unknown __BYTE_ORDER__"
|
||||||
|
#endif
|
||||||
|
|
||||||
pr_debug("linker: adding object file '%s'...\n", filename);
|
pr_debug("linker: adding object file '%s'...\n", obj->filename);
|
||||||
|
|
||||||
obj->filename = filename;
|
|
||||||
|
|
||||||
obj->fd = open(filename, O_RDONLY | O_CLOEXEC);
|
|
||||||
if (obj->fd < 0) {
|
|
||||||
err = -errno;
|
|
||||||
pr_warn("failed to open file '%s': %d\n", filename, err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
obj->elf = elf_begin(obj->fd, ELF_C_READ_MMAP, NULL);
|
obj->elf = elf_begin(obj->fd, ELF_C_READ_MMAP, NULL);
|
||||||
if (!obj->elf) {
|
if (!obj->elf) {
|
||||||
err = -errno;
|
pr_warn_elf("failed to parse ELF file '%s'", obj->filename);
|
||||||
pr_warn_elf("failed to parse ELF file '%s'", filename);
|
return -EINVAL;
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sanity check ELF file high-level properties */
|
/* Sanity check ELF file high-level properties */
|
||||||
ehdr = elf64_getehdr(obj->elf);
|
ehdr = elf64_getehdr(obj->elf);
|
||||||
if (!ehdr) {
|
if (!ehdr) {
|
||||||
err = -errno;
|
pr_warn_elf("failed to get ELF header for %s", obj->filename);
|
||||||
pr_warn_elf("failed to get ELF header for %s", filename);
|
return -EINVAL;
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
if (ehdr->e_ident[EI_DATA] != host_endianness) {
|
|
||||||
|
/* Linker output endianness set by first input object */
|
||||||
|
obj_byteorder = ehdr->e_ident[EI_DATA];
|
||||||
|
if (obj_byteorder != ELFDATA2LSB && obj_byteorder != ELFDATA2MSB) {
|
||||||
err = -EOPNOTSUPP;
|
err = -EOPNOTSUPP;
|
||||||
pr_warn_elf("unsupported byte order of ELF file %s", filename);
|
pr_warn("unknown byte order of ELF file %s\n", obj->filename);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
if (link_byteorder == ELFDATANONE) {
|
||||||
|
linker->elf_hdr->e_ident[EI_DATA] = obj_byteorder;
|
||||||
|
linker->swapped_endian = obj_byteorder != host_byteorder;
|
||||||
|
pr_debug("linker: set %s-endian output byte order\n",
|
||||||
|
obj_byteorder == ELFDATA2MSB ? "big" : "little");
|
||||||
|
} else if (link_byteorder != obj_byteorder) {
|
||||||
|
err = -EOPNOTSUPP;
|
||||||
|
pr_warn("byte order mismatch with ELF file %s\n", obj->filename);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
if (ehdr->e_type != ET_REL
|
if (ehdr->e_type != ET_REL
|
||||||
|| ehdr->e_machine != EM_BPF
|
|| ehdr->e_machine != EM_BPF
|
||||||
|| ehdr->e_ident[EI_CLASS] != ELFCLASS64) {
|
|| ehdr->e_ident[EI_CLASS] != ELFCLASS64) {
|
||||||
err = -EOPNOTSUPP;
|
err = -EOPNOTSUPP;
|
||||||
pr_warn_elf("unsupported kind of ELF file %s", filename);
|
pr_warn_elf("unsupported kind of ELF file %s", obj->filename);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elf_getshdrstrndx(obj->elf, &obj->shstrs_sec_idx)) {
|
if (elf_getshdrstrndx(obj->elf, &obj->shstrs_sec_idx)) {
|
||||||
err = -errno;
|
pr_warn_elf("failed to get SHSTRTAB section index for %s", obj->filename);
|
||||||
pr_warn_elf("failed to get SHSTRTAB section index for %s", filename);
|
return -EINVAL;
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scn = NULL;
|
scn = NULL;
|
||||||
@@ -603,26 +733,23 @@ static int linker_load_obj_file(struct bpf_linker *linker, const char *filename,
|
|||||||
|
|
||||||
shdr = elf64_getshdr(scn);
|
shdr = elf64_getshdr(scn);
|
||||||
if (!shdr) {
|
if (!shdr) {
|
||||||
err = -errno;
|
|
||||||
pr_warn_elf("failed to get section #%zu header for %s",
|
pr_warn_elf("failed to get section #%zu header for %s",
|
||||||
sec_idx, filename);
|
sec_idx, obj->filename);
|
||||||
return err;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sec_name = elf_strptr(obj->elf, obj->shstrs_sec_idx, shdr->sh_name);
|
sec_name = elf_strptr(obj->elf, obj->shstrs_sec_idx, shdr->sh_name);
|
||||||
if (!sec_name) {
|
if (!sec_name) {
|
||||||
err = -errno;
|
|
||||||
pr_warn_elf("failed to get section #%zu name for %s",
|
pr_warn_elf("failed to get section #%zu name for %s",
|
||||||
sec_idx, filename);
|
sec_idx, obj->filename);
|
||||||
return err;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = elf_getdata(scn, 0);
|
data = elf_getdata(scn, 0);
|
||||||
if (!data) {
|
if (!data) {
|
||||||
err = -errno;
|
|
||||||
pr_warn_elf("failed to get section #%zu (%s) data from %s",
|
pr_warn_elf("failed to get section #%zu (%s) data from %s",
|
||||||
sec_idx, sec_name, filename);
|
sec_idx, sec_name, obj->filename);
|
||||||
return err;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sec = add_src_sec(obj, sec_name);
|
sec = add_src_sec(obj, sec_name);
|
||||||
@@ -656,7 +783,8 @@ static int linker_load_obj_file(struct bpf_linker *linker, const char *filename,
|
|||||||
obj->btf = btf__new(data->d_buf, shdr->sh_size);
|
obj->btf = btf__new(data->d_buf, shdr->sh_size);
|
||||||
err = libbpf_get_error(obj->btf);
|
err = libbpf_get_error(obj->btf);
|
||||||
if (err) {
|
if (err) {
|
||||||
pr_warn("failed to parse .BTF from %s: %d\n", filename, err);
|
pr_warn("failed to parse .BTF from %s: %s\n",
|
||||||
|
obj->filename, errstr(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
sec->skipped = true;
|
sec->skipped = true;
|
||||||
@@ -666,7 +794,8 @@ static int linker_load_obj_file(struct bpf_linker *linker, const char *filename,
|
|||||||
obj->btf_ext = btf_ext__new(data->d_buf, shdr->sh_size);
|
obj->btf_ext = btf_ext__new(data->d_buf, shdr->sh_size);
|
||||||
err = libbpf_get_error(obj->btf_ext);
|
err = libbpf_get_error(obj->btf_ext);
|
||||||
if (err) {
|
if (err) {
|
||||||
pr_warn("failed to parse .BTF.ext from '%s': %d\n", filename, err);
|
pr_warn("failed to parse .BTF.ext from '%s': %s\n",
|
||||||
|
obj->filename, errstr(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
sec->skipped = true;
|
sec->skipped = true;
|
||||||
@@ -683,7 +812,7 @@ static int linker_load_obj_file(struct bpf_linker *linker, const char *filename,
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
pr_warn("unrecognized section #%zu (%s) in %s\n",
|
pr_warn("unrecognized section #%zu (%s) in %s\n",
|
||||||
sec_idx, sec_name, filename);
|
sec_idx, sec_name, obj->filename);
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -1109,6 +1238,24 @@ static bool sec_content_is_same(struct dst_sec *dst_sec, struct src_sec *src_sec
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_exec_sec(struct dst_sec *sec)
|
||||||
|
{
|
||||||
|
if (!sec || sec->ephemeral)
|
||||||
|
return false;
|
||||||
|
return (sec->shdr->sh_type == SHT_PROGBITS) &&
|
||||||
|
(sec->shdr->sh_flags & SHF_EXECINSTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exec_sec_bswap(void *raw_data, int size)
|
||||||
|
{
|
||||||
|
const int insn_cnt = size / sizeof(struct bpf_insn);
|
||||||
|
struct bpf_insn *insn = raw_data;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < insn_cnt; i++, insn++)
|
||||||
|
bpf_insn_bswap(insn);
|
||||||
|
}
|
||||||
|
|
||||||
static int extend_sec(struct bpf_linker *linker, struct dst_sec *dst, struct src_sec *src)
|
static int extend_sec(struct bpf_linker *linker, struct dst_sec *dst, struct src_sec *src)
|
||||||
{
|
{
|
||||||
void *tmp;
|
void *tmp;
|
||||||
@@ -1168,6 +1315,10 @@ static int extend_sec(struct bpf_linker *linker, struct dst_sec *dst, struct src
|
|||||||
memset(dst->raw_data + dst->sec_sz, 0, dst_align_sz - dst->sec_sz);
|
memset(dst->raw_data + dst->sec_sz, 0, dst_align_sz - dst->sec_sz);
|
||||||
/* now copy src data at a properly aligned offset */
|
/* now copy src data at a properly aligned offset */
|
||||||
memcpy(dst->raw_data + dst_align_sz, src->data->d_buf, src->shdr->sh_size);
|
memcpy(dst->raw_data + dst_align_sz, src->data->d_buf, src->shdr->sh_size);
|
||||||
|
|
||||||
|
/* convert added bpf insns to native byte-order */
|
||||||
|
if (linker->swapped_endian && is_exec_sec(dst))
|
||||||
|
exec_sec_bswap(dst->raw_data + dst_align_sz, src->shdr->sh_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
dst->sec_sz = dst_final_sz;
|
dst->sec_sz = dst_final_sz;
|
||||||
@@ -1224,7 +1375,7 @@ static int linker_append_sec_data(struct bpf_linker *linker, struct src_obj *obj
|
|||||||
} else {
|
} else {
|
||||||
if (!secs_match(dst_sec, src_sec)) {
|
if (!secs_match(dst_sec, src_sec)) {
|
||||||
pr_warn("ELF sections %s are incompatible\n", src_sec->sec_name);
|
pr_warn("ELF sections %s are incompatible\n", src_sec->sec_name);
|
||||||
return -1;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* "license" and "version" sections are deduped */
|
/* "license" and "version" sections are deduped */
|
||||||
@@ -1413,7 +1564,7 @@ recur:
|
|||||||
return true;
|
return true;
|
||||||
case BTF_KIND_PTR:
|
case BTF_KIND_PTR:
|
||||||
/* just validate overall shape of the referenced type, so no
|
/* just validate overall shape of the referenced type, so no
|
||||||
* contents comparison for struct/union, and allowd fwd vs
|
* contents comparison for struct/union, and allowed fwd vs
|
||||||
* struct/union
|
* struct/union
|
||||||
*/
|
*/
|
||||||
exact = false;
|
exact = false;
|
||||||
@@ -1874,6 +2025,9 @@ static int linker_append_elf_sym(struct bpf_linker *linker, struct src_obj *obj,
|
|||||||
obj->sym_map[src_sym_idx] = dst_sec->sec_sym_idx;
|
obj->sym_map[src_sym_idx] = dst_sec->sec_sym_idx;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strcmp(src_sec->sec_name, JUMPTABLES_SEC) == 0)
|
||||||
|
goto add_sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sym_bind == STB_LOCAL)
|
if (sym_bind == STB_LOCAL)
|
||||||
@@ -1962,7 +2116,7 @@ static int linker_append_elf_sym(struct bpf_linker *linker, struct src_obj *obj,
|
|||||||
|
|
||||||
/* If existing symbol is a strong resolved symbol, bail out,
|
/* If existing symbol is a strong resolved symbol, bail out,
|
||||||
* because we lost resolution battle have nothing to
|
* because we lost resolution battle have nothing to
|
||||||
* contribute. We already checked abover that there is no
|
* contribute. We already checked above that there is no
|
||||||
* strong-strong conflict. We also already tightened binding
|
* strong-strong conflict. We also already tightened binding
|
||||||
* and visibility, so nothing else to contribute at that point.
|
* and visibility, so nothing else to contribute at that point.
|
||||||
*/
|
*/
|
||||||
@@ -2011,7 +2165,7 @@ add_sym:
|
|||||||
|
|
||||||
obj->sym_map[src_sym_idx] = dst_sym_idx;
|
obj->sym_map[src_sym_idx] = dst_sym_idx;
|
||||||
|
|
||||||
if (sym_type == STT_SECTION && dst_sym) {
|
if (sym_type == STT_SECTION && dst_sec) {
|
||||||
dst_sec->sec_sym_idx = dst_sym_idx;
|
dst_sec->sec_sym_idx = dst_sym_idx;
|
||||||
dst_sym->st_value = 0;
|
dst_sym->st_value = 0;
|
||||||
}
|
}
|
||||||
@@ -2071,7 +2225,7 @@ static int linker_append_elf_relos(struct bpf_linker *linker, struct src_obj *ob
|
|||||||
}
|
}
|
||||||
} else if (!secs_match(dst_sec, src_sec)) {
|
} else if (!secs_match(dst_sec, src_sec)) {
|
||||||
pr_warn("sections %s are not compatible\n", src_sec->sec_name);
|
pr_warn("sections %s are not compatible\n", src_sec->sec_name);
|
||||||
return -1;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* shdr->sh_link points to SYMTAB */
|
/* shdr->sh_link points to SYMTAB */
|
||||||
@@ -2415,6 +2569,10 @@ static int linker_append_btf(struct bpf_linker *linker, struct src_obj *obj)
|
|||||||
if (glob_sym && glob_sym->var_idx >= 0) {
|
if (glob_sym && glob_sym->var_idx >= 0) {
|
||||||
__s64 sz;
|
__s64 sz;
|
||||||
|
|
||||||
|
/* FUNCs don't have size, nothing to update */
|
||||||
|
if (btf_is_func(t))
|
||||||
|
continue;
|
||||||
|
|
||||||
dst_var = &dst_sec->sec_vars[glob_sym->var_idx];
|
dst_var = &dst_sec->sec_vars[glob_sym->var_idx];
|
||||||
/* Because underlying BTF type might have
|
/* Because underlying BTF type might have
|
||||||
* changed, so might its size have changed, so
|
* changed, so might its size have changed, so
|
||||||
@@ -2628,27 +2786,32 @@ int bpf_linker__finalize(struct bpf_linker *linker)
|
|||||||
if (!sec->scn)
|
if (!sec->scn)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* restore sections with bpf insns to target byte-order */
|
||||||
|
if (linker->swapped_endian && is_exec_sec(sec))
|
||||||
|
exec_sec_bswap(sec->raw_data, sec->sec_sz);
|
||||||
|
|
||||||
sec->data->d_buf = sec->raw_data;
|
sec->data->d_buf = sec->raw_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finalize ELF layout */
|
/* Finalize ELF layout */
|
||||||
if (elf_update(linker->elf, ELF_C_NULL) < 0) {
|
if (elf_update(linker->elf, ELF_C_NULL) < 0) {
|
||||||
err = -errno;
|
err = -EINVAL;
|
||||||
pr_warn_elf("failed to finalize ELF layout");
|
pr_warn_elf("failed to finalize ELF layout");
|
||||||
return libbpf_err(err);
|
return libbpf_err(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write out final ELF contents */
|
/* Write out final ELF contents */
|
||||||
if (elf_update(linker->elf, ELF_C_WRITE) < 0) {
|
if (elf_update(linker->elf, ELF_C_WRITE) < 0) {
|
||||||
err = -errno;
|
err = -EINVAL;
|
||||||
pr_warn_elf("failed to write ELF contents");
|
pr_warn_elf("failed to write ELF contents");
|
||||||
return libbpf_err(err);
|
return libbpf_err(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
elf_end(linker->elf);
|
elf_end(linker->elf);
|
||||||
close(linker->fd);
|
|
||||||
|
|
||||||
linker->elf = NULL;
|
linker->elf = NULL;
|
||||||
|
|
||||||
|
if (linker->fd_is_owned)
|
||||||
|
close(linker->fd);
|
||||||
linker->fd = -1;
|
linker->fd = -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2696,6 +2859,7 @@ static int emit_elf_data_sec(struct bpf_linker *linker, const char *sec_name,
|
|||||||
|
|
||||||
static int finalize_btf(struct bpf_linker *linker)
|
static int finalize_btf(struct bpf_linker *linker)
|
||||||
{
|
{
|
||||||
|
enum btf_endianness link_endianness;
|
||||||
LIBBPF_OPTS(btf_dedup_opts, opts);
|
LIBBPF_OPTS(btf_dedup_opts, opts);
|
||||||
struct btf *btf = linker->btf;
|
struct btf *btf = linker->btf;
|
||||||
const void *raw_data;
|
const void *raw_data;
|
||||||
@@ -2729,17 +2893,24 @@ static int finalize_btf(struct bpf_linker *linker)
|
|||||||
|
|
||||||
err = finalize_btf_ext(linker);
|
err = finalize_btf_ext(linker);
|
||||||
if (err) {
|
if (err) {
|
||||||
pr_warn(".BTF.ext generation failed: %d\n", err);
|
pr_warn(".BTF.ext generation failed: %s\n", errstr(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
opts.btf_ext = linker->btf_ext;
|
opts.btf_ext = linker->btf_ext;
|
||||||
err = btf__dedup(linker->btf, &opts);
|
err = btf__dedup(linker->btf, &opts);
|
||||||
if (err) {
|
if (err) {
|
||||||
pr_warn("BTF dedup failed: %d\n", err);
|
pr_warn("BTF dedup failed: %s\n", errstr(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set .BTF and .BTF.ext output byte order */
|
||||||
|
link_endianness = linker->elf_hdr->e_ident[EI_DATA] == ELFDATA2MSB ?
|
||||||
|
BTF_BIG_ENDIAN : BTF_LITTLE_ENDIAN;
|
||||||
|
btf__set_endianness(linker->btf, link_endianness);
|
||||||
|
if (linker->btf_ext)
|
||||||
|
btf_ext__set_endianness(linker->btf_ext, link_endianness);
|
||||||
|
|
||||||
/* Emit .BTF section */
|
/* Emit .BTF section */
|
||||||
raw_data = btf__raw_data(linker->btf, &raw_sz);
|
raw_data = btf__raw_data(linker->btf, &raw_sz);
|
||||||
if (!raw_data)
|
if (!raw_data)
|
||||||
@@ -2747,7 +2918,7 @@ static int finalize_btf(struct bpf_linker *linker)
|
|||||||
|
|
||||||
err = emit_elf_data_sec(linker, BTF_ELF_SEC, 8, raw_data, raw_sz);
|
err = emit_elf_data_sec(linker, BTF_ELF_SEC, 8, raw_data, raw_sz);
|
||||||
if (err) {
|
if (err) {
|
||||||
pr_warn("failed to write out .BTF ELF section: %d\n", err);
|
pr_warn("failed to write out .BTF ELF section: %s\n", errstr(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2759,7 +2930,7 @@ static int finalize_btf(struct bpf_linker *linker)
|
|||||||
|
|
||||||
err = emit_elf_data_sec(linker, BTF_EXT_ELF_SEC, 8, raw_data, raw_sz);
|
err = emit_elf_data_sec(linker, BTF_EXT_ELF_SEC, 8, raw_data, raw_sz);
|
||||||
if (err) {
|
if (err) {
|
||||||
pr_warn("failed to write out .BTF.ext ELF section: %d\n", err);
|
pr_warn("failed to write out .BTF.ext ELF section: %s\n", errstr(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2935,7 +3106,7 @@ static int finalize_btf_ext(struct bpf_linker *linker)
|
|||||||
err = libbpf_get_error(linker->btf_ext);
|
err = libbpf_get_error(linker->btf_ext);
|
||||||
if (err) {
|
if (err) {
|
||||||
linker->btf_ext = NULL;
|
linker->btf_ext = NULL;
|
||||||
pr_warn("failed to parse final .BTF.ext data: %d\n", err);
|
pr_warn("failed to parse final .BTF.ext data: %s\n", errstr(err));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -529,9 +529,9 @@ int bpf_xdp_query_id(int ifindex, int flags, __u32 *prog_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef int (*qdisc_config_t)(struct libbpf_nla_req *req);
|
typedef int (*qdisc_config_t)(struct libbpf_nla_req *req, const struct bpf_tc_hook *hook);
|
||||||
|
|
||||||
static int clsact_config(struct libbpf_nla_req *req)
|
static int clsact_config(struct libbpf_nla_req *req, const struct bpf_tc_hook *hook)
|
||||||
{
|
{
|
||||||
req->tc.tcm_parent = TC_H_CLSACT;
|
req->tc.tcm_parent = TC_H_CLSACT;
|
||||||
req->tc.tcm_handle = TC_H_MAKE(TC_H_CLSACT, 0);
|
req->tc.tcm_handle = TC_H_MAKE(TC_H_CLSACT, 0);
|
||||||
@@ -539,6 +539,16 @@ static int clsact_config(struct libbpf_nla_req *req)
|
|||||||
return nlattr_add(req, TCA_KIND, "clsact", sizeof("clsact"));
|
return nlattr_add(req, TCA_KIND, "clsact", sizeof("clsact"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int qdisc_config(struct libbpf_nla_req *req, const struct bpf_tc_hook *hook)
|
||||||
|
{
|
||||||
|
const char *qdisc = OPTS_GET(hook, qdisc, NULL);
|
||||||
|
|
||||||
|
req->tc.tcm_parent = OPTS_GET(hook, parent, TC_H_ROOT);
|
||||||
|
req->tc.tcm_handle = OPTS_GET(hook, handle, 0);
|
||||||
|
|
||||||
|
return nlattr_add(req, TCA_KIND, qdisc, strlen(qdisc) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
static int attach_point_to_config(struct bpf_tc_hook *hook,
|
static int attach_point_to_config(struct bpf_tc_hook *hook,
|
||||||
qdisc_config_t *config)
|
qdisc_config_t *config)
|
||||||
{
|
{
|
||||||
@@ -552,6 +562,9 @@ static int attach_point_to_config(struct bpf_tc_hook *hook,
|
|||||||
return 0;
|
return 0;
|
||||||
case BPF_TC_CUSTOM:
|
case BPF_TC_CUSTOM:
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
case BPF_TC_QDISC:
|
||||||
|
*config = &qdisc_config;
|
||||||
|
return 0;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -596,7 +609,7 @@ static int tc_qdisc_modify(struct bpf_tc_hook *hook, int cmd, int flags)
|
|||||||
req.tc.tcm_family = AF_UNSPEC;
|
req.tc.tcm_family = AF_UNSPEC;
|
||||||
req.tc.tcm_ifindex = OPTS_GET(hook, ifindex, 0);
|
req.tc.tcm_ifindex = OPTS_GET(hook, ifindex, 0);
|
||||||
|
|
||||||
ret = config(&req);
|
ret = config(&req, hook);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@@ -639,6 +652,7 @@ int bpf_tc_hook_destroy(struct bpf_tc_hook *hook)
|
|||||||
case BPF_TC_INGRESS:
|
case BPF_TC_INGRESS:
|
||||||
case BPF_TC_EGRESS:
|
case BPF_TC_EGRESS:
|
||||||
return libbpf_err(__bpf_tc_detach(hook, NULL, true));
|
return libbpf_err(__bpf_tc_detach(hook, NULL, true));
|
||||||
|
case BPF_TC_QDISC:
|
||||||
case BPF_TC_INGRESS | BPF_TC_EGRESS:
|
case BPF_TC_INGRESS | BPF_TC_EGRESS:
|
||||||
return libbpf_err(tc_qdisc_delete(hook));
|
return libbpf_err(tc_qdisc_delete(hook));
|
||||||
case BPF_TC_CUSTOM:
|
case BPF_TC_CUSTOM:
|
||||||
|
|||||||
15
src/nlattr.c
15
src/nlattr.c
@@ -63,16 +63,16 @@ static int validate_nla(struct nlattr *nla, int maxtype,
|
|||||||
minlen = nla_attr_minlen[pt->type];
|
minlen = nla_attr_minlen[pt->type];
|
||||||
|
|
||||||
if (libbpf_nla_len(nla) < minlen)
|
if (libbpf_nla_len(nla) < minlen)
|
||||||
return -1;
|
return -EINVAL;
|
||||||
|
|
||||||
if (pt->maxlen && libbpf_nla_len(nla) > pt->maxlen)
|
if (pt->maxlen && libbpf_nla_len(nla) > pt->maxlen)
|
||||||
return -1;
|
return -EINVAL;
|
||||||
|
|
||||||
if (pt->type == LIBBPF_NLA_STRING) {
|
if (pt->type == LIBBPF_NLA_STRING) {
|
||||||
char *data = libbpf_nla_data(nla);
|
char *data = libbpf_nla_data(nla);
|
||||||
|
|
||||||
if (data[libbpf_nla_len(nla) - 1] != '\0')
|
if (data[libbpf_nla_len(nla) - 1] != '\0')
|
||||||
return -1;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -118,19 +118,18 @@ int libbpf_nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head,
|
|||||||
if (policy) {
|
if (policy) {
|
||||||
err = validate_nla(nla, maxtype, policy);
|
err = validate_nla(nla, maxtype, policy);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto errout;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tb[type])
|
if (tb[type]) {
|
||||||
pr_warn("Attribute of type %#x found multiple times in message, "
|
pr_warn("Attribute of type %#x found multiple times in message, "
|
||||||
"previous attribute is being ignored.\n", type);
|
"previous attribute is being ignored.\n", type);
|
||||||
|
}
|
||||||
|
|
||||||
tb[type] = nla;
|
tb[type] = nla;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = 0;
|
return 0;
|
||||||
errout:
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -64,7 +64,6 @@ enum libbpf_print_level {
|
|||||||
#include "libbpf.h"
|
#include "libbpf.h"
|
||||||
#include "bpf.h"
|
#include "bpf.h"
|
||||||
#include "btf.h"
|
#include "btf.h"
|
||||||
#include "str_error.h"
|
|
||||||
#include "libbpf_internal.h"
|
#include "libbpf_internal.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -683,7 +682,7 @@ static int bpf_core_calc_field_relo(const char *prog_name,
|
|||||||
{
|
{
|
||||||
const struct bpf_core_accessor *acc;
|
const struct bpf_core_accessor *acc;
|
||||||
const struct btf_type *t;
|
const struct btf_type *t;
|
||||||
__u32 byte_off, byte_sz, bit_off, bit_sz, field_type_id;
|
__u32 byte_off, byte_sz, bit_off, bit_sz, field_type_id, elem_id;
|
||||||
const struct btf_member *m;
|
const struct btf_member *m;
|
||||||
const struct btf_type *mt;
|
const struct btf_type *mt;
|
||||||
bool bitfield;
|
bool bitfield;
|
||||||
@@ -706,8 +705,14 @@ static int bpf_core_calc_field_relo(const char *prog_name,
|
|||||||
if (!acc->name) {
|
if (!acc->name) {
|
||||||
if (relo->kind == BPF_CORE_FIELD_BYTE_OFFSET) {
|
if (relo->kind == BPF_CORE_FIELD_BYTE_OFFSET) {
|
||||||
*val = spec->bit_offset / 8;
|
*val = spec->bit_offset / 8;
|
||||||
/* remember field size for load/store mem size */
|
/* remember field size for load/store mem size;
|
||||||
sz = btf__resolve_size(spec->btf, acc->type_id);
|
* note, for arrays we care about individual element
|
||||||
|
* sizes, not the overall array size
|
||||||
|
*/
|
||||||
|
t = skip_mods_and_typedefs(spec->btf, acc->type_id, &elem_id);
|
||||||
|
while (btf_is_array(t))
|
||||||
|
t = skip_mods_and_typedefs(spec->btf, btf_array(t)->type, &elem_id);
|
||||||
|
sz = btf__resolve_size(spec->btf, elem_id);
|
||||||
if (sz < 0)
|
if (sz < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
*field_sz = sz;
|
*field_sz = sz;
|
||||||
@@ -767,7 +772,17 @@ static int bpf_core_calc_field_relo(const char *prog_name,
|
|||||||
case BPF_CORE_FIELD_BYTE_OFFSET:
|
case BPF_CORE_FIELD_BYTE_OFFSET:
|
||||||
*val = byte_off;
|
*val = byte_off;
|
||||||
if (!bitfield) {
|
if (!bitfield) {
|
||||||
*field_sz = byte_sz;
|
/* remember field size for load/store mem size;
|
||||||
|
* note, for arrays we care about individual element
|
||||||
|
* sizes, not the overall array size
|
||||||
|
*/
|
||||||
|
t = skip_mods_and_typedefs(spec->btf, field_type_id, &elem_id);
|
||||||
|
while (btf_is_array(t))
|
||||||
|
t = skip_mods_and_typedefs(spec->btf, btf_array(t)->type, &elem_id);
|
||||||
|
sz = btf__resolve_size(spec->btf, elem_id);
|
||||||
|
if (sz < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
*field_sz = sz;
|
||||||
*type_id = field_type_id;
|
*type_id = field_type_id;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1339,7 +1354,7 @@ int bpf_core_calc_relo_insn(const char *prog_name,
|
|||||||
cands->cands[i].id, cand_spec);
|
cands->cands[i].id, cand_spec);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
bpf_core_format_spec(spec_buf, sizeof(spec_buf), cand_spec);
|
bpf_core_format_spec(spec_buf, sizeof(spec_buf), cand_spec);
|
||||||
pr_warn("prog '%s': relo #%d: error matching candidate #%d %s: %d\n ",
|
pr_warn("prog '%s': relo #%d: error matching candidate #%d %s: %d\n",
|
||||||
prog_name, relo_idx, i, spec_buf, err);
|
prog_name, relo_idx, i, spec_buf, err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,8 +88,8 @@ int ring_buffer__add(struct ring_buffer *rb, int map_fd,
|
|||||||
err = bpf_map_get_info_by_fd(map_fd, &info, &len);
|
err = bpf_map_get_info_by_fd(map_fd, &info, &len);
|
||||||
if (err) {
|
if (err) {
|
||||||
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: %s\n",
|
||||||
map_fd, err);
|
map_fd, errstr(err));
|
||||||
return libbpf_err(err);
|
return libbpf_err(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,8 +123,8 @@ int ring_buffer__add(struct ring_buffer *rb, int map_fd,
|
|||||||
tmp = mmap(NULL, rb->page_size, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
|
tmp = mmap(NULL, rb->page_size, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
|
||||||
if (tmp == MAP_FAILED) {
|
if (tmp == MAP_FAILED) {
|
||||||
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: %s\n",
|
||||||
map_fd, err);
|
map_fd, errstr(err));
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
r->consumer_pos = tmp;
|
r->consumer_pos = tmp;
|
||||||
@@ -142,8 +142,8 @@ int ring_buffer__add(struct ring_buffer *rb, int map_fd,
|
|||||||
tmp = mmap(NULL, (size_t)mmap_sz, PROT_READ, MAP_SHARED, map_fd, rb->page_size);
|
tmp = mmap(NULL, (size_t)mmap_sz, PROT_READ, MAP_SHARED, map_fd, rb->page_size);
|
||||||
if (tmp == MAP_FAILED) {
|
if (tmp == MAP_FAILED) {
|
||||||
err = -errno;
|
err = -errno;
|
||||||
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: %s\n",
|
||||||
map_fd, err);
|
map_fd, errstr(err));
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
r->producer_pos = tmp;
|
r->producer_pos = tmp;
|
||||||
@@ -156,8 +156,8 @@ int ring_buffer__add(struct ring_buffer *rb, int map_fd,
|
|||||||
e->data.fd = rb->ring_cnt;
|
e->data.fd = rb->ring_cnt;
|
||||||
if (epoll_ctl(rb->epoll_fd, EPOLL_CTL_ADD, map_fd, e) < 0) {
|
if (epoll_ctl(rb->epoll_fd, EPOLL_CTL_ADD, map_fd, e) < 0) {
|
||||||
err = -errno;
|
err = -errno;
|
||||||
pr_warn("ringbuf: failed to epoll add map fd=%d: %d\n",
|
pr_warn("ringbuf: failed to epoll add map fd=%d: %s\n",
|
||||||
map_fd, err);
|
map_fd, errstr(err));
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,7 +205,7 @@ ring_buffer__new(int map_fd, ring_buffer_sample_fn sample_cb, void *ctx,
|
|||||||
rb->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
|
rb->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
|
||||||
if (rb->epoll_fd < 0) {
|
if (rb->epoll_fd < 0) {
|
||||||
err = -errno;
|
err = -errno;
|
||||||
pr_warn("ringbuf: failed to create epoll instance: %d\n", err);
|
pr_warn("ringbuf: failed to create epoll instance: %s\n", errstr(err));
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,7 +458,8 @@ static int user_ringbuf_map(struct user_ring_buffer *rb, int map_fd)
|
|||||||
err = bpf_map_get_info_by_fd(map_fd, &info, &len);
|
err = bpf_map_get_info_by_fd(map_fd, &info, &len);
|
||||||
if (err) {
|
if (err) {
|
||||||
err = -errno;
|
err = -errno;
|
||||||
pr_warn("user ringbuf: failed to get map info for fd=%d: %d\n", map_fd, err);
|
pr_warn("user ringbuf: failed to get map info for fd=%d: %s\n",
|
||||||
|
map_fd, errstr(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,8 +475,8 @@ static int user_ringbuf_map(struct user_ring_buffer *rb, int map_fd)
|
|||||||
tmp = mmap(NULL, rb->page_size, PROT_READ, MAP_SHARED, map_fd, 0);
|
tmp = mmap(NULL, rb->page_size, PROT_READ, MAP_SHARED, map_fd, 0);
|
||||||
if (tmp == MAP_FAILED) {
|
if (tmp == MAP_FAILED) {
|
||||||
err = -errno;
|
err = -errno;
|
||||||
pr_warn("user ringbuf: failed to mmap consumer page for map fd=%d: %d\n",
|
pr_warn("user ringbuf: failed to mmap consumer page for map fd=%d: %s\n",
|
||||||
map_fd, err);
|
map_fd, errstr(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
rb->consumer_pos = tmp;
|
rb->consumer_pos = tmp;
|
||||||
@@ -494,8 +495,8 @@ static int user_ringbuf_map(struct user_ring_buffer *rb, int map_fd)
|
|||||||
map_fd, rb->page_size);
|
map_fd, rb->page_size);
|
||||||
if (tmp == MAP_FAILED) {
|
if (tmp == MAP_FAILED) {
|
||||||
err = -errno;
|
err = -errno;
|
||||||
pr_warn("user ringbuf: failed to mmap data pages for map fd=%d: %d\n",
|
pr_warn("user ringbuf: failed to mmap data pages for map fd=%d: %s\n",
|
||||||
map_fd, err);
|
map_fd, errstr(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -506,7 +507,7 @@ static int user_ringbuf_map(struct user_ring_buffer *rb, int map_fd)
|
|||||||
rb_epoll->events = EPOLLOUT;
|
rb_epoll->events = EPOLLOUT;
|
||||||
if (epoll_ctl(rb->epoll_fd, EPOLL_CTL_ADD, map_fd, rb_epoll) < 0) {
|
if (epoll_ctl(rb->epoll_fd, EPOLL_CTL_ADD, map_fd, rb_epoll) < 0) {
|
||||||
err = -errno;
|
err = -errno;
|
||||||
pr_warn("user ringbuf: failed to epoll add map fd=%d: %d\n", map_fd, err);
|
pr_warn("user ringbuf: failed to epoll add map fd=%d: %s\n", map_fd, errstr(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,7 +532,7 @@ user_ring_buffer__new(int map_fd, const struct user_ring_buffer_opts *opts)
|
|||||||
rb->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
|
rb->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
|
||||||
if (rb->epoll_fd < 0) {
|
if (rb->epoll_fd < 0) {
|
||||||
err = -errno;
|
err = -errno;
|
||||||
pr_warn("user ringbuf: failed to create epoll instance: %d\n", err);
|
pr_warn("user ringbuf: failed to create epoll instance: %s\n", errstr(err));
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,10 +13,15 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <linux/keyctl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "bpf.h"
|
#include "bpf.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef SHA256_DIGEST_LENGTH
|
||||||
|
#define SHA256_DIGEST_LENGTH 32
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef __NR_bpf
|
#ifndef __NR_bpf
|
||||||
# if defined(__mips__) && defined(_ABIO32)
|
# if defined(__mips__) && defined(_ABIO32)
|
||||||
# define __NR_bpf 4355
|
# define __NR_bpf 4355
|
||||||
@@ -64,6 +69,11 @@ struct bpf_load_and_run_opts {
|
|||||||
__u32 data_sz;
|
__u32 data_sz;
|
||||||
__u32 insns_sz;
|
__u32 insns_sz;
|
||||||
const char *errstr;
|
const char *errstr;
|
||||||
|
void *signature;
|
||||||
|
__u32 signature_sz;
|
||||||
|
__s32 keyring_id;
|
||||||
|
void *excl_prog_hash;
|
||||||
|
__u32 excl_prog_hash_sz;
|
||||||
};
|
};
|
||||||
|
|
||||||
long kern_sys_bpf(__u32 cmd, void *attr, __u32 attr_size);
|
long kern_sys_bpf(__u32 cmd, void *attr, __u32 attr_size);
|
||||||
@@ -107,7 +117,7 @@ static inline void skel_free(const void *p)
|
|||||||
* The loader program will perform probe_read_kernel() from maps.rodata.initial_value.
|
* The loader program will perform probe_read_kernel() from maps.rodata.initial_value.
|
||||||
* skel_finalize_map_data() sets skel->rodata to point to actual value in a bpf map and
|
* skel_finalize_map_data() sets skel->rodata to point to actual value in a bpf map and
|
||||||
* does maps.rodata.initial_value = ~0ULL to signal skel_free_map_data() that kvfree
|
* does maps.rodata.initial_value = ~0ULL to signal skel_free_map_data() that kvfree
|
||||||
* is not nessary.
|
* is not necessary.
|
||||||
*
|
*
|
||||||
* For user space:
|
* For user space:
|
||||||
* skel_prep_map_data() mmaps anon memory into skel->rodata that can be accessed directly.
|
* skel_prep_map_data() mmaps anon memory into skel->rodata that can be accessed directly.
|
||||||
@@ -220,14 +230,19 @@ static inline int skel_map_create(enum bpf_map_type map_type,
|
|||||||
const char *map_name,
|
const char *map_name,
|
||||||
__u32 key_size,
|
__u32 key_size,
|
||||||
__u32 value_size,
|
__u32 value_size,
|
||||||
__u32 max_entries)
|
__u32 max_entries,
|
||||||
|
const void *excl_prog_hash,
|
||||||
|
__u32 excl_prog_hash_sz)
|
||||||
{
|
{
|
||||||
const size_t attr_sz = offsetofend(union bpf_attr, map_extra);
|
const size_t attr_sz = offsetofend(union bpf_attr, excl_prog_hash_size);
|
||||||
union bpf_attr attr;
|
union bpf_attr attr;
|
||||||
|
|
||||||
memset(&attr, 0, attr_sz);
|
memset(&attr, 0, attr_sz);
|
||||||
|
|
||||||
attr.map_type = map_type;
|
attr.map_type = map_type;
|
||||||
|
attr.excl_prog_hash = (unsigned long) excl_prog_hash;
|
||||||
|
attr.excl_prog_hash_size = excl_prog_hash_sz;
|
||||||
|
|
||||||
strncpy(attr.map_name, map_name, sizeof(attr.map_name));
|
strncpy(attr.map_name, map_name, sizeof(attr.map_name));
|
||||||
attr.key_size = key_size;
|
attr.key_size = key_size;
|
||||||
attr.value_size = value_size;
|
attr.value_size = value_size;
|
||||||
@@ -300,6 +315,35 @@ static inline int skel_link_create(int prog_fd, int target_fd,
|
|||||||
return skel_sys_bpf(BPF_LINK_CREATE, &attr, attr_sz);
|
return skel_sys_bpf(BPF_LINK_CREATE, &attr, attr_sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int skel_obj_get_info_by_fd(int fd)
|
||||||
|
{
|
||||||
|
const size_t attr_sz = offsetofend(union bpf_attr, info);
|
||||||
|
__u8 sha[SHA256_DIGEST_LENGTH];
|
||||||
|
struct bpf_map_info info;
|
||||||
|
__u32 info_len = sizeof(info);
|
||||||
|
union bpf_attr attr;
|
||||||
|
|
||||||
|
memset(&info, 0, sizeof(info));
|
||||||
|
info.hash = (long) &sha;
|
||||||
|
info.hash_size = SHA256_DIGEST_LENGTH;
|
||||||
|
|
||||||
|
memset(&attr, 0, attr_sz);
|
||||||
|
attr.info.bpf_fd = fd;
|
||||||
|
attr.info.info = (long) &info;
|
||||||
|
attr.info.info_len = info_len;
|
||||||
|
return skel_sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, attr_sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int skel_map_freeze(int fd)
|
||||||
|
{
|
||||||
|
const size_t attr_sz = offsetofend(union bpf_attr, map_fd);
|
||||||
|
union bpf_attr attr;
|
||||||
|
|
||||||
|
memset(&attr, 0, attr_sz);
|
||||||
|
attr.map_fd = fd;
|
||||||
|
|
||||||
|
return skel_sys_bpf(BPF_MAP_FREEZE, &attr, attr_sz);
|
||||||
|
}
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
#define set_err
|
#define set_err
|
||||||
#else
|
#else
|
||||||
@@ -308,12 +352,13 @@ static inline int skel_link_create(int prog_fd, int target_fd,
|
|||||||
|
|
||||||
static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts)
|
static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts)
|
||||||
{
|
{
|
||||||
const size_t prog_load_attr_sz = offsetofend(union bpf_attr, fd_array);
|
const size_t prog_load_attr_sz = offsetofend(union bpf_attr, keyring_id);
|
||||||
const size_t test_run_attr_sz = offsetofend(union bpf_attr, test);
|
const size_t test_run_attr_sz = offsetofend(union bpf_attr, test);
|
||||||
int map_fd = -1, prog_fd = -1, key = 0, err;
|
int map_fd = -1, prog_fd = -1, key = 0, err;
|
||||||
union bpf_attr attr;
|
union bpf_attr attr;
|
||||||
|
|
||||||
err = map_fd = skel_map_create(BPF_MAP_TYPE_ARRAY, "__loader.map", 4, opts->data_sz, 1);
|
err = map_fd = skel_map_create(BPF_MAP_TYPE_ARRAY, "__loader.map", 4, opts->data_sz, 1,
|
||||||
|
opts->excl_prog_hash, opts->excl_prog_hash_sz);
|
||||||
if (map_fd < 0) {
|
if (map_fd < 0) {
|
||||||
opts->errstr = "failed to create loader map";
|
opts->errstr = "failed to create loader map";
|
||||||
set_err;
|
set_err;
|
||||||
@@ -327,11 +372,34 @@ static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __KERNEL__
|
||||||
|
err = skel_map_freeze(map_fd);
|
||||||
|
if (err < 0) {
|
||||||
|
opts->errstr = "failed to freeze map";
|
||||||
|
set_err;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
err = skel_obj_get_info_by_fd(map_fd);
|
||||||
|
if (err < 0) {
|
||||||
|
opts->errstr = "failed to fetch obj info";
|
||||||
|
set_err;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
memset(&attr, 0, prog_load_attr_sz);
|
memset(&attr, 0, prog_load_attr_sz);
|
||||||
attr.prog_type = BPF_PROG_TYPE_SYSCALL;
|
attr.prog_type = BPF_PROG_TYPE_SYSCALL;
|
||||||
attr.insns = (long) opts->insns;
|
attr.insns = (long) opts->insns;
|
||||||
attr.insn_cnt = opts->insns_sz / sizeof(struct bpf_insn);
|
attr.insn_cnt = opts->insns_sz / sizeof(struct bpf_insn);
|
||||||
attr.license = (long) "Dual BSD/GPL";
|
attr.license = (long) "Dual BSD/GPL";
|
||||||
|
#ifndef __KERNEL__
|
||||||
|
attr.signature = (long) opts->signature;
|
||||||
|
attr.signature_size = opts->signature_sz;
|
||||||
|
#else
|
||||||
|
if (opts->signature || opts->signature_sz)
|
||||||
|
pr_warn("signatures are not supported from bpf_preload\n");
|
||||||
|
#endif
|
||||||
|
attr.keyring_id = opts->keyring_id;
|
||||||
memcpy(attr.prog_name, "__loader.prog", sizeof("__loader.prog"));
|
memcpy(attr.prog_name, "__loader.prog", sizeof("__loader.prog"));
|
||||||
attr.fd_array = (long) &map_fd;
|
attr.fd_array = (long) &map_fd;
|
||||||
attr.log_level = opts->ctx->log_level;
|
attr.log_level = opts->ctx->log_level;
|
||||||
@@ -351,10 +419,11 @@ static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts)
|
|||||||
attr.test.ctx_size_in = opts->ctx->sz;
|
attr.test.ctx_size_in = opts->ctx->sz;
|
||||||
err = skel_sys_bpf(BPF_PROG_RUN, &attr, test_run_attr_sz);
|
err = skel_sys_bpf(BPF_PROG_RUN, &attr, test_run_attr_sz);
|
||||||
if (err < 0 || (int)attr.test.retval < 0) {
|
if (err < 0 || (int)attr.test.retval < 0) {
|
||||||
opts->errstr = "failed to execute loader prog";
|
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
|
opts->errstr = "failed to execute loader prog";
|
||||||
set_err;
|
set_err;
|
||||||
} else {
|
} else {
|
||||||
|
opts->errstr = "error returned by loader prog";
|
||||||
err = (int)attr.test.retval;
|
err = (int)attr.test.retval;
|
||||||
#ifndef __KERNEL__
|
#ifndef __KERNEL__
|
||||||
errno = -err;
|
errno = -err;
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
|
||||||
#undef _GNU_SOURCE
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include "str_error.h"
|
|
||||||
|
|
||||||
/* make sure libbpf doesn't use kernel-only integer typedefs */
|
|
||||||
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Wrapper to allow for building in non-GNU systems such as Alpine Linux's musl
|
|
||||||
* libc, while checking strerror_r() return to avoid having to check this in
|
|
||||||
* all places calling it.
|
|
||||||
*/
|
|
||||||
char *libbpf_strerror_r(int err, char *dst, int len)
|
|
||||||
{
|
|
||||||
int ret = strerror_r(err < 0 ? -err : err, dst, len);
|
|
||||||
/* on glibc <2.13, ret == -1 and errno is set, if strerror_r() can't
|
|
||||||
* handle the error, on glibc >=2.13 *positive* (errno-like) error
|
|
||||||
* code is returned directly
|
|
||||||
*/
|
|
||||||
if (ret == -1)
|
|
||||||
ret = errno;
|
|
||||||
if (ret) {
|
|
||||||
if (ret == EINVAL)
|
|
||||||
/* strerror_r() doesn't recognize this specific error */
|
|
||||||
snprintf(dst, len, "unknown error (%d)", err < 0 ? err : -err);
|
|
||||||
else
|
|
||||||
snprintf(dst, len, "ERROR: strerror_r(%d)=%d", err, ret);
|
|
||||||
}
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
|
||||||
#ifndef __LIBBPF_STR_ERROR_H
|
|
||||||
#define __LIBBPF_STR_ERROR_H
|
|
||||||
|
|
||||||
#define STRERR_BUFSIZE 128
|
|
||||||
|
|
||||||
char *libbpf_strerror_r(int err, char *dst, int len);
|
|
||||||
|
|
||||||
#endif /* __LIBBPF_STR_ERROR_H */
|
|
||||||
@@ -34,13 +34,32 @@ enum __bpf_usdt_arg_type {
|
|||||||
BPF_USDT_ARG_CONST,
|
BPF_USDT_ARG_CONST,
|
||||||
BPF_USDT_ARG_REG,
|
BPF_USDT_ARG_REG,
|
||||||
BPF_USDT_ARG_REG_DEREF,
|
BPF_USDT_ARG_REG_DEREF,
|
||||||
|
BPF_USDT_ARG_SIB,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This struct layout is designed specifically to be backwards/forward
|
||||||
|
* compatible between libbpf versions for ARG_CONST, ARG_REG, and
|
||||||
|
* ARG_REG_DEREF modes. ARG_SIB requires libbpf v1.7+.
|
||||||
|
*/
|
||||||
struct __bpf_usdt_arg_spec {
|
struct __bpf_usdt_arg_spec {
|
||||||
/* u64 scalar interpreted depending on arg_type, see below */
|
/* u64 scalar interpreted depending on arg_type, see below */
|
||||||
__u64 val_off;
|
__u64 val_off;
|
||||||
/* arg location case, see bpf_udst_arg() for details */
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||||
enum __bpf_usdt_arg_type arg_type;
|
/* arg location case, see bpf_usdt_arg() for details */
|
||||||
|
enum __bpf_usdt_arg_type arg_type: 8;
|
||||||
|
/* index register offset within struct pt_regs */
|
||||||
|
__u16 idx_reg_off: 12;
|
||||||
|
/* scale factor for index register (1, 2, 4, or 8) */
|
||||||
|
__u16 scale_bitshift: 4;
|
||||||
|
/* reserved for future use, keeps reg_off offset stable */
|
||||||
|
__u8 __reserved: 8;
|
||||||
|
#else
|
||||||
|
__u8 __reserved: 8;
|
||||||
|
__u16 idx_reg_off: 12;
|
||||||
|
__u16 scale_bitshift: 4;
|
||||||
|
enum __bpf_usdt_arg_type arg_type: 8;
|
||||||
|
#endif
|
||||||
/* offset of referenced register within struct pt_regs */
|
/* offset of referenced register within struct pt_regs */
|
||||||
short reg_off;
|
short reg_off;
|
||||||
/* whether arg should be interpreted as signed value */
|
/* whether arg should be interpreted as signed value */
|
||||||
@@ -108,6 +127,38 @@ int bpf_usdt_arg_cnt(struct pt_regs *ctx)
|
|||||||
return spec->arg_cnt;
|
return spec->arg_cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns the size in bytes of the #*arg_num* (zero-indexed) USDT argument.
|
||||||
|
* Returns negative error if argument is not found or arg_num is invalid.
|
||||||
|
*/
|
||||||
|
static __always_inline
|
||||||
|
int bpf_usdt_arg_size(struct pt_regs *ctx, __u64 arg_num)
|
||||||
|
{
|
||||||
|
struct __bpf_usdt_arg_spec *arg_spec;
|
||||||
|
struct __bpf_usdt_spec *spec;
|
||||||
|
int spec_id;
|
||||||
|
|
||||||
|
spec_id = __bpf_usdt_spec_id(ctx);
|
||||||
|
if (spec_id < 0)
|
||||||
|
return -ESRCH;
|
||||||
|
|
||||||
|
spec = bpf_map_lookup_elem(&__bpf_usdt_specs, &spec_id);
|
||||||
|
if (!spec)
|
||||||
|
return -ESRCH;
|
||||||
|
|
||||||
|
if (arg_num >= BPF_USDT_MAX_ARG_CNT)
|
||||||
|
return -ENOENT;
|
||||||
|
barrier_var(arg_num);
|
||||||
|
if (arg_num >= spec->arg_cnt)
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
arg_spec = &spec->args[arg_num];
|
||||||
|
|
||||||
|
/* arg_spec->arg_bitshift = 64 - arg_sz * 8
|
||||||
|
* so: arg_sz = (64 - arg_spec->arg_bitshift) / 8
|
||||||
|
*/
|
||||||
|
return (unsigned int)(64 - arg_spec->arg_bitshift) / 8;
|
||||||
|
}
|
||||||
|
|
||||||
/* Fetch USDT argument #*arg_num* (zero-indexed) and put its value into *res.
|
/* Fetch USDT argument #*arg_num* (zero-indexed) and put its value into *res.
|
||||||
* Returns 0 on success; negative error, otherwise.
|
* Returns 0 on success; negative error, otherwise.
|
||||||
* On error *res is guaranteed to be set to zero.
|
* On error *res is guaranteed to be set to zero.
|
||||||
@@ -117,7 +168,7 @@ int bpf_usdt_arg(struct pt_regs *ctx, __u64 arg_num, long *res)
|
|||||||
{
|
{
|
||||||
struct __bpf_usdt_spec *spec;
|
struct __bpf_usdt_spec *spec;
|
||||||
struct __bpf_usdt_arg_spec *arg_spec;
|
struct __bpf_usdt_arg_spec *arg_spec;
|
||||||
unsigned long val;
|
unsigned long val, idx;
|
||||||
int err, spec_id;
|
int err, spec_id;
|
||||||
|
|
||||||
*res = 0;
|
*res = 0;
|
||||||
@@ -170,6 +221,27 @@ int bpf_usdt_arg(struct pt_regs *ctx, __u64 arg_num, long *res)
|
|||||||
return err;
|
return err;
|
||||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
val >>= arg_spec->arg_bitshift;
|
val >>= arg_spec->arg_bitshift;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case BPF_USDT_ARG_SIB:
|
||||||
|
/* Arg is in memory addressed by SIB (Scale-Index-Base) mode
|
||||||
|
* (e.g., "-1@-96(%rbp,%rax,8)" in USDT arg spec). We first
|
||||||
|
* fetch the base register contents and the index register
|
||||||
|
* contents from pt_regs. Then we calculate the final address
|
||||||
|
* as base + (index * scale) + offset, and do a user-space
|
||||||
|
* probe read to fetch the argument value.
|
||||||
|
*/
|
||||||
|
err = bpf_probe_read_kernel(&val, sizeof(val), (void *)ctx + arg_spec->reg_off);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
err = bpf_probe_read_kernel(&idx, sizeof(idx), (void *)ctx + arg_spec->idx_reg_off);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
err = bpf_probe_read_user(&val, sizeof(val), (void *)(val + (idx << arg_spec->scale_bitshift) + arg_spec->val_off));
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
|
val >>= arg_spec->arg_bitshift;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
117
src/usdt.c
117
src/usdt.c
@@ -58,7 +58,7 @@
|
|||||||
*
|
*
|
||||||
* STAP_PROBE3(my_usdt_provider, my_usdt_probe_name, 123, x, &y);
|
* STAP_PROBE3(my_usdt_provider, my_usdt_probe_name, 123, x, &y);
|
||||||
*
|
*
|
||||||
* USDT is identified by it's <provider-name>:<probe-name> pair of names. Each
|
* USDT is identified by its <provider-name>:<probe-name> pair of names. Each
|
||||||
* individual USDT has a fixed number of arguments (3 in the above example)
|
* individual USDT has a fixed number of arguments (3 in the above example)
|
||||||
* and specifies values of each argument as if it was a function call.
|
* and specifies values of each argument as if it was a function call.
|
||||||
*
|
*
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
* NOP instruction that kernel can replace with an interrupt instruction to
|
* NOP instruction that kernel can replace with an interrupt instruction to
|
||||||
* trigger instrumentation code (BPF program for all that we care about).
|
* trigger instrumentation code (BPF program for all that we care about).
|
||||||
*
|
*
|
||||||
* Semaphore above is and optional feature. It records an address of a 2-byte
|
* Semaphore above is an optional feature. It records an address of a 2-byte
|
||||||
* refcount variable (normally in '.probes' ELF section) used for signaling if
|
* refcount variable (normally in '.probes' ELF section) used for signaling if
|
||||||
* there is anything that is attached to USDT. This is useful for user
|
* there is anything that is attached to USDT. This is useful for user
|
||||||
* applications if, for example, they need to prepare some arguments that are
|
* applications if, for example, they need to prepare some arguments that are
|
||||||
@@ -120,7 +120,7 @@
|
|||||||
* a uprobe BPF program (which for kernel, at least currently, is just a kprobe
|
* a uprobe BPF program (which for kernel, at least currently, is just a kprobe
|
||||||
* program, so BPF_PROG_TYPE_KPROBE program type). With the only difference
|
* program, so BPF_PROG_TYPE_KPROBE program type). With the only difference
|
||||||
* that uprobe is usually attached at the function entry, while USDT will
|
* that uprobe is usually attached at the function entry, while USDT will
|
||||||
* normally will be somewhere inside the function. But it should always be
|
* normally be somewhere inside the function. But it should always be
|
||||||
* pointing to NOP instruction, which makes such uprobes the fastest uprobe
|
* pointing to NOP instruction, which makes such uprobes the fastest uprobe
|
||||||
* kind.
|
* kind.
|
||||||
*
|
*
|
||||||
@@ -150,7 +150,7 @@
|
|||||||
* libbpf sets to spec ID during attach time, or, if kernel is too old to
|
* libbpf sets to spec ID during attach time, or, if kernel is too old to
|
||||||
* support BPF cookie, through IP-to-spec-ID map that libbpf maintains in such
|
* support BPF cookie, through IP-to-spec-ID map that libbpf maintains in such
|
||||||
* case. The latter means that some modes of operation can't be supported
|
* case. The latter means that some modes of operation can't be supported
|
||||||
* without BPF cookie. Such mode is attaching to shared library "generically",
|
* without BPF cookie. Such a mode is attaching to shared library "generically",
|
||||||
* without specifying target process. In such case, it's impossible to
|
* without specifying target process. In such case, it's impossible to
|
||||||
* calculate absolute IP addresses for IP-to-spec-ID map, and thus such mode
|
* calculate absolute IP addresses for IP-to-spec-ID map, and thus such mode
|
||||||
* is not supported without BPF cookie support.
|
* is not supported without BPF cookie support.
|
||||||
@@ -184,7 +184,7 @@
|
|||||||
* as even if USDT spec string is the same, USDT cookie value can be
|
* as even if USDT spec string is the same, USDT cookie value can be
|
||||||
* different. It was deemed excessive to try to deduplicate across independent
|
* different. It was deemed excessive to try to deduplicate across independent
|
||||||
* USDT attachments by taking into account USDT spec string *and* USDT cookie
|
* USDT attachments by taking into account USDT spec string *and* USDT cookie
|
||||||
* value, which would complicated spec ID accounting significantly for little
|
* value, which would complicate spec ID accounting significantly for little
|
||||||
* gain.
|
* gain.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -199,12 +199,23 @@ enum usdt_arg_type {
|
|||||||
USDT_ARG_CONST,
|
USDT_ARG_CONST,
|
||||||
USDT_ARG_REG,
|
USDT_ARG_REG,
|
||||||
USDT_ARG_REG_DEREF,
|
USDT_ARG_REG_DEREF,
|
||||||
|
USDT_ARG_SIB,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* should match exactly struct __bpf_usdt_arg_spec from usdt.bpf.h */
|
/* should match exactly struct __bpf_usdt_arg_spec from usdt.bpf.h */
|
||||||
struct usdt_arg_spec {
|
struct usdt_arg_spec {
|
||||||
__u64 val_off;
|
__u64 val_off;
|
||||||
enum usdt_arg_type arg_type;
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||||
|
enum usdt_arg_type arg_type: 8;
|
||||||
|
__u16 idx_reg_off: 12;
|
||||||
|
__u16 scale_bitshift: 4;
|
||||||
|
__u8 __reserved: 8; /* keep reg_off offset stable */
|
||||||
|
#else
|
||||||
|
__u8 __reserved: 8; /* keep reg_off offset stable */
|
||||||
|
__u16 idx_reg_off: 12;
|
||||||
|
__u16 scale_bitshift: 4;
|
||||||
|
enum usdt_arg_type arg_type: 8;
|
||||||
|
#endif
|
||||||
short reg_off;
|
short reg_off;
|
||||||
bool arg_signed;
|
bool arg_signed;
|
||||||
char arg_bitshift;
|
char arg_bitshift;
|
||||||
@@ -465,8 +476,8 @@ static int parse_vma_segs(int pid, const char *lib_path, struct elf_seg **segs,
|
|||||||
goto proceed;
|
goto proceed;
|
||||||
|
|
||||||
if (!realpath(lib_path, path)) {
|
if (!realpath(lib_path, path)) {
|
||||||
pr_warn("usdt: failed to get absolute path of '%s' (err %d), using path as is...\n",
|
pr_warn("usdt: failed to get absolute path of '%s' (err %s), using path as is...\n",
|
||||||
lib_path, -errno);
|
lib_path, errstr(-errno));
|
||||||
libbpf_strlcpy(path, lib_path, sizeof(path));
|
libbpf_strlcpy(path, lib_path, sizeof(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -475,8 +486,8 @@ proceed:
|
|||||||
f = fopen(line, "re");
|
f = fopen(line, "re");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
err = -errno;
|
err = -errno;
|
||||||
pr_warn("usdt: failed to open '%s' to get base addr of '%s': %d\n",
|
pr_warn("usdt: failed to open '%s' to get base addr of '%s': %s\n",
|
||||||
line, lib_path, err);
|
line, lib_path, errstr(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -569,9 +580,8 @@ static struct elf_seg *find_vma_seg(struct elf_seg *segs, size_t seg_cnt, long o
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_usdt_note(Elf *elf, const char *path, GElf_Nhdr *nhdr,
|
static int parse_usdt_note(GElf_Nhdr *nhdr, const char *data, size_t name_off,
|
||||||
const char *data, size_t name_off, size_t desc_off,
|
size_t desc_off, struct usdt_note *usdt_note);
|
||||||
struct usdt_note *usdt_note);
|
|
||||||
|
|
||||||
static int parse_usdt_spec(struct usdt_spec *spec, const struct usdt_note *note, __u64 usdt_cookie);
|
static int parse_usdt_spec(struct usdt_spec *spec, const struct usdt_note *note, __u64 usdt_cookie);
|
||||||
|
|
||||||
@@ -606,7 +616,8 @@ static int collect_usdt_targets(struct usdt_manager *man, Elf *elf, const char *
|
|||||||
|
|
||||||
err = parse_elf_segs(elf, path, &segs, &seg_cnt);
|
err = parse_elf_segs(elf, path, &segs, &seg_cnt);
|
||||||
if (err) {
|
if (err) {
|
||||||
pr_warn("usdt: failed to process ELF program segments for '%s': %d\n", path, err);
|
pr_warn("usdt: failed to process ELF program segments for '%s': %s\n",
|
||||||
|
path, errstr(err));
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -624,7 +635,7 @@ static int collect_usdt_targets(struct usdt_manager *man, Elf *elf, const char *
|
|||||||
struct elf_seg *seg = NULL;
|
struct elf_seg *seg = NULL;
|
||||||
void *tmp;
|
void *tmp;
|
||||||
|
|
||||||
err = parse_usdt_note(elf, path, &nhdr, data->d_buf, name_off, desc_off, ¬e);
|
err = parse_usdt_note(&nhdr, data->d_buf, name_off, desc_off, ¬e);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
|
|
||||||
@@ -659,7 +670,7 @@ static int collect_usdt_targets(struct usdt_manager *man, Elf *elf, const char *
|
|||||||
* [0] https://sourceware.org/systemtap/wiki/UserSpaceProbeImplementation
|
* [0] https://sourceware.org/systemtap/wiki/UserSpaceProbeImplementation
|
||||||
*/
|
*/
|
||||||
usdt_abs_ip = note.loc_addr;
|
usdt_abs_ip = note.loc_addr;
|
||||||
if (base_addr)
|
if (base_addr && note.base_addr)
|
||||||
usdt_abs_ip += base_addr - note.base_addr;
|
usdt_abs_ip += base_addr - note.base_addr;
|
||||||
|
|
||||||
/* When attaching uprobes (which is what USDTs basically are)
|
/* When attaching uprobes (which is what USDTs basically are)
|
||||||
@@ -708,8 +719,8 @@ static int collect_usdt_targets(struct usdt_manager *man, Elf *elf, const char *
|
|||||||
if (vma_seg_cnt == 0) {
|
if (vma_seg_cnt == 0) {
|
||||||
err = parse_vma_segs(pid, path, &vma_segs, &vma_seg_cnt);
|
err = parse_vma_segs(pid, path, &vma_segs, &vma_seg_cnt);
|
||||||
if (err) {
|
if (err) {
|
||||||
pr_warn("usdt: failed to get memory segments in PID %d for shared library '%s': %d\n",
|
pr_warn("usdt: failed to get memory segments in PID %d for shared library '%s': %s\n",
|
||||||
pid, path, err);
|
pid, path, errstr(err));
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1047,8 +1058,8 @@ struct bpf_link *usdt_manager_attach_usdt(struct usdt_manager *man, const struct
|
|||||||
|
|
||||||
if (is_new && bpf_map_update_elem(spec_map_fd, &spec_id, &target->spec, BPF_ANY)) {
|
if (is_new && bpf_map_update_elem(spec_map_fd, &spec_id, &target->spec, BPF_ANY)) {
|
||||||
err = -errno;
|
err = -errno;
|
||||||
pr_warn("usdt: failed to set USDT spec #%d for '%s:%s' in '%s': %d\n",
|
pr_warn("usdt: failed to set USDT spec #%d for '%s:%s' in '%s': %s\n",
|
||||||
spec_id, usdt_provider, usdt_name, path, err);
|
spec_id, usdt_provider, usdt_name, path, errstr(err));
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
if (!man->has_bpf_cookie &&
|
if (!man->has_bpf_cookie &&
|
||||||
@@ -1058,9 +1069,9 @@ struct bpf_link *usdt_manager_attach_usdt(struct usdt_manager *man, const struct
|
|||||||
pr_warn("usdt: IP collision detected for spec #%d for '%s:%s' in '%s'\n",
|
pr_warn("usdt: IP collision detected for spec #%d for '%s:%s' in '%s'\n",
|
||||||
spec_id, usdt_provider, usdt_name, path);
|
spec_id, usdt_provider, usdt_name, path);
|
||||||
} else {
|
} else {
|
||||||
pr_warn("usdt: failed to map IP 0x%lx to spec #%d for '%s:%s' in '%s': %d\n",
|
pr_warn("usdt: failed to map IP 0x%lx to spec #%d for '%s:%s' in '%s': %s\n",
|
||||||
target->abs_ip, spec_id, usdt_provider, usdt_name,
|
target->abs_ip, spec_id, usdt_provider, usdt_name,
|
||||||
path, err);
|
path, errstr(err));
|
||||||
}
|
}
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
@@ -1076,8 +1087,8 @@ struct bpf_link *usdt_manager_attach_usdt(struct usdt_manager *man, const struct
|
|||||||
target->rel_ip, &opts);
|
target->rel_ip, &opts);
|
||||||
err = libbpf_get_error(uprobe_link);
|
err = libbpf_get_error(uprobe_link);
|
||||||
if (err) {
|
if (err) {
|
||||||
pr_warn("usdt: failed to attach uprobe #%d for '%s:%s' in '%s': %d\n",
|
pr_warn("usdt: failed to attach uprobe #%d for '%s:%s' in '%s': %s\n",
|
||||||
i, usdt_provider, usdt_name, path, err);
|
i, usdt_provider, usdt_name, path, errstr(err));
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1099,8 +1110,8 @@ struct bpf_link *usdt_manager_attach_usdt(struct usdt_manager *man, const struct
|
|||||||
NULL, &opts_multi);
|
NULL, &opts_multi);
|
||||||
if (!link->multi_link) {
|
if (!link->multi_link) {
|
||||||
err = -errno;
|
err = -errno;
|
||||||
pr_warn("usdt: failed to attach uprobe multi for '%s:%s' in '%s': %d\n",
|
pr_warn("usdt: failed to attach uprobe multi for '%s:%s' in '%s': %s\n",
|
||||||
usdt_provider, usdt_name, path, err);
|
usdt_provider, usdt_name, path, errstr(err));
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1130,8 +1141,7 @@ err_out:
|
|||||||
/* Parse out USDT ELF note from '.note.stapsdt' section.
|
/* Parse out USDT ELF note from '.note.stapsdt' section.
|
||||||
* Logic inspired by perf's code.
|
* Logic inspired by perf's code.
|
||||||
*/
|
*/
|
||||||
static int parse_usdt_note(Elf *elf, const char *path, GElf_Nhdr *nhdr,
|
static int parse_usdt_note(GElf_Nhdr *nhdr, const char *data, size_t name_off, size_t desc_off,
|
||||||
const char *data, size_t name_off, size_t desc_off,
|
|
||||||
struct usdt_note *note)
|
struct usdt_note *note)
|
||||||
{
|
{
|
||||||
const char *provider, *name, *args;
|
const char *provider, *name, *args;
|
||||||
@@ -1281,11 +1291,51 @@ static int calc_pt_regs_off(const char *reg_name)
|
|||||||
|
|
||||||
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz)
|
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz)
|
||||||
{
|
{
|
||||||
char reg_name[16];
|
char reg_name[16] = {0}, idx_reg_name[16] = {0};
|
||||||
int len, reg_off;
|
int len, reg_off, idx_reg_off, scale = 1;
|
||||||
long off;
|
long off = 0;
|
||||||
|
|
||||||
if (sscanf(arg_str, " %d @ %ld ( %%%15[^)] ) %n", arg_sz, &off, reg_name, &len) == 3) {
|
if (sscanf(arg_str, " %d @ %ld ( %%%15[^,] , %%%15[^,] , %d ) %n",
|
||||||
|
arg_sz, &off, reg_name, idx_reg_name, &scale, &len) == 5 ||
|
||||||
|
sscanf(arg_str, " %d @ ( %%%15[^,] , %%%15[^,] , %d ) %n",
|
||||||
|
arg_sz, reg_name, idx_reg_name, &scale, &len) == 4 ||
|
||||||
|
sscanf(arg_str, " %d @ %ld ( %%%15[^,] , %%%15[^)] ) %n",
|
||||||
|
arg_sz, &off, reg_name, idx_reg_name, &len) == 4 ||
|
||||||
|
sscanf(arg_str, " %d @ ( %%%15[^,] , %%%15[^)] ) %n",
|
||||||
|
arg_sz, reg_name, idx_reg_name, &len) == 3
|
||||||
|
) {
|
||||||
|
/*
|
||||||
|
* Scale Index Base case:
|
||||||
|
* 1@-96(%rbp,%rax,8)
|
||||||
|
* 1@(%rbp,%rax,8)
|
||||||
|
* 1@-96(%rbp,%rax)
|
||||||
|
* 1@(%rbp,%rax)
|
||||||
|
*/
|
||||||
|
arg->arg_type = USDT_ARG_SIB;
|
||||||
|
arg->val_off = off;
|
||||||
|
|
||||||
|
reg_off = calc_pt_regs_off(reg_name);
|
||||||
|
if (reg_off < 0)
|
||||||
|
return reg_off;
|
||||||
|
arg->reg_off = reg_off;
|
||||||
|
|
||||||
|
idx_reg_off = calc_pt_regs_off(idx_reg_name);
|
||||||
|
if (idx_reg_off < 0)
|
||||||
|
return idx_reg_off;
|
||||||
|
arg->idx_reg_off = idx_reg_off;
|
||||||
|
|
||||||
|
/* validate scale factor and set fields directly */
|
||||||
|
switch (scale) {
|
||||||
|
case 1: arg->scale_bitshift = 0; break;
|
||||||
|
case 2: arg->scale_bitshift = 1; break;
|
||||||
|
case 4: arg->scale_bitshift = 2; break;
|
||||||
|
case 8: arg->scale_bitshift = 3; break;
|
||||||
|
default:
|
||||||
|
pr_warn("usdt: invalid SIB scale %d, expected 1, 2, 4, 8\n", scale);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
} else if (sscanf(arg_str, " %d @ %ld ( %%%15[^)] ) %n",
|
||||||
|
arg_sz, &off, reg_name, &len) == 3) {
|
||||||
/* Memory dereference case, e.g., -4@-20(%rbp) */
|
/* Memory dereference case, e.g., -4@-20(%rbp) */
|
||||||
arg->arg_type = USDT_ARG_REG_DEREF;
|
arg->arg_type = USDT_ARG_REG_DEREF;
|
||||||
arg->val_off = off;
|
arg->val_off = off;
|
||||||
@@ -1304,6 +1354,7 @@ static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec
|
|||||||
} else if (sscanf(arg_str, " %d @ %%%15s %n", arg_sz, reg_name, &len) == 2) {
|
} else if (sscanf(arg_str, " %d @ %%%15s %n", arg_sz, reg_name, &len) == 2) {
|
||||||
/* Register read case, e.g., -4@%eax */
|
/* Register read case, e.g., -4@%eax */
|
||||||
arg->arg_type = USDT_ARG_REG;
|
arg->arg_type = USDT_ARG_REG;
|
||||||
|
/* register read has no memory offset */
|
||||||
arg->val_off = 0;
|
arg->val_off = 0;
|
||||||
|
|
||||||
reg_off = calc_pt_regs_off(reg_name);
|
reg_off = calc_pt_regs_off(reg_name);
|
||||||
@@ -1325,8 +1376,6 @@ static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec
|
|||||||
|
|
||||||
#elif defined(__s390x__)
|
#elif defined(__s390x__)
|
||||||
|
|
||||||
/* Do not support __s390__ for now, since user_pt_regs is broken with -m31. */
|
|
||||||
|
|
||||||
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz)
|
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz)
|
||||||
{
|
{
|
||||||
unsigned int reg;
|
unsigned int reg;
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ struct zip_archive *zip_archive_open(const char *path)
|
|||||||
if (!archive) {
|
if (!archive) {
|
||||||
munmap(data, size);
|
munmap(data, size);
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
};
|
}
|
||||||
|
|
||||||
archive->data = data;
|
archive->data = data;
|
||||||
archive->size = size;
|
archive->size = size;
|
||||||
|
|||||||
Reference in New Issue
Block a user