mirror of
https://github.com/netdata/libbpf.git
synced 2026-03-25 10:49:06 +08:00
Compare commits
152 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a1615c263 | ||
|
|
e66d297441 | ||
|
|
632afdff45 | ||
|
|
6e706b38bd | ||
|
|
850293ba1c | ||
|
|
fb528063b2 | ||
|
|
97ada10bd8 | ||
|
|
9a35753b42 | ||
|
|
c4af2093cc | ||
|
|
1543a19f36 | ||
|
|
8b41602694 | ||
|
|
cecb299ac4 | ||
|
|
90e89264b9 | ||
|
|
f69cc97272 | ||
|
|
a6e9750c8a | ||
|
|
60bade6674 | ||
|
|
e13c1b7b85 | ||
|
|
1d8451ccaf | ||
|
|
fad6e249ea | ||
|
|
64f7fa917c | ||
|
|
240b8fa098 | ||
|
|
3756d20499 | ||
|
|
9e8b23289f | ||
|
|
902eca48e5 | ||
|
|
9f0d55c24a | ||
|
|
e53dd1c436 | ||
|
|
da790d6014 | ||
|
|
3d81b13b36 | ||
|
|
64bd9e074b | ||
|
|
53d473dd8e | ||
|
|
6d64d927a2 | ||
|
|
cd87f1568e | ||
|
|
c417a4cb6f | ||
|
|
fa21d33fff | ||
|
|
84cf76de9c | ||
|
|
2ef4fdac6c | ||
|
|
1d72c9c382 | ||
|
|
7930230b43 | ||
|
|
483a8c238f | ||
|
|
26cbe2384c | ||
|
|
cb4a430c8a | ||
|
|
f67d535cdb | ||
|
|
ef4785f065 | ||
|
|
9a424bea42 | ||
|
|
10e4311ad7 | ||
|
|
50febacba1 | ||
|
|
ef7d57fcec | ||
|
|
7e7a15321e | ||
|
|
77ac09c3eb | ||
|
|
40a08ef216 | ||
|
|
b6683d1aeb | ||
|
|
5247b0b0dc | ||
|
|
c2b01ad4f3 | ||
|
|
c4468dec74 | ||
|
|
40229b3ffd | ||
|
|
7f2d538c27 | ||
|
|
b7c162a433 | ||
|
|
36c26f12f1 | ||
|
|
22d5d40493 | ||
|
|
17c26b7da6 | ||
|
|
e287979374 | ||
|
|
552af3d963 | ||
|
|
c772c9cbde | ||
|
|
031a38cceb | ||
|
|
6ff5062480 | ||
|
|
fdff85e63e | ||
|
|
5c7661fd5e | ||
|
|
1feb21b081 | ||
|
|
fa8cb316fb | ||
|
|
f72fe00e70 | ||
|
|
583bddce6b | ||
|
|
a52fb86a96 | ||
|
|
e5dbc1a96f | ||
|
|
96333403ca | ||
|
|
928f2fc146 | ||
|
|
8fd8b5bb46 | ||
|
|
b999e8f2c1 | ||
|
|
c6c86a53f2 | ||
|
|
c69f0d12f3 | ||
|
|
033ad7ee78 | ||
|
|
397db2175d | ||
|
|
6756bdc96e | ||
|
|
9c1ae55dbd | ||
|
|
091f073ff0 | ||
|
|
ad51a528dc | ||
|
|
fa29cc01ff | ||
|
|
a2bec08412 | ||
|
|
080fd68e9c | ||
|
|
437f57042c | ||
|
|
f4f271b068 | ||
|
|
bd35a43bb3 | ||
|
|
d91f681d3b | ||
|
|
1e51491d05 | ||
|
|
37440e95d1 | ||
|
|
681f2f9291 | ||
|
|
0e4638ec14 | ||
|
|
234a45a128 | ||
|
|
8687395198 | ||
|
|
0cccc9ff28 | ||
|
|
b50eb28758 | ||
|
|
8d936a1570 | ||
|
|
2c8602eb54 | ||
|
|
1ef23426e7 | ||
|
|
d2100072b9 | ||
|
|
f3edca46e5 | ||
|
|
cabb077325 | ||
|
|
b95b281039 | ||
|
|
5033d7177e | ||
|
|
49058f8c6f | ||
|
|
8b20ffa4b9 | ||
|
|
1b1e30679f | ||
|
|
e7a82fc033 | ||
|
|
7c5583ab2d | ||
|
|
0d9d85e345 | ||
|
|
c8c4edf4c9 | ||
|
|
23983fd75b | ||
|
|
4bbdefdce1 | ||
|
|
5bc09e54fa | ||
|
|
9f61b5b95c | ||
|
|
baa3268b13 | ||
|
|
f5599ef856 | ||
|
|
99c65fed78 | ||
|
|
e9adfa851f | ||
|
|
8363b8d4e6 | ||
|
|
f892b464d0 | ||
|
|
a4132d1590 | ||
|
|
303916a126 | ||
|
|
8eea7ed8e8 | ||
|
|
fa030ffd20 | ||
|
|
ea06bc30fa | ||
|
|
531ac0e65f | ||
|
|
e35cb347ce | ||
|
|
68fa3f0b57 | ||
|
|
1c145f0fda | ||
|
|
418c07226a | ||
|
|
5ec0ba6530 | ||
|
|
600ba1c5e1 | ||
|
|
aa73e35dc3 | ||
|
|
dca6176410 | ||
|
|
6f88f26945 | ||
|
|
f7af143516 | ||
|
|
4f3c7b3e13 | ||
|
|
b85e83f6cb | ||
|
|
33d1fbea57 | ||
|
|
b234d12c97 | ||
|
|
7a1d185108 | ||
|
|
76d5bb6a13 | ||
|
|
c42bfcbf0e | ||
|
|
c2fc7c15a3 | ||
|
|
4060a65222 | ||
|
|
a26f6b1375 | ||
|
|
6e686c26fa |
151
.travis.yml
151
.travis.yml
@@ -1,13 +1,27 @@
|
|||||||
sudo: required
|
sudo: required
|
||||||
|
language: bash
|
||||||
dist: bionic
|
dist: bionic
|
||||||
services:
|
services:
|
||||||
- docker
|
- docker
|
||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
|
- PROJECT_NAME='libbpf'
|
||||||
- AUTHOR_EMAIL="$(git log -1 --pretty=\"%aE\")"
|
- AUTHOR_EMAIL="$(git log -1 --pretty=\"%aE\")"
|
||||||
- CI_MANAGERS="$TRAVIS_BUILD_DIR/travis-ci/managers"
|
|
||||||
- REPO_ROOT="$TRAVIS_BUILD_DIR"
|
- REPO_ROOT="$TRAVIS_BUILD_DIR"
|
||||||
|
- CI_ROOT="$REPO_ROOT/travis-ci"
|
||||||
|
- VMTEST_ROOT="$CI_ROOT/vmtest"
|
||||||
|
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- qemu-kvm
|
||||||
|
- zstd
|
||||||
|
- binutils-dev
|
||||||
|
- elfutils
|
||||||
|
- libcap-dev
|
||||||
|
- libelf-dev
|
||||||
|
- libdw-dev
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
# Run Coverity periodically instead of for each PR for following reasons:
|
# Run Coverity periodically instead of for each PR for following reasons:
|
||||||
@@ -21,113 +35,72 @@ stages:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
include:
|
include:
|
||||||
- stage: Build & test
|
- stage: Build
|
||||||
name: Debian Testing
|
name: Debian Build
|
||||||
language: bash
|
language: bash
|
||||||
env:
|
install: $CI_ROOT/managers/debian.sh SETUP
|
||||||
- DEBIAN_RELEASE="testing"
|
script: $CI_ROOT/managers/debian.sh RUN || travis_terminate
|
||||||
- CONT_NAME="libbpf-debian-$DEBIAN_RELEASE"
|
after_script: $CI_ROOT/managers/debian.sh CLEANUP
|
||||||
before_install:
|
|
||||||
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
|
|
||||||
- docker --version
|
|
||||||
install:
|
|
||||||
- $CI_MANAGERS/debian.sh SETUP
|
|
||||||
script:
|
|
||||||
- $CI_MANAGERS/debian.sh RUN || travis_terminate
|
|
||||||
after_script:
|
|
||||||
- $CI_MANAGERS/debian.sh CLEANUP
|
|
||||||
|
|
||||||
- name: Debian Testing (ASan+UBSan)
|
- name: Debian Build (ASan+UBSan)
|
||||||
language: bash
|
language: bash
|
||||||
env:
|
install: $CI_ROOT/managers/debian.sh SETUP
|
||||||
- DEBIAN_RELEASE="testing"
|
script: $CI_ROOT/managers/debian.sh RUN_ASAN || travis_terminate
|
||||||
- CONT_NAME="libbpf-debian-$DEBIAN_RELEASE"
|
after_script: $CI_ROOT/managers/debian.sh CLEANUP
|
||||||
before_install:
|
|
||||||
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
|
|
||||||
- docker --version
|
|
||||||
install:
|
|
||||||
- $CI_MANAGERS/debian.sh SETUP
|
|
||||||
script:
|
|
||||||
- $CI_MANAGERS/debian.sh RUN_ASAN || travis_terminate
|
|
||||||
after_script:
|
|
||||||
- $CI_MANAGERS/debian.sh CLEANUP
|
|
||||||
|
|
||||||
- name: Debian Testing (clang)
|
- name: Debian Build (clang)
|
||||||
language: bash
|
language: bash
|
||||||
env:
|
install: $CI_ROOT/managers/debian.sh SETUP
|
||||||
- DEBIAN_RELEASE="testing"
|
script: $CI_ROOT/managers/debian.sh RUN_CLANG || travis_terminate
|
||||||
- CONT_NAME="libbpf-debian-$DEBIAN_RELEASE"
|
after_script: $CI_ROOT/managers/debian.sh CLEANUP
|
||||||
before_install:
|
|
||||||
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
|
|
||||||
- docker --version
|
|
||||||
install:
|
|
||||||
- $CI_MANAGERS/debian.sh SETUP
|
|
||||||
script:
|
|
||||||
- $CI_MANAGERS/debian.sh RUN_CLANG || travis_terminate
|
|
||||||
after_script:
|
|
||||||
- $CI_MANAGERS/debian.sh CLEANUP
|
|
||||||
|
|
||||||
- name: Debian Testing (clang ASan+UBSan)
|
- name: Debian Build (clang ASan+UBSan)
|
||||||
language: bash
|
language: bash
|
||||||
env:
|
install: $CI_ROOT/managers/debian.sh SETUP
|
||||||
- DEBIAN_RELEASE="testing"
|
script: $CI_ROOT/managers/debian.sh RUN_CLANG_ASAN || travis_terminate
|
||||||
- CONT_NAME="libbpf-debian-$DEBIAN_RELEASE"
|
after_script: $CI_ROOT/managers/debian.sh CLEANUP
|
||||||
before_install:
|
|
||||||
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
|
|
||||||
- docker --version
|
|
||||||
install:
|
|
||||||
- $CI_MANAGERS/debian.sh SETUP
|
|
||||||
script:
|
|
||||||
- $CI_MANAGERS/debian.sh RUN_CLANG_ASAN || travis_terminate
|
|
||||||
after_script:
|
|
||||||
- $CI_MANAGERS/debian.sh CLEANUP
|
|
||||||
|
|
||||||
- name: Debian Testing (gcc-8)
|
- name: Debian Build (gcc-8)
|
||||||
language: bash
|
language: bash
|
||||||
env:
|
install: $CI_ROOT/managers/debian.sh SETUP
|
||||||
- DEBIAN_RELEASE="testing"
|
script: $CI_ROOT/managers/debian.sh RUN_GCC8 || travis_terminate
|
||||||
- CONT_NAME="libbpf-debian-$DEBIAN_RELEASE"
|
after_script: $CI_ROOT/managers/debian.sh CLEANUP
|
||||||
before_install:
|
|
||||||
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
|
|
||||||
- docker --version
|
|
||||||
install:
|
|
||||||
- $CI_MANAGERS/debian.sh SETUP
|
|
||||||
script:
|
|
||||||
- $CI_MANAGERS/debian.sh RUN_GCC8 || travis_terminate
|
|
||||||
after_script:
|
|
||||||
- $CI_MANAGERS/debian.sh CLEANUP
|
|
||||||
|
|
||||||
- name: Debian Testing (gcc-8 ASan+UBSan)
|
- name: Debian Build (gcc-8 ASan+UBSan)
|
||||||
language: bash
|
language: bash
|
||||||
env:
|
install: $CI_ROOT/managers/debian.sh SETUP
|
||||||
- DEBIAN_RELEASE="testing"
|
script: $CI_ROOT/managers/debian.sh RUN_GCC8_ASAN || travis_terminate
|
||||||
- CONT_NAME="libbpf-debian-$DEBIAN_RELEASE"
|
after_script: $CI_ROOT/managers/debian.sh CLEANUP
|
||||||
before_install:
|
|
||||||
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
|
|
||||||
- docker --version
|
|
||||||
install:
|
|
||||||
- $CI_MANAGERS/debian.sh SETUP
|
|
||||||
script:
|
|
||||||
- $CI_MANAGERS/debian.sh RUN_GCC8_ASAN || travis_terminate
|
|
||||||
after_script:
|
|
||||||
- $CI_MANAGERS/debian.sh CLEANUP
|
|
||||||
|
|
||||||
- name: Ubuntu Bionic
|
- name: Ubuntu Bionic Build
|
||||||
language: bash
|
language: bash
|
||||||
script:
|
script: sudo $CI_ROOT/managers/ubuntu.sh || travis_terminate
|
||||||
- sudo $CI_MANAGERS/ubuntu.sh || travis_terminate
|
|
||||||
|
|
||||||
- name: Ubuntu Bionic (arm)
|
- name: Ubuntu Bionic Build (arm)
|
||||||
arch: arm64
|
arch: arm64
|
||||||
language: bash
|
language: bash
|
||||||
script:
|
script: sudo $CI_ROOT/managers/ubuntu.sh || travis_terminate
|
||||||
- sudo $CI_MANAGERS/ubuntu.sh || travis_terminate
|
|
||||||
|
|
||||||
- name: Ubuntu Bionic (s390x)
|
- name: Ubuntu Bionic Build (s390x)
|
||||||
arch: s390x
|
arch: s390x
|
||||||
language: bash
|
language: bash
|
||||||
script:
|
script: sudo $CI_ROOT/managers/ubuntu.sh || travis_terminate
|
||||||
- sudo $CI_MANAGERS/ubuntu.sh || travis_terminate
|
|
||||||
|
- name: Ubuntu Bionic Build (ppc64le)
|
||||||
|
arch: ppc64le
|
||||||
|
language: bash
|
||||||
|
script: sudo $CI_ROOT/managers/ubuntu.sh || travis_terminate
|
||||||
|
|
||||||
|
- stage: Build & Test
|
||||||
|
name: Kernel 5.5.0 + selftests
|
||||||
|
language: bash
|
||||||
|
env: KERNEL=5.5.0
|
||||||
|
script: $CI_ROOT/vmtest/run_vmtest.sh || travis_terminate
|
||||||
|
|
||||||
|
- name: Kernel LATEST + selftests
|
||||||
|
language: bash
|
||||||
|
env: KERNEL=LATEST
|
||||||
|
script: $CI_ROOT/vmtest/run_vmtest.sh || travis_terminate
|
||||||
|
|
||||||
- stage: Coverity
|
- stage: Coverity
|
||||||
language: bash
|
language: bash
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
e42617b825f8073569da76dc4510bfa019b1c35a
|
edadedf1c5b4e4404192a0a4c3c0c05e3b7672ab
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
e7096c131e5161fa3b8e52a650d7719d2857adfd
|
2fcd80144b93ff90836a44f2054b4d82133d3a85
|
||||||
|
|||||||
22
README.md
22
README.md
@@ -51,6 +51,28 @@ $ cd src
|
|||||||
$ PKG_CONFIG_PATH=/build/root/lib64/pkgconfig DESTDIR=/build/root make install
|
$ PKG_CONFIG_PATH=/build/root/lib64/pkgconfig DESTDIR=/build/root make install
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Distributions
|
||||||
|
=====
|
||||||
|
|
||||||
|
Distributions packaging libbpf from this mirror:
|
||||||
|
- [Fedora](https://src.fedoraproject.org/rpms/libbpf)
|
||||||
|
- [Gentoo](https://packages.gentoo.org/packages/dev-libs/libbpf)
|
||||||
|
|
||||||
|
Benefits of packaging from the mirror over packaging from kernel sources:
|
||||||
|
- Consistent versioning across distributions.
|
||||||
|
- No ties to any specific kernel, transparent handling of older kernels.
|
||||||
|
Libbpf is designed to be kernel-agnostic and work across multitude of kernel
|
||||||
|
versions. It has built-in mechanisms to gracefully handle older kernels,
|
||||||
|
that are missing some of the features, by working around or gracefully
|
||||||
|
degrading functionality. Thus libbpf is not tied to a specific kernel
|
||||||
|
version and can/should be packaged and versioned independently.
|
||||||
|
- Continuous integration testing via [TravisCI](https://travis-ci.org/libbpf/libbpf).
|
||||||
|
- Static code analysis via [LGTM](https://lgtm.com/projects/g/libbpf/libbpf) and [Coverity](https://scan.coverity.com/projects/libbpf).
|
||||||
|
|
||||||
|
Package dependencies of libbpf, package names may vary across distros:
|
||||||
|
- zlib
|
||||||
|
- libelf
|
||||||
|
|
||||||
License
|
License
|
||||||
=====
|
=====
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ struct bpf_insn {
|
|||||||
/* Key of an a BPF_MAP_TYPE_LPM_TRIE entry */
|
/* Key of an a BPF_MAP_TYPE_LPM_TRIE entry */
|
||||||
struct bpf_lpm_trie_key {
|
struct bpf_lpm_trie_key {
|
||||||
__u32 prefixlen; /* up to 32 for AF_INET, 128 for AF_INET6 */
|
__u32 prefixlen; /* up to 32 for AF_INET, 128 for AF_INET6 */
|
||||||
__u8 data[0]; /* Arbitrary size */
|
__u8 data[]; /* Arbitrary size */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bpf_cgroup_storage_key {
|
struct bpf_cgroup_storage_key {
|
||||||
@@ -107,6 +107,12 @@ enum bpf_cmd {
|
|||||||
BPF_MAP_LOOKUP_AND_DELETE_ELEM,
|
BPF_MAP_LOOKUP_AND_DELETE_ELEM,
|
||||||
BPF_MAP_FREEZE,
|
BPF_MAP_FREEZE,
|
||||||
BPF_BTF_GET_NEXT_ID,
|
BPF_BTF_GET_NEXT_ID,
|
||||||
|
BPF_MAP_LOOKUP_BATCH,
|
||||||
|
BPF_MAP_LOOKUP_AND_DELETE_BATCH,
|
||||||
|
BPF_MAP_UPDATE_BATCH,
|
||||||
|
BPF_MAP_DELETE_BATCH,
|
||||||
|
BPF_LINK_CREATE,
|
||||||
|
BPF_LINK_UPDATE,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum bpf_map_type {
|
enum bpf_map_type {
|
||||||
@@ -136,6 +142,7 @@ enum bpf_map_type {
|
|||||||
BPF_MAP_TYPE_STACK,
|
BPF_MAP_TYPE_STACK,
|
||||||
BPF_MAP_TYPE_SK_STORAGE,
|
BPF_MAP_TYPE_SK_STORAGE,
|
||||||
BPF_MAP_TYPE_DEVMAP_HASH,
|
BPF_MAP_TYPE_DEVMAP_HASH,
|
||||||
|
BPF_MAP_TYPE_STRUCT_OPS,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Note that tracing related programs such as
|
/* Note that tracing related programs such as
|
||||||
@@ -174,6 +181,9 @@ enum bpf_prog_type {
|
|||||||
BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE,
|
BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE,
|
||||||
BPF_PROG_TYPE_CGROUP_SOCKOPT,
|
BPF_PROG_TYPE_CGROUP_SOCKOPT,
|
||||||
BPF_PROG_TYPE_TRACING,
|
BPF_PROG_TYPE_TRACING,
|
||||||
|
BPF_PROG_TYPE_STRUCT_OPS,
|
||||||
|
BPF_PROG_TYPE_EXT,
|
||||||
|
BPF_PROG_TYPE_LSM,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum bpf_attach_type {
|
enum bpf_attach_type {
|
||||||
@@ -203,6 +213,8 @@ enum bpf_attach_type {
|
|||||||
BPF_TRACE_RAW_TP,
|
BPF_TRACE_RAW_TP,
|
||||||
BPF_TRACE_FENTRY,
|
BPF_TRACE_FENTRY,
|
||||||
BPF_TRACE_FEXIT,
|
BPF_TRACE_FEXIT,
|
||||||
|
BPF_MODIFY_RETURN,
|
||||||
|
BPF_LSM_MAC,
|
||||||
__MAX_BPF_ATTACH_TYPE
|
__MAX_BPF_ATTACH_TYPE
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -231,6 +243,11 @@ enum bpf_attach_type {
|
|||||||
* When children program makes decision (like picking TCP CA or sock bind)
|
* When children program makes decision (like picking TCP CA or sock bind)
|
||||||
* parent program has a chance to override it.
|
* parent program has a chance to override it.
|
||||||
*
|
*
|
||||||
|
* With BPF_F_ALLOW_MULTI a new program is added to the end of the list of
|
||||||
|
* programs for a cgroup. Though it's possible to replace an old program at
|
||||||
|
* any position by also specifying BPF_F_REPLACE flag and position itself in
|
||||||
|
* replace_bpf_fd attribute. Old program at this position will be released.
|
||||||
|
*
|
||||||
* A cgroup with MULTI or OVERRIDE flag allows any attach flags in sub-cgroups.
|
* A cgroup with MULTI or OVERRIDE flag allows any attach flags in sub-cgroups.
|
||||||
* A cgroup with NONE doesn't allow any programs in sub-cgroups.
|
* A cgroup with NONE doesn't allow any programs in sub-cgroups.
|
||||||
* Ex1:
|
* Ex1:
|
||||||
@@ -249,6 +266,7 @@ enum bpf_attach_type {
|
|||||||
*/
|
*/
|
||||||
#define BPF_F_ALLOW_OVERRIDE (1U << 0)
|
#define BPF_F_ALLOW_OVERRIDE (1U << 0)
|
||||||
#define BPF_F_ALLOW_MULTI (1U << 1)
|
#define BPF_F_ALLOW_MULTI (1U << 1)
|
||||||
|
#define BPF_F_REPLACE (1U << 2)
|
||||||
|
|
||||||
/* 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
|
||||||
* verifier will perform strict alignment checking as if the kernel
|
* verifier will perform strict alignment checking as if the kernel
|
||||||
@@ -312,46 +330,53 @@ enum bpf_attach_type {
|
|||||||
#define BPF_PSEUDO_CALL 1
|
#define BPF_PSEUDO_CALL 1
|
||||||
|
|
||||||
/* flags for BPF_MAP_UPDATE_ELEM command */
|
/* flags for BPF_MAP_UPDATE_ELEM command */
|
||||||
#define BPF_ANY 0 /* create new element or update existing */
|
enum {
|
||||||
#define BPF_NOEXIST 1 /* create new element if it didn't exist */
|
BPF_ANY = 0, /* create new element or update existing */
|
||||||
#define BPF_EXIST 2 /* update existing element */
|
BPF_NOEXIST = 1, /* create new element if it didn't exist */
|
||||||
#define BPF_F_LOCK 4 /* spin_lock-ed map_lookup/map_update */
|
BPF_EXIST = 2, /* update existing element */
|
||||||
|
BPF_F_LOCK = 4, /* spin_lock-ed map_lookup/map_update */
|
||||||
|
};
|
||||||
|
|
||||||
/* flags for BPF_MAP_CREATE command */
|
/* flags for BPF_MAP_CREATE command */
|
||||||
#define BPF_F_NO_PREALLOC (1U << 0)
|
enum {
|
||||||
|
BPF_F_NO_PREALLOC = (1U << 0),
|
||||||
/* Instead of having one common LRU list in the
|
/* Instead of having one common LRU list in the
|
||||||
* BPF_MAP_TYPE_LRU_[PERCPU_]HASH map, use a percpu LRU list
|
* BPF_MAP_TYPE_LRU_[PERCPU_]HASH map, use a percpu LRU list
|
||||||
* which can scale and perform better.
|
* which can scale and perform better.
|
||||||
* Note, the LRU nodes (including free nodes) cannot be moved
|
* Note, the LRU nodes (including free nodes) cannot be moved
|
||||||
* across different LRU lists.
|
* across different LRU lists.
|
||||||
*/
|
*/
|
||||||
#define BPF_F_NO_COMMON_LRU (1U << 1)
|
BPF_F_NO_COMMON_LRU = (1U << 1),
|
||||||
/* Specify numa node during map creation */
|
/* Specify numa node during map creation */
|
||||||
#define BPF_F_NUMA_NODE (1U << 2)
|
BPF_F_NUMA_NODE = (1U << 2),
|
||||||
|
|
||||||
#define BPF_OBJ_NAME_LEN 16U
|
|
||||||
|
|
||||||
/* Flags for accessing BPF object from syscall side. */
|
/* Flags for accessing BPF object from syscall side. */
|
||||||
#define BPF_F_RDONLY (1U << 3)
|
BPF_F_RDONLY = (1U << 3),
|
||||||
#define BPF_F_WRONLY (1U << 4)
|
BPF_F_WRONLY = (1U << 4),
|
||||||
|
|
||||||
/* Flag for stack_map, store build_id+offset instead of pointer */
|
/* Flag for stack_map, store build_id+offset instead of pointer */
|
||||||
#define BPF_F_STACK_BUILD_ID (1U << 5)
|
BPF_F_STACK_BUILD_ID = (1U << 5),
|
||||||
|
|
||||||
/* Zero-initialize hash function seed. This should only be used for testing. */
|
/* Zero-initialize hash function seed. This should only be used for testing. */
|
||||||
#define BPF_F_ZERO_SEED (1U << 6)
|
BPF_F_ZERO_SEED = (1U << 6),
|
||||||
|
|
||||||
/* Flags for accessing BPF object from program side. */
|
/* Flags for accessing BPF object from program side. */
|
||||||
#define BPF_F_RDONLY_PROG (1U << 7)
|
BPF_F_RDONLY_PROG = (1U << 7),
|
||||||
#define BPF_F_WRONLY_PROG (1U << 8)
|
BPF_F_WRONLY_PROG = (1U << 8),
|
||||||
|
|
||||||
/* Clone map from listener for newly accepted socket */
|
/* Clone map from listener for newly accepted socket */
|
||||||
#define BPF_F_CLONE (1U << 9)
|
BPF_F_CLONE = (1U << 9),
|
||||||
|
|
||||||
/* Enable memory-mapping BPF map */
|
/* Enable memory-mapping BPF map */
|
||||||
#define BPF_F_MMAPABLE (1U << 10)
|
BPF_F_MMAPABLE = (1U << 10),
|
||||||
|
};
|
||||||
|
|
||||||
/* flags for BPF_PROG_QUERY */
|
/* Flags for BPF_PROG_QUERY. */
|
||||||
|
|
||||||
|
/* Query effective (directly attached + inherited from ancestor cgroups)
|
||||||
|
* programs that will be executed for events within a cgroup.
|
||||||
|
* attach_flags with this flag are returned only for directly attached programs.
|
||||||
|
*/
|
||||||
#define BPF_F_QUERY_EFFECTIVE (1U << 0)
|
#define BPF_F_QUERY_EFFECTIVE (1U << 0)
|
||||||
|
|
||||||
enum bpf_stack_build_id_status {
|
enum bpf_stack_build_id_status {
|
||||||
@@ -373,6 +398,8 @@ struct bpf_stack_build_id {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define BPF_OBJ_NAME_LEN 16U
|
||||||
|
|
||||||
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 */
|
||||||
@@ -391,6 +418,10 @@ union bpf_attr {
|
|||||||
__u32 btf_fd; /* fd pointing to a BTF type data */
|
__u32 btf_fd; /* fd pointing to a BTF type data */
|
||||||
__u32 btf_key_type_id; /* BTF type_id of the key */
|
__u32 btf_key_type_id; /* BTF type_id of the key */
|
||||||
__u32 btf_value_type_id; /* BTF type_id of the value */
|
__u32 btf_value_type_id; /* BTF type_id of the value */
|
||||||
|
__u32 btf_vmlinux_value_type_id;/* BTF type_id of a kernel-
|
||||||
|
* struct stored as the
|
||||||
|
* map value
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */
|
struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */
|
||||||
@@ -403,6 +434,23 @@ union bpf_attr {
|
|||||||
__u64 flags;
|
__u64 flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct { /* struct used by BPF_MAP_*_BATCH commands */
|
||||||
|
__aligned_u64 in_batch; /* start batch,
|
||||||
|
* NULL to start from beginning
|
||||||
|
*/
|
||||||
|
__aligned_u64 out_batch; /* output: next start batch */
|
||||||
|
__aligned_u64 keys;
|
||||||
|
__aligned_u64 values;
|
||||||
|
__u32 count; /* input/output:
|
||||||
|
* input: # of key/value
|
||||||
|
* elements
|
||||||
|
* output: # of filled elements
|
||||||
|
*/
|
||||||
|
__u32 map_fd;
|
||||||
|
__u64 elem_flags;
|
||||||
|
__u64 flags;
|
||||||
|
} batch;
|
||||||
|
|
||||||
struct { /* anonymous struct used by BPF_PROG_LOAD command */
|
struct { /* anonymous struct used by BPF_PROG_LOAD command */
|
||||||
__u32 prog_type; /* one of enum bpf_prog_type */
|
__u32 prog_type; /* one of enum bpf_prog_type */
|
||||||
__u32 insn_cnt;
|
__u32 insn_cnt;
|
||||||
@@ -442,6 +490,10 @@ union bpf_attr {
|
|||||||
__u32 attach_bpf_fd; /* eBPF program to attach */
|
__u32 attach_bpf_fd; /* eBPF program to attach */
|
||||||
__u32 attach_type;
|
__u32 attach_type;
|
||||||
__u32 attach_flags;
|
__u32 attach_flags;
|
||||||
|
__u32 replace_bpf_fd; /* previously attached eBPF
|
||||||
|
* program to replace if
|
||||||
|
* BPF_F_REPLACE is used
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
struct { /* anonymous struct used by BPF_PROG_TEST_RUN command */
|
struct { /* anonymous struct used by BPF_PROG_TEST_RUN command */
|
||||||
@@ -491,7 +543,7 @@ union bpf_attr {
|
|||||||
__u32 prog_cnt;
|
__u32 prog_cnt;
|
||||||
} query;
|
} query;
|
||||||
|
|
||||||
struct {
|
struct { /* anonymous struct used by BPF_RAW_TRACEPOINT_OPEN command */
|
||||||
__u64 name;
|
__u64 name;
|
||||||
__u32 prog_fd;
|
__u32 prog_fd;
|
||||||
} raw_tracepoint;
|
} raw_tracepoint;
|
||||||
@@ -519,6 +571,24 @@ union bpf_attr {
|
|||||||
__u64 probe_offset; /* output: probe_offset */
|
__u64 probe_offset; /* output: probe_offset */
|
||||||
__u64 probe_addr; /* output: probe_addr */
|
__u64 probe_addr; /* output: probe_addr */
|
||||||
} task_fd_query;
|
} task_fd_query;
|
||||||
|
|
||||||
|
struct { /* struct used by BPF_LINK_CREATE command */
|
||||||
|
__u32 prog_fd; /* eBPF program to attach */
|
||||||
|
__u32 target_fd; /* object to attach to */
|
||||||
|
__u32 attach_type; /* attach type */
|
||||||
|
__u32 flags; /* extra flags */
|
||||||
|
} link_create;
|
||||||
|
|
||||||
|
struct { /* struct used by BPF_LINK_UPDATE command */
|
||||||
|
__u32 link_fd; /* link fd */
|
||||||
|
/* new program fd to update link with */
|
||||||
|
__u32 new_prog_fd;
|
||||||
|
__u32 flags; /* extra flags */
|
||||||
|
/* expected link's program fd; is specified only if
|
||||||
|
* BPF_F_REPLACE flag is set in flags */
|
||||||
|
__u32 old_prog_fd;
|
||||||
|
} link_update;
|
||||||
|
|
||||||
} __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
|
||||||
@@ -1002,9 +1072,9 @@ union bpf_attr {
|
|||||||
* supports redirection to the egress interface, and accepts no
|
* supports redirection to the egress interface, and accepts no
|
||||||
* flag at all.
|
* flag at all.
|
||||||
*
|
*
|
||||||
* The same effect can be attained with the more generic
|
* The same effect can also be attained with the more generic
|
||||||
* **bpf_redirect_map**\ (), which requires specific maps to be
|
* **bpf_redirect_map**\ (), which uses a BPF map to store the
|
||||||
* used but offers better performance.
|
* redirect target instead of providing it directly to the helper.
|
||||||
* Return
|
* Return
|
||||||
* For XDP, the helper returns **XDP_REDIRECT** on success or
|
* For XDP, the helper returns **XDP_REDIRECT** on success or
|
||||||
* **XDP_ABORTED** on error. For other program types, the values
|
* **XDP_ABORTED** on error. For other program types, the values
|
||||||
@@ -1568,13 +1638,11 @@ union bpf_attr {
|
|||||||
* the caller. Any higher bits in the *flags* argument must be
|
* the caller. Any higher bits in the *flags* argument must be
|
||||||
* unset.
|
* unset.
|
||||||
*
|
*
|
||||||
* When used to redirect packets to net devices, this helper
|
* See also bpf_redirect(), which only supports redirecting to an
|
||||||
* provides a high performance increase over **bpf_redirect**\ ().
|
* ifindex, but doesn't require a map to do so.
|
||||||
* This is due to various implementation details of the underlying
|
|
||||||
* mechanisms, one of which is the fact that **bpf_redirect_map**\
|
|
||||||
* () tries to send packet as a "bulk" to the device.
|
|
||||||
* Return
|
* Return
|
||||||
* **XDP_REDIRECT** on success, or **XDP_ABORTED** on error.
|
* **XDP_REDIRECT** on success, or the value of the two lower bits
|
||||||
|
* of the **flags* argument on error.
|
||||||
*
|
*
|
||||||
* int bpf_sk_redirect_map(struct sk_buff *skb, struct bpf_map *map, u32 key, u64 flags)
|
* int bpf_sk_redirect_map(struct sk_buff *skb, struct bpf_map *map, u32 key, u64 flags)
|
||||||
* Description
|
* Description
|
||||||
@@ -2693,7 +2761,8 @@ union bpf_attr {
|
|||||||
*
|
*
|
||||||
* int bpf_send_signal(u32 sig)
|
* int bpf_send_signal(u32 sig)
|
||||||
* Description
|
* Description
|
||||||
* Send signal *sig* to the current task.
|
* Send signal *sig* to the process of the current task.
|
||||||
|
* The signal may be delivered to any of this process's threads.
|
||||||
* Return
|
* Return
|
||||||
* 0 on success or successfully queued.
|
* 0 on success or successfully queued.
|
||||||
*
|
*
|
||||||
@@ -2821,6 +2890,141 @@ union bpf_attr {
|
|||||||
* Return
|
* Return
|
||||||
* On success, the strictly positive length of the string, including
|
* On success, the strictly positive length of the string, including
|
||||||
* the trailing NUL character. On error, a negative value.
|
* the trailing NUL character. On error, a negative value.
|
||||||
|
*
|
||||||
|
* int bpf_tcp_send_ack(void *tp, u32 rcv_nxt)
|
||||||
|
* Description
|
||||||
|
* Send out a tcp-ack. *tp* is the in-kernel struct tcp_sock.
|
||||||
|
* *rcv_nxt* is the ack_seq to be sent out.
|
||||||
|
* Return
|
||||||
|
* 0 on success, or a negative error in case of failure.
|
||||||
|
*
|
||||||
|
* int bpf_send_signal_thread(u32 sig)
|
||||||
|
* Description
|
||||||
|
* Send signal *sig* to the thread corresponding to the current task.
|
||||||
|
* Return
|
||||||
|
* 0 on success or successfully queued.
|
||||||
|
*
|
||||||
|
* **-EBUSY** if work queue under nmi is full.
|
||||||
|
*
|
||||||
|
* **-EINVAL** if *sig* is invalid.
|
||||||
|
*
|
||||||
|
* **-EPERM** if no permission to send the *sig*.
|
||||||
|
*
|
||||||
|
* **-EAGAIN** if bpf program can try again.
|
||||||
|
*
|
||||||
|
* u64 bpf_jiffies64(void)
|
||||||
|
* Description
|
||||||
|
* Obtain the 64bit jiffies
|
||||||
|
* Return
|
||||||
|
* The 64 bit jiffies
|
||||||
|
*
|
||||||
|
* int bpf_read_branch_records(struct bpf_perf_event_data *ctx, void *buf, u32 size, u64 flags)
|
||||||
|
* Description
|
||||||
|
* For an eBPF program attached to a perf event, retrieve the
|
||||||
|
* branch records (struct perf_branch_entry) associated to *ctx*
|
||||||
|
* and store it in the buffer pointed by *buf* up to size
|
||||||
|
* *size* bytes.
|
||||||
|
* Return
|
||||||
|
* On success, number of bytes written to *buf*. On error, a
|
||||||
|
* negative value.
|
||||||
|
*
|
||||||
|
* The *flags* can be set to **BPF_F_GET_BRANCH_RECORDS_SIZE** to
|
||||||
|
* instead return the number of bytes required to store all the
|
||||||
|
* branch entries. If this flag is set, *buf* may be NULL.
|
||||||
|
*
|
||||||
|
* **-EINVAL** if arguments invalid or **size** not a multiple
|
||||||
|
* of sizeof(struct perf_branch_entry).
|
||||||
|
*
|
||||||
|
* **-ENOENT** if architecture does not support branch records.
|
||||||
|
*
|
||||||
|
* int bpf_get_ns_current_pid_tgid(u64 dev, u64 ino, struct bpf_pidns_info *nsdata, u32 size)
|
||||||
|
* Description
|
||||||
|
* Returns 0 on success, values for *pid* and *tgid* as seen from the current
|
||||||
|
* *namespace* will be returned in *nsdata*.
|
||||||
|
*
|
||||||
|
* On failure, the returned value is one of the following:
|
||||||
|
*
|
||||||
|
* **-EINVAL** if dev and inum supplied don't match dev_t and inode number
|
||||||
|
* with nsfs of current task, or if dev conversion to dev_t lost high bits.
|
||||||
|
*
|
||||||
|
* **-ENOENT** if pidns does not exists for the current task.
|
||||||
|
*
|
||||||
|
* int bpf_xdp_output(void *ctx, struct bpf_map *map, u64 flags, void *data, u64 size)
|
||||||
|
* Description
|
||||||
|
* Write raw *data* blob into a special BPF perf event held by
|
||||||
|
* *map* of type **BPF_MAP_TYPE_PERF_EVENT_ARRAY**. This perf
|
||||||
|
* event must have the following attributes: **PERF_SAMPLE_RAW**
|
||||||
|
* as **sample_type**, **PERF_TYPE_SOFTWARE** as **type**, and
|
||||||
|
* **PERF_COUNT_SW_BPF_OUTPUT** as **config**.
|
||||||
|
*
|
||||||
|
* The *flags* are used to indicate the index in *map* for which
|
||||||
|
* the value must be put, masked with **BPF_F_INDEX_MASK**.
|
||||||
|
* Alternatively, *flags* can be set to **BPF_F_CURRENT_CPU**
|
||||||
|
* to indicate that the index of the current CPU core should be
|
||||||
|
* used.
|
||||||
|
*
|
||||||
|
* The value to write, of *size*, is passed through eBPF stack and
|
||||||
|
* pointed by *data*.
|
||||||
|
*
|
||||||
|
* *ctx* is a pointer to in-kernel struct xdp_buff.
|
||||||
|
*
|
||||||
|
* This helper is similar to **bpf_perf_eventoutput**\ () but
|
||||||
|
* restricted to raw_tracepoint bpf programs.
|
||||||
|
* Return
|
||||||
|
* 0 on success, or a negative error in case of failure.
|
||||||
|
*
|
||||||
|
* u64 bpf_get_netns_cookie(void *ctx)
|
||||||
|
* Description
|
||||||
|
* Retrieve the cookie (generated by the kernel) of the network
|
||||||
|
* namespace the input *ctx* is associated with. The network
|
||||||
|
* namespace cookie remains stable for its lifetime and provides
|
||||||
|
* a global identifier that can be assumed unique. If *ctx* is
|
||||||
|
* NULL, then the helper returns the cookie for the initial
|
||||||
|
* network namespace. The cookie itself is very similar to that
|
||||||
|
* of bpf_get_socket_cookie() helper, but for network namespaces
|
||||||
|
* instead of sockets.
|
||||||
|
* Return
|
||||||
|
* A 8-byte long opaque number.
|
||||||
|
*
|
||||||
|
* u64 bpf_get_current_ancestor_cgroup_id(int ancestor_level)
|
||||||
|
* Description
|
||||||
|
* Return id of cgroup v2 that is ancestor of the cgroup associated
|
||||||
|
* with the current task at the *ancestor_level*. The root cgroup
|
||||||
|
* is at *ancestor_level* zero and each step down the hierarchy
|
||||||
|
* increments the level. If *ancestor_level* == level of cgroup
|
||||||
|
* associated with the current task, then return value will be the
|
||||||
|
* same as that of **bpf_get_current_cgroup_id**\ ().
|
||||||
|
*
|
||||||
|
* The helper is useful to implement policies based on cgroups
|
||||||
|
* that are upper in hierarchy than immediate cgroup associated
|
||||||
|
* with the current task.
|
||||||
|
*
|
||||||
|
* The format of returned id and helper limitations are same as in
|
||||||
|
* **bpf_get_current_cgroup_id**\ ().
|
||||||
|
* Return
|
||||||
|
* The id is returned or 0 in case the id could not be retrieved.
|
||||||
|
*
|
||||||
|
* int bpf_sk_assign(struct sk_buff *skb, struct bpf_sock *sk, u64 flags)
|
||||||
|
* Description
|
||||||
|
* Assign the *sk* to the *skb*. When combined with appropriate
|
||||||
|
* routing configuration to receive the packet towards the socket,
|
||||||
|
* will cause *skb* to be delivered to the specified socket.
|
||||||
|
* Subsequent redirection of *skb* via **bpf_redirect**\ (),
|
||||||
|
* **bpf_clone_redirect**\ () or other methods outside of BPF may
|
||||||
|
* interfere with successful delivery to the socket.
|
||||||
|
*
|
||||||
|
* This operation is only valid from TC ingress path.
|
||||||
|
*
|
||||||
|
* The *flags* argument must be zero.
|
||||||
|
* Return
|
||||||
|
* 0 on success, or a negative errno in case of failure.
|
||||||
|
*
|
||||||
|
* * **-EINVAL** Unsupported flags specified.
|
||||||
|
* * **-ENOENT** Socket is unavailable for assignment.
|
||||||
|
* * **-ENETUNREACH** Socket is unreachable (wrong netns).
|
||||||
|
* * **-EOPNOTSUPP** Unsupported operation, for example a
|
||||||
|
* call from outside of TC ingress.
|
||||||
|
* * **-ESOCKTNOSUPPORT** Socket type not supported (reuseport).
|
||||||
*/
|
*/
|
||||||
#define __BPF_FUNC_MAPPER(FN) \
|
#define __BPF_FUNC_MAPPER(FN) \
|
||||||
FN(unspec), \
|
FN(unspec), \
|
||||||
@@ -2938,7 +3142,16 @@ union bpf_attr {
|
|||||||
FN(probe_read_user), \
|
FN(probe_read_user), \
|
||||||
FN(probe_read_kernel), \
|
FN(probe_read_kernel), \
|
||||||
FN(probe_read_user_str), \
|
FN(probe_read_user_str), \
|
||||||
FN(probe_read_kernel_str),
|
FN(probe_read_kernel_str), \
|
||||||
|
FN(tcp_send_ack), \
|
||||||
|
FN(send_signal_thread), \
|
||||||
|
FN(jiffies64), \
|
||||||
|
FN(read_branch_records), \
|
||||||
|
FN(get_ns_current_pid_tgid), \
|
||||||
|
FN(xdp_output), \
|
||||||
|
FN(get_netns_cookie), \
|
||||||
|
FN(get_current_ancestor_cgroup_id), \
|
||||||
|
FN(sk_assign),
|
||||||
|
|
||||||
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
|
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
|
||||||
* function eBPF program intends to call
|
* function eBPF program intends to call
|
||||||
@@ -2953,69 +3166,100 @@ enum bpf_func_id {
|
|||||||
/* All flags used by eBPF helper functions, placed here. */
|
/* All flags used by eBPF helper functions, placed here. */
|
||||||
|
|
||||||
/* BPF_FUNC_skb_store_bytes flags. */
|
/* BPF_FUNC_skb_store_bytes flags. */
|
||||||
#define BPF_F_RECOMPUTE_CSUM (1ULL << 0)
|
enum {
|
||||||
#define BPF_F_INVALIDATE_HASH (1ULL << 1)
|
BPF_F_RECOMPUTE_CSUM = (1ULL << 0),
|
||||||
|
BPF_F_INVALIDATE_HASH = (1ULL << 1),
|
||||||
|
};
|
||||||
|
|
||||||
/* BPF_FUNC_l3_csum_replace and BPF_FUNC_l4_csum_replace flags.
|
/* BPF_FUNC_l3_csum_replace and BPF_FUNC_l4_csum_replace flags.
|
||||||
* First 4 bits are for passing the header field size.
|
* First 4 bits are for passing the header field size.
|
||||||
*/
|
*/
|
||||||
#define BPF_F_HDR_FIELD_MASK 0xfULL
|
enum {
|
||||||
|
BPF_F_HDR_FIELD_MASK = 0xfULL,
|
||||||
|
};
|
||||||
|
|
||||||
/* BPF_FUNC_l4_csum_replace flags. */
|
/* BPF_FUNC_l4_csum_replace flags. */
|
||||||
#define BPF_F_PSEUDO_HDR (1ULL << 4)
|
enum {
|
||||||
#define BPF_F_MARK_MANGLED_0 (1ULL << 5)
|
BPF_F_PSEUDO_HDR = (1ULL << 4),
|
||||||
#define BPF_F_MARK_ENFORCE (1ULL << 6)
|
BPF_F_MARK_MANGLED_0 = (1ULL << 5),
|
||||||
|
BPF_F_MARK_ENFORCE = (1ULL << 6),
|
||||||
|
};
|
||||||
|
|
||||||
/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */
|
/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */
|
||||||
#define BPF_F_INGRESS (1ULL << 0)
|
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. */
|
||||||
#define BPF_F_TUNINFO_IPV6 (1ULL << 0)
|
enum {
|
||||||
|
BPF_F_TUNINFO_IPV6 = (1ULL << 0),
|
||||||
|
};
|
||||||
|
|
||||||
/* flags for both BPF_FUNC_get_stackid and BPF_FUNC_get_stack. */
|
/* flags for both BPF_FUNC_get_stackid and BPF_FUNC_get_stack. */
|
||||||
#define BPF_F_SKIP_FIELD_MASK 0xffULL
|
enum {
|
||||||
#define BPF_F_USER_STACK (1ULL << 8)
|
BPF_F_SKIP_FIELD_MASK = 0xffULL,
|
||||||
|
BPF_F_USER_STACK = (1ULL << 8),
|
||||||
/* flags used by BPF_FUNC_get_stackid only. */
|
/* flags used by BPF_FUNC_get_stackid only. */
|
||||||
#define BPF_F_FAST_STACK_CMP (1ULL << 9)
|
BPF_F_FAST_STACK_CMP = (1ULL << 9),
|
||||||
#define BPF_F_REUSE_STACKID (1ULL << 10)
|
BPF_F_REUSE_STACKID = (1ULL << 10),
|
||||||
/* flags used by BPF_FUNC_get_stack only. */
|
/* flags used by BPF_FUNC_get_stack only. */
|
||||||
#define BPF_F_USER_BUILD_ID (1ULL << 11)
|
BPF_F_USER_BUILD_ID = (1ULL << 11),
|
||||||
|
};
|
||||||
|
|
||||||
/* BPF_FUNC_skb_set_tunnel_key flags. */
|
/* BPF_FUNC_skb_set_tunnel_key flags. */
|
||||||
#define BPF_F_ZERO_CSUM_TX (1ULL << 1)
|
enum {
|
||||||
#define BPF_F_DONT_FRAGMENT (1ULL << 2)
|
BPF_F_ZERO_CSUM_TX = (1ULL << 1),
|
||||||
#define BPF_F_SEQ_NUMBER (1ULL << 3)
|
BPF_F_DONT_FRAGMENT = (1ULL << 2),
|
||||||
|
BPF_F_SEQ_NUMBER = (1ULL << 3),
|
||||||
|
};
|
||||||
|
|
||||||
/* BPF_FUNC_perf_event_output, BPF_FUNC_perf_event_read and
|
/* BPF_FUNC_perf_event_output, BPF_FUNC_perf_event_read and
|
||||||
* BPF_FUNC_perf_event_read_value flags.
|
* BPF_FUNC_perf_event_read_value flags.
|
||||||
*/
|
*/
|
||||||
#define BPF_F_INDEX_MASK 0xffffffffULL
|
enum {
|
||||||
#define BPF_F_CURRENT_CPU BPF_F_INDEX_MASK
|
BPF_F_INDEX_MASK = 0xffffffffULL,
|
||||||
|
BPF_F_CURRENT_CPU = BPF_F_INDEX_MASK,
|
||||||
/* BPF_FUNC_perf_event_output for sk_buff input context. */
|
/* BPF_FUNC_perf_event_output for sk_buff input context. */
|
||||||
#define BPF_F_CTXLEN_MASK (0xfffffULL << 32)
|
BPF_F_CTXLEN_MASK = (0xfffffULL << 32),
|
||||||
|
};
|
||||||
|
|
||||||
/* Current network namespace */
|
/* Current network namespace */
|
||||||
#define BPF_F_CURRENT_NETNS (-1L)
|
enum {
|
||||||
|
BPF_F_CURRENT_NETNS = (-1L),
|
||||||
|
};
|
||||||
|
|
||||||
/* BPF_FUNC_skb_adjust_room flags. */
|
/* BPF_FUNC_skb_adjust_room flags. */
|
||||||
#define BPF_F_ADJ_ROOM_FIXED_GSO (1ULL << 0)
|
enum {
|
||||||
|
BPF_F_ADJ_ROOM_FIXED_GSO = (1ULL << 0),
|
||||||
|
BPF_F_ADJ_ROOM_ENCAP_L3_IPV4 = (1ULL << 1),
|
||||||
|
BPF_F_ADJ_ROOM_ENCAP_L3_IPV6 = (1ULL << 2),
|
||||||
|
BPF_F_ADJ_ROOM_ENCAP_L4_GRE = (1ULL << 3),
|
||||||
|
BPF_F_ADJ_ROOM_ENCAP_L4_UDP = (1ULL << 4),
|
||||||
|
};
|
||||||
|
|
||||||
#define BPF_ADJ_ROOM_ENCAP_L2_MASK 0xff
|
enum {
|
||||||
#define BPF_ADJ_ROOM_ENCAP_L2_SHIFT 56
|
BPF_ADJ_ROOM_ENCAP_L2_MASK = 0xff,
|
||||||
|
BPF_ADJ_ROOM_ENCAP_L2_SHIFT = 56,
|
||||||
|
};
|
||||||
|
|
||||||
#define BPF_F_ADJ_ROOM_ENCAP_L3_IPV4 (1ULL << 1)
|
|
||||||
#define BPF_F_ADJ_ROOM_ENCAP_L3_IPV6 (1ULL << 2)
|
|
||||||
#define BPF_F_ADJ_ROOM_ENCAP_L4_GRE (1ULL << 3)
|
|
||||||
#define BPF_F_ADJ_ROOM_ENCAP_L4_UDP (1ULL << 4)
|
|
||||||
#define BPF_F_ADJ_ROOM_ENCAP_L2(len) (((__u64)len & \
|
#define BPF_F_ADJ_ROOM_ENCAP_L2(len) (((__u64)len & \
|
||||||
BPF_ADJ_ROOM_ENCAP_L2_MASK) \
|
BPF_ADJ_ROOM_ENCAP_L2_MASK) \
|
||||||
<< BPF_ADJ_ROOM_ENCAP_L2_SHIFT)
|
<< BPF_ADJ_ROOM_ENCAP_L2_SHIFT)
|
||||||
|
|
||||||
/* BPF_FUNC_sysctl_get_name flags. */
|
/* BPF_FUNC_sysctl_get_name flags. */
|
||||||
#define BPF_F_SYSCTL_BASE_NAME (1ULL << 0)
|
enum {
|
||||||
|
BPF_F_SYSCTL_BASE_NAME = (1ULL << 0),
|
||||||
|
};
|
||||||
|
|
||||||
/* BPF_FUNC_sk_storage_get flags */
|
/* BPF_FUNC_sk_storage_get flags */
|
||||||
#define BPF_SK_STORAGE_GET_F_CREATE (1ULL << 0)
|
enum {
|
||||||
|
BPF_SK_STORAGE_GET_F_CREATE = (1ULL << 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
/* BPF_FUNC_read_branch_records flags. */
|
||||||
|
enum {
|
||||||
|
BPF_F_GET_BRANCH_RECORDS_SIZE = (1ULL << 0),
|
||||||
|
};
|
||||||
|
|
||||||
/* Mode for BPF_FUNC_skb_adjust_room helper. */
|
/* Mode for BPF_FUNC_skb_adjust_room helper. */
|
||||||
enum bpf_adj_room_mode {
|
enum bpf_adj_room_mode {
|
||||||
@@ -3081,6 +3325,7 @@ struct __sk_buff {
|
|||||||
__u32 wire_len;
|
__u32 wire_len;
|
||||||
__u32 gso_segs;
|
__u32 gso_segs;
|
||||||
__bpf_md_ptr(struct bpf_sock *, sk);
|
__bpf_md_ptr(struct bpf_sock *, sk);
|
||||||
|
__u32 gso_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bpf_tunnel_key {
|
struct bpf_tunnel_key {
|
||||||
@@ -3339,7 +3584,7 @@ struct bpf_map_info {
|
|||||||
__u32 map_flags;
|
__u32 map_flags;
|
||||||
char name[BPF_OBJ_NAME_LEN];
|
char name[BPF_OBJ_NAME_LEN];
|
||||||
__u32 ifindex;
|
__u32 ifindex;
|
||||||
__u32 :32;
|
__u32 btf_vmlinux_value_type_id;
|
||||||
__u64 netns_dev;
|
__u64 netns_dev;
|
||||||
__u64 netns_ino;
|
__u64 netns_ino;
|
||||||
__u32 btf_id;
|
__u32 btf_id;
|
||||||
@@ -3433,13 +3678,14 @@ struct bpf_sock_ops {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Definitions for bpf_sock_ops_cb_flags */
|
/* Definitions for bpf_sock_ops_cb_flags */
|
||||||
#define BPF_SOCK_OPS_RTO_CB_FLAG (1<<0)
|
enum {
|
||||||
#define BPF_SOCK_OPS_RETRANS_CB_FLAG (1<<1)
|
BPF_SOCK_OPS_RTO_CB_FLAG = (1<<0),
|
||||||
#define BPF_SOCK_OPS_STATE_CB_FLAG (1<<2)
|
BPF_SOCK_OPS_RETRANS_CB_FLAG = (1<<1),
|
||||||
#define BPF_SOCK_OPS_RTT_CB_FLAG (1<<3)
|
BPF_SOCK_OPS_STATE_CB_FLAG = (1<<2),
|
||||||
#define BPF_SOCK_OPS_ALL_CB_FLAGS 0xF /* Mask of all currently
|
BPF_SOCK_OPS_RTT_CB_FLAG = (1<<3),
|
||||||
* supported cb flags
|
/* Mask of all currently supported cb flags */
|
||||||
*/
|
BPF_SOCK_OPS_ALL_CB_FLAGS = 0xF,
|
||||||
|
};
|
||||||
|
|
||||||
/* 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
|
||||||
@@ -3518,8 +3764,10 @@ enum {
|
|||||||
BPF_TCP_MAX_STATES /* Leave at the end! */
|
BPF_TCP_MAX_STATES /* Leave at the end! */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TCP_BPF_IW 1001 /* Set TCP initial congestion window */
|
enum {
|
||||||
#define TCP_BPF_SNDCWND_CLAMP 1002 /* Set sndcwnd_clamp */
|
TCP_BPF_IW = 1001, /* Set TCP initial congestion window */
|
||||||
|
TCP_BPF_SNDCWND_CLAMP = 1002, /* Set sndcwnd_clamp */
|
||||||
|
};
|
||||||
|
|
||||||
struct bpf_perf_event_value {
|
struct bpf_perf_event_value {
|
||||||
__u64 counter;
|
__u64 counter;
|
||||||
@@ -3527,12 +3775,16 @@ struct bpf_perf_event_value {
|
|||||||
__u64 running;
|
__u64 running;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BPF_DEVCG_ACC_MKNOD (1ULL << 0)
|
enum {
|
||||||
#define BPF_DEVCG_ACC_READ (1ULL << 1)
|
BPF_DEVCG_ACC_MKNOD = (1ULL << 0),
|
||||||
#define BPF_DEVCG_ACC_WRITE (1ULL << 2)
|
BPF_DEVCG_ACC_READ = (1ULL << 1),
|
||||||
|
BPF_DEVCG_ACC_WRITE = (1ULL << 2),
|
||||||
|
};
|
||||||
|
|
||||||
#define BPF_DEVCG_DEV_BLOCK (1ULL << 0)
|
enum {
|
||||||
#define BPF_DEVCG_DEV_CHAR (1ULL << 1)
|
BPF_DEVCG_DEV_BLOCK = (1ULL << 0),
|
||||||
|
BPF_DEVCG_DEV_CHAR = (1ULL << 1),
|
||||||
|
};
|
||||||
|
|
||||||
struct bpf_cgroup_dev_ctx {
|
struct bpf_cgroup_dev_ctx {
|
||||||
/* access_type encoded as (BPF_DEVCG_ACC_* << 16) | BPF_DEVCG_DEV_* */
|
/* access_type encoded as (BPF_DEVCG_ACC_* << 16) | BPF_DEVCG_DEV_* */
|
||||||
@@ -3548,8 +3800,10 @@ struct bpf_raw_tracepoint_args {
|
|||||||
/* DIRECT: Skip the FIB rules and go to FIB table associated with device
|
/* DIRECT: Skip the FIB rules and go to FIB table associated with device
|
||||||
* OUTPUT: Do lookup from egress perspective; default is ingress
|
* OUTPUT: Do lookup from egress perspective; default is ingress
|
||||||
*/
|
*/
|
||||||
#define BPF_FIB_LOOKUP_DIRECT (1U << 0)
|
enum {
|
||||||
#define BPF_FIB_LOOKUP_OUTPUT (1U << 1)
|
BPF_FIB_LOOKUP_DIRECT = (1U << 0),
|
||||||
|
BPF_FIB_LOOKUP_OUTPUT = (1U << 1),
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
BPF_FIB_LKUP_RET_SUCCESS, /* lookup successful */
|
BPF_FIB_LKUP_RET_SUCCESS, /* lookup successful */
|
||||||
@@ -3621,9 +3875,11 @@ enum bpf_task_fd_type {
|
|||||||
BPF_FD_TYPE_URETPROBE, /* filename + offset */
|
BPF_FD_TYPE_URETPROBE, /* filename + offset */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG (1U << 0)
|
enum {
|
||||||
#define BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL (1U << 1)
|
BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG = (1U << 0),
|
||||||
#define BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP (1U << 2)
|
BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL = (1U << 1),
|
||||||
|
BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP = (1U << 2),
|
||||||
|
};
|
||||||
|
|
||||||
struct bpf_flow_keys {
|
struct bpf_flow_keys {
|
||||||
__u16 nhoff;
|
__u16 nhoff;
|
||||||
@@ -3689,4 +3945,8 @@ struct bpf_sockopt {
|
|||||||
__s32 retval;
|
__s32 retval;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct bpf_pidns_info {
|
||||||
|
__u32 pid;
|
||||||
|
__u32 tgid;
|
||||||
|
};
|
||||||
#endif /* _UAPI__LINUX_BPF_H__ */
|
#endif /* _UAPI__LINUX_BPF_H__ */
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ struct btf_header {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Max # of type identifier */
|
/* Max # of type identifier */
|
||||||
#define BTF_MAX_TYPE 0x0000ffff
|
#define BTF_MAX_TYPE 0x000fffff
|
||||||
/* Max offset into the string section */
|
/* Max offset into the string section */
|
||||||
#define BTF_MAX_NAME_OFFSET 0x0000ffff
|
#define BTF_MAX_NAME_OFFSET 0x00ffffff
|
||||||
/* Max # of struct/union/enum members or func args */
|
/* Max # of struct/union/enum members or func args */
|
||||||
#define BTF_MAX_VLEN 0xffff
|
#define BTF_MAX_VLEN 0xffff
|
||||||
|
|
||||||
@@ -142,7 +142,14 @@ struct btf_param {
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
BTF_VAR_STATIC = 0,
|
BTF_VAR_STATIC = 0,
|
||||||
BTF_VAR_GLOBAL_ALLOCATED,
|
BTF_VAR_GLOBAL_ALLOCATED = 1,
|
||||||
|
BTF_VAR_GLOBAL_EXTERN = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum btf_func_linkage {
|
||||||
|
BTF_FUNC_STATIC = 0,
|
||||||
|
BTF_FUNC_GLOBAL = 1,
|
||||||
|
BTF_FUNC_EXTERN = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* BTF_KIND_VAR is followed by a single "struct btf_var" to describe
|
/* BTF_KIND_VAR is followed by a single "struct btf_var" to describe
|
||||||
|
|||||||
@@ -169,6 +169,7 @@ enum {
|
|||||||
IFLA_MAX_MTU,
|
IFLA_MAX_MTU,
|
||||||
IFLA_PROP_LIST,
|
IFLA_PROP_LIST,
|
||||||
IFLA_ALT_IFNAME, /* Alternative ifname */
|
IFLA_ALT_IFNAME, /* Alternative ifname */
|
||||||
|
IFLA_PERM_ADDRESS,
|
||||||
__IFLA_MAX
|
__IFLA_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -462,6 +463,7 @@ enum {
|
|||||||
IFLA_MACSEC_REPLAY_PROTECT,
|
IFLA_MACSEC_REPLAY_PROTECT,
|
||||||
IFLA_MACSEC_VALIDATION,
|
IFLA_MACSEC_VALIDATION,
|
||||||
IFLA_MACSEC_PAD,
|
IFLA_MACSEC_PAD,
|
||||||
|
IFLA_MACSEC_OFFLOAD,
|
||||||
__IFLA_MACSEC_MAX,
|
__IFLA_MACSEC_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -485,6 +487,14 @@ enum macsec_validation_type {
|
|||||||
MACSEC_VALIDATE_MAX = __MACSEC_VALIDATE_END - 1,
|
MACSEC_VALIDATE_MAX = __MACSEC_VALIDATE_END - 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum macsec_offload {
|
||||||
|
MACSEC_OFFLOAD_OFF = 0,
|
||||||
|
MACSEC_OFFLOAD_PHY = 1,
|
||||||
|
MACSEC_OFFLOAD_MAC = 2,
|
||||||
|
__MACSEC_OFFLOAD_END,
|
||||||
|
MACSEC_OFFLOAD_MAX = __MACSEC_OFFLOAD_END - 1,
|
||||||
|
};
|
||||||
|
|
||||||
/* IPVLAN section */
|
/* IPVLAN section */
|
||||||
enum {
|
enum {
|
||||||
IFLA_IPVLAN_UNSPEC,
|
IFLA_IPVLAN_UNSPEC,
|
||||||
@@ -952,11 +962,12 @@ enum {
|
|||||||
#define XDP_FLAGS_SKB_MODE (1U << 1)
|
#define XDP_FLAGS_SKB_MODE (1U << 1)
|
||||||
#define XDP_FLAGS_DRV_MODE (1U << 2)
|
#define XDP_FLAGS_DRV_MODE (1U << 2)
|
||||||
#define XDP_FLAGS_HW_MODE (1U << 3)
|
#define XDP_FLAGS_HW_MODE (1U << 3)
|
||||||
|
#define XDP_FLAGS_REPLACE (1U << 4)
|
||||||
#define XDP_FLAGS_MODES (XDP_FLAGS_SKB_MODE | \
|
#define XDP_FLAGS_MODES (XDP_FLAGS_SKB_MODE | \
|
||||||
XDP_FLAGS_DRV_MODE | \
|
XDP_FLAGS_DRV_MODE | \
|
||||||
XDP_FLAGS_HW_MODE)
|
XDP_FLAGS_HW_MODE)
|
||||||
#define XDP_FLAGS_MASK (XDP_FLAGS_UPDATE_IF_NOEXIST | \
|
#define XDP_FLAGS_MASK (XDP_FLAGS_UPDATE_IF_NOEXIST | \
|
||||||
XDP_FLAGS_MODES)
|
XDP_FLAGS_MODES | XDP_FLAGS_REPLACE)
|
||||||
|
|
||||||
/* These are stored into IFLA_XDP_ATTACHED on dump. */
|
/* These are stored into IFLA_XDP_ATTACHED on dump. */
|
||||||
enum {
|
enum {
|
||||||
@@ -976,6 +987,7 @@ enum {
|
|||||||
IFLA_XDP_DRV_PROG_ID,
|
IFLA_XDP_DRV_PROG_ID,
|
||||||
IFLA_XDP_SKB_PROG_ID,
|
IFLA_XDP_SKB_PROG_ID,
|
||||||
IFLA_XDP_HW_PROG_ID,
|
IFLA_XDP_HW_PROG_ID,
|
||||||
|
IFLA_XDP_EXPECTED_FD,
|
||||||
__IFLA_XDP_MAX,
|
__IFLA_XDP_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ PATH_MAP=( \
|
|||||||
[tools/include/tools/libc_compat.h]=include/tools/libc_compat.h \
|
[tools/include/tools/libc_compat.h]=include/tools/libc_compat.h \
|
||||||
)
|
)
|
||||||
|
|
||||||
LIBBPF_PATHS="${!PATH_MAP[@]}"
|
LIBBPF_PATHS="${!PATH_MAP[@]} :^tools/lib/bpf/Makefile :^tools/lib/bpf/Build :^tools/lib/bpf/.gitignore"
|
||||||
LIBBPF_VIEW_PATHS="${PATH_MAP[@]}"
|
LIBBPF_VIEW_PATHS="${PATH_MAP[@]}"
|
||||||
LIBBPF_VIEW_EXCLUDE_REGEX='^src/(Makefile|Build|test_libbpf\.c|bpf_helper_defs\.h|\.gitignore)$'
|
LIBBPF_VIEW_EXCLUDE_REGEX='^src/(Makefile|Build|test_libbpf\.c|bpf_helper_defs\.h|\.gitignore)$'
|
||||||
|
|
||||||
@@ -79,9 +79,10 @@ commit_desc()
|
|||||||
# The idea is that this single-line signature is good enough to make final
|
# The idea is that this single-line signature is good enough to make final
|
||||||
# decision about whether two commits are the same, across different repos.
|
# decision about whether two commits are the same, across different repos.
|
||||||
# $1 - commit ref
|
# $1 - commit ref
|
||||||
|
# $2 - paths filter
|
||||||
commit_signature()
|
commit_signature()
|
||||||
{
|
{
|
||||||
git log -n1 --pretty='("%s")|%aI|%b' --shortstat $1 | tr '\n' '|'
|
git show --pretty='("%s")|%aI|%b' --shortstat $1 -- ${2-.} | tr '\n' '|'
|
||||||
}
|
}
|
||||||
|
|
||||||
# Validate there are no non-empty merges (we can't handle them)
|
# Validate there are no non-empty merges (we can't handle them)
|
||||||
@@ -133,7 +134,7 @@ cherry_pick_commits()
|
|||||||
new_commits=$(git rev-list --no-merges --topo-order --reverse ${baseline_tag}..${tip_tag} ${LIBBPF_PATHS[@]})
|
new_commits=$(git rev-list --no-merges --topo-order --reverse ${baseline_tag}..${tip_tag} ${LIBBPF_PATHS[@]})
|
||||||
for new_commit in ${new_commits}; do
|
for new_commit in ${new_commits}; do
|
||||||
desc="$(commit_desc ${new_commit})"
|
desc="$(commit_desc ${new_commit})"
|
||||||
signature="$(commit_signature ${new_commit})"
|
signature="$(commit_signature ${new_commit} "${LIBBPF_PATHS[@]}")"
|
||||||
synced_cnt=$(grep -F "${signature}" ${TMP_DIR}/libbpf_commits.txt | wc -l)
|
synced_cnt=$(grep -F "${signature}" ${TMP_DIR}/libbpf_commits.txt | wc -l)
|
||||||
manual_check=0
|
manual_check=0
|
||||||
if ((${synced_cnt} > 0)); then
|
if ((${synced_cnt} > 0)); then
|
||||||
|
|||||||
15
src/Makefile
15
src/Makefile
@@ -21,7 +21,7 @@ CFLAGS ?= -g -O2 -Werror -Wall
|
|||||||
ALL_CFLAGS += $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
|
ALL_CFLAGS += $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
|
||||||
ALL_LDFLAGS += $(LDFLAGS)
|
ALL_LDFLAGS += $(LDFLAGS)
|
||||||
ifdef NO_PKG_CONFIG
|
ifdef NO_PKG_CONFIG
|
||||||
ALL_LDFLAGS += -lelf
|
ALL_LDFLAGS += -lelf -lz
|
||||||
else
|
else
|
||||||
PKG_CONFIG ?= pkg-config
|
PKG_CONFIG ?= pkg-config
|
||||||
ALL_CFLAGS += $(shell $(PKG_CONFIG) --cflags libelf)
|
ALL_CFLAGS += $(shell $(PKG_CONFIG) --cflags libelf)
|
||||||
@@ -47,7 +47,7 @@ endif
|
|||||||
|
|
||||||
HEADERS := bpf.h libbpf.h btf.h xsk.h libbpf_util.h \
|
HEADERS := bpf.h libbpf.h btf.h xsk.h libbpf_util.h \
|
||||||
bpf_helpers.h bpf_helper_defs.h bpf_tracing.h \
|
bpf_helpers.h bpf_helper_defs.h bpf_tracing.h \
|
||||||
bpf_endian.h bpf_core_read.h
|
bpf_endian.h bpf_core_read.h libbpf_common.h
|
||||||
UAPI_HEADERS := $(addprefix $(TOPDIR)/include/uapi/linux/,\
|
UAPI_HEADERS := $(addprefix $(TOPDIR)/include/uapi/linux/,\
|
||||||
bpf.h bpf_common.h btf.h)
|
bpf.h bpf_common.h btf.h)
|
||||||
|
|
||||||
@@ -68,6 +68,8 @@ LIBDIR ?= $(PREFIX)/$(LIBSUBDIR)
|
|||||||
INCLUDEDIR ?= $(PREFIX)/include
|
INCLUDEDIR ?= $(PREFIX)/include
|
||||||
UAPIDIR ?= $(PREFIX)/include
|
UAPIDIR ?= $(PREFIX)/include
|
||||||
|
|
||||||
|
TAGS_PROG := $(if $(shell which etags 2>/dev/null),etags,ctags)
|
||||||
|
|
||||||
all: $(STATIC_LIBS) $(SHARED_LIBS) $(PC_FILE)
|
all: $(STATIC_LIBS) $(SHARED_LIBS) $(PC_FILE)
|
||||||
|
|
||||||
$(OBJDIR)/libbpf.a: $(STATIC_OBJS)
|
$(OBJDIR)/libbpf.a: $(STATIC_OBJS)
|
||||||
@@ -133,3 +135,12 @@ install_pkgconfig: $(PC_FILE)
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf *.o *.a *.so *.so.* *.pc $(SHARED_OBJDIR) $(STATIC_OBJDIR)
|
rm -rf *.o *.a *.so *.so.* *.pc $(SHARED_OBJDIR) $(STATIC_OBJDIR)
|
||||||
|
|
||||||
|
.PHONY: cscope tags
|
||||||
|
cscope:
|
||||||
|
ls *.c *.h > cscope.files
|
||||||
|
cscope -b -q -f cscope.out
|
||||||
|
|
||||||
|
tags:
|
||||||
|
rm -f TAGS tags
|
||||||
|
ls *.c *.h | xargs $(TAGS_PROG) -a
|
||||||
|
|||||||
124
src/bpf.c
124
src/bpf.c
@@ -32,6 +32,9 @@
|
|||||||
#include "libbpf.h"
|
#include "libbpf.h"
|
||||||
#include "libbpf_internal.h"
|
#include "libbpf_internal.h"
|
||||||
|
|
||||||
|
/* make sure libbpf doesn't use kernel-only integer typedefs */
|
||||||
|
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When building perf, unistd.h is overridden. __NR_bpf is
|
* When building perf, unistd.h is overridden. __NR_bpf is
|
||||||
* required to be defined explicitly.
|
* required to be defined explicitly.
|
||||||
@@ -95,7 +98,11 @@ int bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr)
|
|||||||
attr.btf_key_type_id = create_attr->btf_key_type_id;
|
attr.btf_key_type_id = create_attr->btf_key_type_id;
|
||||||
attr.btf_value_type_id = create_attr->btf_value_type_id;
|
attr.btf_value_type_id = create_attr->btf_value_type_id;
|
||||||
attr.map_ifindex = create_attr->map_ifindex;
|
attr.map_ifindex = create_attr->map_ifindex;
|
||||||
attr.inner_map_fd = create_attr->inner_map_fd;
|
if (attr.map_type == BPF_MAP_TYPE_STRUCT_OPS)
|
||||||
|
attr.btf_vmlinux_value_type_id =
|
||||||
|
create_attr->btf_vmlinux_value_type_id;
|
||||||
|
else
|
||||||
|
attr.inner_map_fd = create_attr->inner_map_fd;
|
||||||
|
|
||||||
return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
|
return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
|
||||||
}
|
}
|
||||||
@@ -228,7 +235,11 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
|
|||||||
memset(&attr, 0, sizeof(attr));
|
memset(&attr, 0, sizeof(attr));
|
||||||
attr.prog_type = load_attr->prog_type;
|
attr.prog_type = load_attr->prog_type;
|
||||||
attr.expected_attach_type = load_attr->expected_attach_type;
|
attr.expected_attach_type = load_attr->expected_attach_type;
|
||||||
if (attr.prog_type == BPF_PROG_TYPE_TRACING) {
|
if (attr.prog_type == BPF_PROG_TYPE_STRUCT_OPS ||
|
||||||
|
attr.prog_type == BPF_PROG_TYPE_LSM) {
|
||||||
|
attr.attach_btf_id = load_attr->attach_btf_id;
|
||||||
|
} else if (attr.prog_type == BPF_PROG_TYPE_TRACING ||
|
||||||
|
attr.prog_type == BPF_PROG_TYPE_EXT) {
|
||||||
attr.attach_btf_id = load_attr->attach_btf_id;
|
attr.attach_btf_id = load_attr->attach_btf_id;
|
||||||
attr.attach_prog_fd = load_attr->attach_prog_fd;
|
attr.attach_prog_fd = load_attr->attach_prog_fd;
|
||||||
} else {
|
} else {
|
||||||
@@ -443,6 +454,64 @@ int bpf_map_freeze(int fd)
|
|||||||
return sys_bpf(BPF_MAP_FREEZE, &attr, sizeof(attr));
|
return sys_bpf(BPF_MAP_FREEZE, &attr, sizeof(attr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int bpf_map_batch_common(int cmd, int fd, void *in_batch,
|
||||||
|
void *out_batch, void *keys, void *values,
|
||||||
|
__u32 *count,
|
||||||
|
const struct bpf_map_batch_opts *opts)
|
||||||
|
{
|
||||||
|
union bpf_attr attr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!OPTS_VALID(opts, bpf_map_batch_opts))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
memset(&attr, 0, sizeof(attr));
|
||||||
|
attr.batch.map_fd = fd;
|
||||||
|
attr.batch.in_batch = ptr_to_u64(in_batch);
|
||||||
|
attr.batch.out_batch = ptr_to_u64(out_batch);
|
||||||
|
attr.batch.keys = ptr_to_u64(keys);
|
||||||
|
attr.batch.values = ptr_to_u64(values);
|
||||||
|
attr.batch.count = *count;
|
||||||
|
attr.batch.elem_flags = OPTS_GET(opts, elem_flags, 0);
|
||||||
|
attr.batch.flags = OPTS_GET(opts, flags, 0);
|
||||||
|
|
||||||
|
ret = sys_bpf(cmd, &attr, sizeof(attr));
|
||||||
|
*count = attr.batch.count;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bpf_map_delete_batch(int fd, void *keys, __u32 *count,
|
||||||
|
const struct bpf_map_batch_opts *opts)
|
||||||
|
{
|
||||||
|
return bpf_map_batch_common(BPF_MAP_DELETE_BATCH, fd, NULL,
|
||||||
|
NULL, keys, NULL, count, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bpf_map_lookup_batch(int fd, void *in_batch, void *out_batch, void *keys,
|
||||||
|
void *values, __u32 *count,
|
||||||
|
const struct bpf_map_batch_opts *opts)
|
||||||
|
{
|
||||||
|
return bpf_map_batch_common(BPF_MAP_LOOKUP_BATCH, fd, in_batch,
|
||||||
|
out_batch, keys, values, count, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bpf_map_lookup_and_delete_batch(int fd, void *in_batch, void *out_batch,
|
||||||
|
void *keys, void *values, __u32 *count,
|
||||||
|
const struct bpf_map_batch_opts *opts)
|
||||||
|
{
|
||||||
|
return bpf_map_batch_common(BPF_MAP_LOOKUP_AND_DELETE_BATCH,
|
||||||
|
fd, in_batch, out_batch, keys, values,
|
||||||
|
count, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bpf_map_update_batch(int fd, void *keys, void *values, __u32 *count,
|
||||||
|
const struct bpf_map_batch_opts *opts)
|
||||||
|
{
|
||||||
|
return bpf_map_batch_common(BPF_MAP_UPDATE_BATCH, fd, NULL, NULL,
|
||||||
|
keys, values, count, opts);
|
||||||
|
}
|
||||||
|
|
||||||
int bpf_obj_pin(int fd, const char *pathname)
|
int bpf_obj_pin(int fd, const char *pathname)
|
||||||
{
|
{
|
||||||
union bpf_attr attr;
|
union bpf_attr attr;
|
||||||
@@ -466,14 +535,29 @@ int bpf_obj_get(const char *pathname)
|
|||||||
|
|
||||||
int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type,
|
int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
DECLARE_LIBBPF_OPTS(bpf_prog_attach_opts, opts,
|
||||||
|
.flags = flags,
|
||||||
|
);
|
||||||
|
|
||||||
|
return bpf_prog_attach_xattr(prog_fd, target_fd, type, &opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bpf_prog_attach_xattr(int prog_fd, int target_fd,
|
||||||
|
enum bpf_attach_type type,
|
||||||
|
const struct bpf_prog_attach_opts *opts)
|
||||||
{
|
{
|
||||||
union bpf_attr attr;
|
union bpf_attr attr;
|
||||||
|
|
||||||
|
if (!OPTS_VALID(opts, bpf_prog_attach_opts))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
memset(&attr, 0, sizeof(attr));
|
memset(&attr, 0, sizeof(attr));
|
||||||
attr.target_fd = target_fd;
|
attr.target_fd = target_fd;
|
||||||
attr.attach_bpf_fd = prog_fd;
|
attr.attach_bpf_fd = prog_fd;
|
||||||
attr.attach_type = type;
|
attr.attach_type = type;
|
||||||
attr.attach_flags = flags;
|
attr.attach_flags = OPTS_GET(opts, flags, 0);
|
||||||
|
attr.replace_bpf_fd = OPTS_GET(opts, replace_prog_fd, 0);
|
||||||
|
|
||||||
return sys_bpf(BPF_PROG_ATTACH, &attr, sizeof(attr));
|
return sys_bpf(BPF_PROG_ATTACH, &attr, sizeof(attr));
|
||||||
}
|
}
|
||||||
@@ -501,6 +585,40 @@ int bpf_prog_detach2(int prog_fd, int target_fd, enum bpf_attach_type type)
|
|||||||
return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
|
return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bpf_link_create(int prog_fd, int target_fd,
|
||||||
|
enum bpf_attach_type attach_type,
|
||||||
|
const struct bpf_link_create_opts *opts)
|
||||||
|
{
|
||||||
|
union bpf_attr attr;
|
||||||
|
|
||||||
|
if (!OPTS_VALID(opts, bpf_link_create_opts))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
memset(&attr, 0, sizeof(attr));
|
||||||
|
attr.link_create.prog_fd = prog_fd;
|
||||||
|
attr.link_create.target_fd = target_fd;
|
||||||
|
attr.link_create.attach_type = attach_type;
|
||||||
|
|
||||||
|
return sys_bpf(BPF_LINK_CREATE, &attr, sizeof(attr));
|
||||||
|
}
|
||||||
|
|
||||||
|
int bpf_link_update(int link_fd, int new_prog_fd,
|
||||||
|
const struct bpf_link_update_opts *opts)
|
||||||
|
{
|
||||||
|
union bpf_attr attr;
|
||||||
|
|
||||||
|
if (!OPTS_VALID(opts, bpf_link_update_opts))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
memset(&attr, 0, sizeof(attr));
|
||||||
|
attr.link_update.link_fd = link_fd;
|
||||||
|
attr.link_update.new_prog_fd = new_prog_fd;
|
||||||
|
attr.link_update.flags = OPTS_GET(opts, flags, 0);
|
||||||
|
attr.link_update.old_prog_fd = OPTS_GET(opts, old_prog_fd, 0);
|
||||||
|
|
||||||
|
return sys_bpf(BPF_LINK_UPDATE, &attr, sizeof(attr));
|
||||||
|
}
|
||||||
|
|
||||||
int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
|
int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
|
||||||
__u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt)
|
__u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt)
|
||||||
{
|
{
|
||||||
|
|||||||
63
src/bpf.h
63
src/bpf.h
@@ -28,14 +28,12 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "libbpf_common.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef LIBBPF_API
|
|
||||||
#define LIBBPF_API __attribute__((visibility("default")))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct bpf_create_map_attr {
|
struct bpf_create_map_attr {
|
||||||
const char *name;
|
const char *name;
|
||||||
enum bpf_map_type map_type;
|
enum bpf_map_type map_type;
|
||||||
@@ -48,7 +46,10 @@ struct bpf_create_map_attr {
|
|||||||
__u32 btf_key_type_id;
|
__u32 btf_key_type_id;
|
||||||
__u32 btf_value_type_id;
|
__u32 btf_value_type_id;
|
||||||
__u32 map_ifindex;
|
__u32 map_ifindex;
|
||||||
__u32 inner_map_fd;
|
union {
|
||||||
|
__u32 inner_map_fd;
|
||||||
|
__u32 btf_vmlinux_value_type_id;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
LIBBPF_API int
|
LIBBPF_API int
|
||||||
@@ -126,14 +127,66 @@ LIBBPF_API int bpf_map_lookup_and_delete_elem(int fd, const void *key,
|
|||||||
LIBBPF_API int bpf_map_delete_elem(int fd, const void *key);
|
LIBBPF_API int bpf_map_delete_elem(int fd, const void *key);
|
||||||
LIBBPF_API int bpf_map_get_next_key(int fd, const void *key, void *next_key);
|
LIBBPF_API int bpf_map_get_next_key(int fd, const void *key, void *next_key);
|
||||||
LIBBPF_API int bpf_map_freeze(int fd);
|
LIBBPF_API int bpf_map_freeze(int fd);
|
||||||
|
|
||||||
|
struct bpf_map_batch_opts {
|
||||||
|
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||||
|
__u64 elem_flags;
|
||||||
|
__u64 flags;
|
||||||
|
};
|
||||||
|
#define bpf_map_batch_opts__last_field flags
|
||||||
|
|
||||||
|
LIBBPF_API int bpf_map_delete_batch(int fd, void *keys,
|
||||||
|
__u32 *count,
|
||||||
|
const struct bpf_map_batch_opts *opts);
|
||||||
|
LIBBPF_API int bpf_map_lookup_batch(int fd, void *in_batch, void *out_batch,
|
||||||
|
void *keys, void *values, __u32 *count,
|
||||||
|
const struct bpf_map_batch_opts *opts);
|
||||||
|
LIBBPF_API int bpf_map_lookup_and_delete_batch(int fd, void *in_batch,
|
||||||
|
void *out_batch, void *keys,
|
||||||
|
void *values, __u32 *count,
|
||||||
|
const struct bpf_map_batch_opts *opts);
|
||||||
|
LIBBPF_API int bpf_map_update_batch(int fd, void *keys, void *values,
|
||||||
|
__u32 *count,
|
||||||
|
const struct bpf_map_batch_opts *opts);
|
||||||
|
|
||||||
LIBBPF_API int bpf_obj_pin(int fd, const char *pathname);
|
LIBBPF_API int bpf_obj_pin(int fd, const char *pathname);
|
||||||
LIBBPF_API int bpf_obj_get(const char *pathname);
|
LIBBPF_API int bpf_obj_get(const char *pathname);
|
||||||
|
|
||||||
|
struct bpf_prog_attach_opts {
|
||||||
|
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||||
|
unsigned int flags;
|
||||||
|
int replace_prog_fd;
|
||||||
|
};
|
||||||
|
#define bpf_prog_attach_opts__last_field replace_prog_fd
|
||||||
|
|
||||||
LIBBPF_API int bpf_prog_attach(int prog_fd, int attachable_fd,
|
LIBBPF_API int bpf_prog_attach(int prog_fd, int attachable_fd,
|
||||||
enum bpf_attach_type type, unsigned int flags);
|
enum bpf_attach_type type, unsigned int flags);
|
||||||
|
LIBBPF_API int bpf_prog_attach_xattr(int prog_fd, int attachable_fd,
|
||||||
|
enum bpf_attach_type type,
|
||||||
|
const struct bpf_prog_attach_opts *opts);
|
||||||
LIBBPF_API int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type);
|
LIBBPF_API int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type);
|
||||||
LIBBPF_API int bpf_prog_detach2(int prog_fd, int attachable_fd,
|
LIBBPF_API int bpf_prog_detach2(int prog_fd, int attachable_fd,
|
||||||
enum bpf_attach_type type);
|
enum bpf_attach_type type);
|
||||||
|
|
||||||
|
struct bpf_link_create_opts {
|
||||||
|
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||||
|
};
|
||||||
|
#define bpf_link_create_opts__last_field sz
|
||||||
|
|
||||||
|
LIBBPF_API int bpf_link_create(int prog_fd, int target_fd,
|
||||||
|
enum bpf_attach_type attach_type,
|
||||||
|
const struct bpf_link_create_opts *opts);
|
||||||
|
|
||||||
|
struct bpf_link_update_opts {
|
||||||
|
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||||
|
__u32 flags; /* extra flags */
|
||||||
|
__u32 old_prog_fd; /* expected old program FD */
|
||||||
|
};
|
||||||
|
#define bpf_link_update_opts__last_field old_prog_fd
|
||||||
|
|
||||||
|
LIBBPF_API int bpf_link_update(int link_fd, int new_prog_fd,
|
||||||
|
const struct bpf_link_update_opts *opts);
|
||||||
|
|
||||||
struct bpf_prog_test_run_attr {
|
struct bpf_prog_test_run_attr {
|
||||||
int prog_fd;
|
int prog_fd;
|
||||||
int repeat;
|
int repeat;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
struct bpf_fib_lookup;
|
struct bpf_fib_lookup;
|
||||||
struct bpf_perf_event_data;
|
struct bpf_perf_event_data;
|
||||||
struct bpf_perf_event_value;
|
struct bpf_perf_event_value;
|
||||||
|
struct bpf_pidns_info;
|
||||||
struct bpf_sock;
|
struct bpf_sock;
|
||||||
struct bpf_sock_addr;
|
struct bpf_sock_addr;
|
||||||
struct bpf_sock_ops;
|
struct bpf_sock_ops;
|
||||||
@@ -576,9 +577,9 @@ static __u64 (*bpf_perf_event_read)(void *map, __u64 flags) = (void *) 22;
|
|||||||
* supports redirection to the egress interface, and accepts no
|
* supports redirection to the egress interface, and accepts no
|
||||||
* flag at all.
|
* flag at all.
|
||||||
*
|
*
|
||||||
* The same effect can be attained with the more generic
|
* The same effect can also be attained with the more generic
|
||||||
* **bpf_redirect_map**\ (), which requires specific maps to be
|
* **bpf_redirect_map**\ (), which uses a BPF map to store the
|
||||||
* used but offers better performance.
|
* redirect target instead of providing it directly to the helper.
|
||||||
*
|
*
|
||||||
* Returns
|
* Returns
|
||||||
* For XDP, the helper returns **XDP_REDIRECT** on success or
|
* For XDP, the helper returns **XDP_REDIRECT** on success or
|
||||||
@@ -1242,14 +1243,12 @@ static int (*bpf_skb_adjust_room)(struct __sk_buff *skb, __s32 len_diff, __u32 m
|
|||||||
* the caller. Any higher bits in the *flags* argument must be
|
* the caller. Any higher bits in the *flags* argument must be
|
||||||
* unset.
|
* unset.
|
||||||
*
|
*
|
||||||
* When used to redirect packets to net devices, this helper
|
* See also bpf_redirect(), which only supports redirecting to an
|
||||||
* provides a high performance increase over **bpf_redirect**\ ().
|
* ifindex, but doesn't require a map to do so.
|
||||||
* This is due to various implementation details of the underlying
|
|
||||||
* mechanisms, one of which is the fact that **bpf_redirect_map**\
|
|
||||||
* () tries to send packet as a "bulk" to the device.
|
|
||||||
*
|
*
|
||||||
* Returns
|
* Returns
|
||||||
* **XDP_REDIRECT** on success, or **XDP_ABORTED** on error.
|
* **XDP_REDIRECT** on success, or the value of the two lower bits
|
||||||
|
* of the **flags* argument on error.
|
||||||
*/
|
*/
|
||||||
static int (*bpf_redirect_map)(void *map, __u32 key, __u64 flags) = (void *) 51;
|
static int (*bpf_redirect_map)(void *map, __u32 key, __u64 flags) = (void *) 51;
|
||||||
|
|
||||||
@@ -2600,7 +2599,8 @@ static int (*bpf_sk_storage_delete)(void *map, struct bpf_sock *sk) = (void *) 1
|
|||||||
/*
|
/*
|
||||||
* bpf_send_signal
|
* bpf_send_signal
|
||||||
*
|
*
|
||||||
* Send signal *sig* to the current task.
|
* Send signal *sig* to the process of the current task.
|
||||||
|
* The signal may be delivered to any of this process's threads.
|
||||||
*
|
*
|
||||||
* Returns
|
* Returns
|
||||||
* 0 on success or successfully queued.
|
* 0 on success or successfully queued.
|
||||||
@@ -2756,4 +2756,175 @@ static int (*bpf_probe_read_user_str)(void *dst, __u32 size, const void *unsafe_
|
|||||||
*/
|
*/
|
||||||
static int (*bpf_probe_read_kernel_str)(void *dst, __u32 size, const void *unsafe_ptr) = (void *) 115;
|
static int (*bpf_probe_read_kernel_str)(void *dst, __u32 size, const void *unsafe_ptr) = (void *) 115;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bpf_tcp_send_ack
|
||||||
|
*
|
||||||
|
* Send out a tcp-ack. *tp* is the in-kernel struct tcp_sock.
|
||||||
|
* *rcv_nxt* is the ack_seq to be sent out.
|
||||||
|
*
|
||||||
|
* Returns
|
||||||
|
* 0 on success, or a negative error in case of failure.
|
||||||
|
*/
|
||||||
|
static int (*bpf_tcp_send_ack)(void *tp, __u32 rcv_nxt) = (void *) 116;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bpf_send_signal_thread
|
||||||
|
*
|
||||||
|
* Send signal *sig* to the thread corresponding to the current task.
|
||||||
|
*
|
||||||
|
* Returns
|
||||||
|
* 0 on success or successfully queued.
|
||||||
|
*
|
||||||
|
* **-EBUSY** if work queue under nmi is full.
|
||||||
|
*
|
||||||
|
* **-EINVAL** if *sig* is invalid.
|
||||||
|
*
|
||||||
|
* **-EPERM** if no permission to send the *sig*.
|
||||||
|
*
|
||||||
|
* **-EAGAIN** if bpf program can try again.
|
||||||
|
*/
|
||||||
|
static int (*bpf_send_signal_thread)(__u32 sig) = (void *) 117;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bpf_jiffies64
|
||||||
|
*
|
||||||
|
* Obtain the 64bit jiffies
|
||||||
|
*
|
||||||
|
* Returns
|
||||||
|
* The 64 bit jiffies
|
||||||
|
*/
|
||||||
|
static __u64 (*bpf_jiffies64)(void) = (void *) 118;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bpf_read_branch_records
|
||||||
|
*
|
||||||
|
* For an eBPF program attached to a perf event, retrieve the
|
||||||
|
* branch records (struct perf_branch_entry) associated to *ctx*
|
||||||
|
* and store it in the buffer pointed by *buf* up to size
|
||||||
|
* *size* bytes.
|
||||||
|
*
|
||||||
|
* Returns
|
||||||
|
* On success, number of bytes written to *buf*. On error, a
|
||||||
|
* negative value.
|
||||||
|
*
|
||||||
|
* The *flags* can be set to **BPF_F_GET_BRANCH_RECORDS_SIZE** to
|
||||||
|
* instead return the number of bytes required to store all the
|
||||||
|
* branch entries. If this flag is set, *buf* may be NULL.
|
||||||
|
*
|
||||||
|
* **-EINVAL** if arguments invalid or **size** not a multiple
|
||||||
|
* of sizeof(struct perf_branch_entry).
|
||||||
|
*
|
||||||
|
* **-ENOENT** if architecture does not support branch records.
|
||||||
|
*/
|
||||||
|
static int (*bpf_read_branch_records)(struct bpf_perf_event_data *ctx, void *buf, __u32 size, __u64 flags) = (void *) 119;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bpf_get_ns_current_pid_tgid
|
||||||
|
*
|
||||||
|
* Returns 0 on success, values for *pid* and *tgid* as seen from the current
|
||||||
|
* *namespace* will be returned in *nsdata*.
|
||||||
|
*
|
||||||
|
* On failure, the returned value is one of the following:
|
||||||
|
*
|
||||||
|
* **-EINVAL** if dev and inum supplied don't match dev_t and inode number
|
||||||
|
* with nsfs of current task, or if dev conversion to dev_t lost high bits.
|
||||||
|
*
|
||||||
|
* **-ENOENT** if pidns does not exists for the current task.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int (*bpf_get_ns_current_pid_tgid)(__u64 dev, __u64 ino, struct bpf_pidns_info *nsdata, __u32 size) = (void *) 120;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bpf_xdp_output
|
||||||
|
*
|
||||||
|
* Write raw *data* blob into a special BPF perf event held by
|
||||||
|
* *map* of type **BPF_MAP_TYPE_PERF_EVENT_ARRAY**. This perf
|
||||||
|
* event must have the following attributes: **PERF_SAMPLE_RAW**
|
||||||
|
* as **sample_type**, **PERF_TYPE_SOFTWARE** as **type**, and
|
||||||
|
* **PERF_COUNT_SW_BPF_OUTPUT** as **config**.
|
||||||
|
*
|
||||||
|
* The *flags* are used to indicate the index in *map* for which
|
||||||
|
* the value must be put, masked with **BPF_F_INDEX_MASK**.
|
||||||
|
* Alternatively, *flags* can be set to **BPF_F_CURRENT_CPU**
|
||||||
|
* to indicate that the index of the current CPU core should be
|
||||||
|
* used.
|
||||||
|
*
|
||||||
|
* The value to write, of *size*, is passed through eBPF stack and
|
||||||
|
* pointed by *data*.
|
||||||
|
*
|
||||||
|
* *ctx* is a pointer to in-kernel struct xdp_buff.
|
||||||
|
*
|
||||||
|
* This helper is similar to **bpf_perf_eventoutput**\ () but
|
||||||
|
* restricted to raw_tracepoint bpf programs.
|
||||||
|
*
|
||||||
|
* Returns
|
||||||
|
* 0 on success, or a negative error in case of failure.
|
||||||
|
*/
|
||||||
|
static int (*bpf_xdp_output)(void *ctx, void *map, __u64 flags, void *data, __u64 size) = (void *) 121;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bpf_get_netns_cookie
|
||||||
|
*
|
||||||
|
* Retrieve the cookie (generated by the kernel) of the network
|
||||||
|
* namespace the input *ctx* is associated with. The network
|
||||||
|
* namespace cookie remains stable for its lifetime and provides
|
||||||
|
* a global identifier that can be assumed unique. If *ctx* is
|
||||||
|
* NULL, then the helper returns the cookie for the initial
|
||||||
|
* network namespace. The cookie itself is very similar to that
|
||||||
|
* of bpf_get_socket_cookie() helper, but for network namespaces
|
||||||
|
* instead of sockets.
|
||||||
|
*
|
||||||
|
* Returns
|
||||||
|
* A 8-byte long opaque number.
|
||||||
|
*/
|
||||||
|
static __u64 (*bpf_get_netns_cookie)(void *ctx) = (void *) 122;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bpf_get_current_ancestor_cgroup_id
|
||||||
|
*
|
||||||
|
* Return id of cgroup v2 that is ancestor of the cgroup associated
|
||||||
|
* with the current task at the *ancestor_level*. The root cgroup
|
||||||
|
* is at *ancestor_level* zero and each step down the hierarchy
|
||||||
|
* increments the level. If *ancestor_level* == level of cgroup
|
||||||
|
* associated with the current task, then return value will be the
|
||||||
|
* same as that of **bpf_get_current_cgroup_id**\ ().
|
||||||
|
*
|
||||||
|
* The helper is useful to implement policies based on cgroups
|
||||||
|
* that are upper in hierarchy than immediate cgroup associated
|
||||||
|
* with the current task.
|
||||||
|
*
|
||||||
|
* The format of returned id and helper limitations are same as in
|
||||||
|
* **bpf_get_current_cgroup_id**\ ().
|
||||||
|
*
|
||||||
|
* Returns
|
||||||
|
* The id is returned or 0 in case the id could not be retrieved.
|
||||||
|
*/
|
||||||
|
static __u64 (*bpf_get_current_ancestor_cgroup_id)(int ancestor_level) = (void *) 123;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bpf_sk_assign
|
||||||
|
*
|
||||||
|
* Assign the *sk* to the *skb*. When combined with appropriate
|
||||||
|
* routing configuration to receive the packet towards the socket,
|
||||||
|
* will cause *skb* to be delivered to the specified socket.
|
||||||
|
* Subsequent redirection of *skb* via **bpf_redirect**\ (),
|
||||||
|
* **bpf_clone_redirect**\ () or other methods outside of BPF may
|
||||||
|
* interfere with successful delivery to the socket.
|
||||||
|
*
|
||||||
|
* This operation is only valid from TC ingress path.
|
||||||
|
*
|
||||||
|
* The *flags* argument must be zero.
|
||||||
|
*
|
||||||
|
* Returns
|
||||||
|
* 0 on success, or a negative errno in case of failure.
|
||||||
|
*
|
||||||
|
* * **-EINVAL** Unsupported flags specified.
|
||||||
|
* * **-ENOENT** Socket is unavailable for assignment.
|
||||||
|
* * **-ENETUNREACH** Socket is unreachable (wrong netns).
|
||||||
|
* * **-EOPNOTSUPP** Unsupported operation, for example a
|
||||||
|
* call from outside of TC ingress.
|
||||||
|
* * **-ESOCKTNOSUPPORT** Socket type not supported (reuseport).
|
||||||
|
*/
|
||||||
|
static int (*bpf_sk_assign)(struct __sk_buff *skb, struct bpf_sock *sk, __u64 flags) = (void *) 124;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,9 @@
|
|||||||
#ifndef __always_inline
|
#ifndef __always_inline
|
||||||
#define __always_inline __attribute__((always_inline))
|
#define __always_inline __attribute__((always_inline))
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef __weak
|
||||||
|
#define __weak __attribute__((weak))
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper structure used by eBPF C program
|
* Helper structure used by eBPF C program
|
||||||
@@ -44,4 +47,12 @@ enum libbpf_pin_type {
|
|||||||
LIBBPF_PIN_BY_NAME,
|
LIBBPF_PIN_BY_NAME,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum libbpf_tristate {
|
||||||
|
TRI_NO = 0,
|
||||||
|
TRI_YES = 1,
|
||||||
|
TRI_MODULE = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define __kconfig __attribute__((section(".kconfig")))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,6 +8,9 @@
|
|||||||
#include "libbpf.h"
|
#include "libbpf.h"
|
||||||
#include "libbpf_internal.h"
|
#include "libbpf_internal.h"
|
||||||
|
|
||||||
|
/* make sure libbpf doesn't use kernel-only integer typedefs */
|
||||||
|
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
|
||||||
|
|
||||||
struct bpf_prog_linfo {
|
struct bpf_prog_linfo {
|
||||||
void *raw_linfo;
|
void *raw_linfo;
|
||||||
void *raw_jited_linfo;
|
void *raw_jited_linfo;
|
||||||
|
|||||||
@@ -49,7 +49,8 @@
|
|||||||
|
|
||||||
#if defined(bpf_target_x86)
|
#if defined(bpf_target_x86)
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#if defined(__KERNEL__) || defined(__VMLINUX_H__)
|
||||||
|
|
||||||
#define PT_REGS_PARM1(x) ((x)->di)
|
#define PT_REGS_PARM1(x) ((x)->di)
|
||||||
#define PT_REGS_PARM2(x) ((x)->si)
|
#define PT_REGS_PARM2(x) ((x)->si)
|
||||||
#define PT_REGS_PARM3(x) ((x)->dx)
|
#define PT_REGS_PARM3(x) ((x)->dx)
|
||||||
@@ -60,7 +61,20 @@
|
|||||||
#define PT_REGS_RC(x) ((x)->ax)
|
#define PT_REGS_RC(x) ((x)->ax)
|
||||||
#define PT_REGS_SP(x) ((x)->sp)
|
#define PT_REGS_SP(x) ((x)->sp)
|
||||||
#define PT_REGS_IP(x) ((x)->ip)
|
#define PT_REGS_IP(x) ((x)->ip)
|
||||||
|
|
||||||
|
#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), di)
|
||||||
|
#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), si)
|
||||||
|
#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), dx)
|
||||||
|
#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), cx)
|
||||||
|
#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), r8)
|
||||||
|
#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), sp)
|
||||||
|
#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), bp)
|
||||||
|
#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), ax)
|
||||||
|
#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), sp)
|
||||||
|
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), ip)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#ifdef __i386__
|
#ifdef __i386__
|
||||||
/* i386 kernel is built with -mregparm=3 */
|
/* i386 kernel is built with -mregparm=3 */
|
||||||
#define PT_REGS_PARM1(x) ((x)->eax)
|
#define PT_REGS_PARM1(x) ((x)->eax)
|
||||||
@@ -73,7 +87,20 @@
|
|||||||
#define PT_REGS_RC(x) ((x)->eax)
|
#define PT_REGS_RC(x) ((x)->eax)
|
||||||
#define PT_REGS_SP(x) ((x)->esp)
|
#define PT_REGS_SP(x) ((x)->esp)
|
||||||
#define PT_REGS_IP(x) ((x)->eip)
|
#define PT_REGS_IP(x) ((x)->eip)
|
||||||
|
|
||||||
|
#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), eax)
|
||||||
|
#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), edx)
|
||||||
|
#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), ecx)
|
||||||
|
#define PT_REGS_PARM4_CORE(x) 0
|
||||||
|
#define PT_REGS_PARM5_CORE(x) 0
|
||||||
|
#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), esp)
|
||||||
|
#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), ebp)
|
||||||
|
#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), eax)
|
||||||
|
#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), esp)
|
||||||
|
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), eip)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define PT_REGS_PARM1(x) ((x)->rdi)
|
#define PT_REGS_PARM1(x) ((x)->rdi)
|
||||||
#define PT_REGS_PARM2(x) ((x)->rsi)
|
#define PT_REGS_PARM2(x) ((x)->rsi)
|
||||||
#define PT_REGS_PARM3(x) ((x)->rdx)
|
#define PT_REGS_PARM3(x) ((x)->rdx)
|
||||||
@@ -84,6 +111,18 @@
|
|||||||
#define PT_REGS_RC(x) ((x)->rax)
|
#define PT_REGS_RC(x) ((x)->rax)
|
||||||
#define PT_REGS_SP(x) ((x)->rsp)
|
#define PT_REGS_SP(x) ((x)->rsp)
|
||||||
#define PT_REGS_IP(x) ((x)->rip)
|
#define PT_REGS_IP(x) ((x)->rip)
|
||||||
|
|
||||||
|
#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), rdi)
|
||||||
|
#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), rsi)
|
||||||
|
#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), rdx)
|
||||||
|
#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), rcx)
|
||||||
|
#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), r8)
|
||||||
|
#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), rsp)
|
||||||
|
#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), rbp)
|
||||||
|
#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), rax)
|
||||||
|
#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), rsp)
|
||||||
|
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), rip)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -104,6 +143,17 @@ struct pt_regs;
|
|||||||
#define PT_REGS_SP(x) (((PT_REGS_S390 *)(x))->gprs[15])
|
#define PT_REGS_SP(x) (((PT_REGS_S390 *)(x))->gprs[15])
|
||||||
#define PT_REGS_IP(x) (((PT_REGS_S390 *)(x))->psw.addr)
|
#define PT_REGS_IP(x) (((PT_REGS_S390 *)(x))->psw.addr)
|
||||||
|
|
||||||
|
#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[2])
|
||||||
|
#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[3])
|
||||||
|
#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[4])
|
||||||
|
#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[5])
|
||||||
|
#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[6])
|
||||||
|
#define PT_REGS_RET_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), grps[14])
|
||||||
|
#define PT_REGS_FP_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[11])
|
||||||
|
#define PT_REGS_RC_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[2])
|
||||||
|
#define PT_REGS_SP_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[15])
|
||||||
|
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), pdw.addr)
|
||||||
|
|
||||||
#elif defined(bpf_target_arm)
|
#elif defined(bpf_target_arm)
|
||||||
|
|
||||||
#define PT_REGS_PARM1(x) ((x)->uregs[0])
|
#define PT_REGS_PARM1(x) ((x)->uregs[0])
|
||||||
@@ -117,6 +167,17 @@ struct pt_regs;
|
|||||||
#define PT_REGS_SP(x) ((x)->uregs[13])
|
#define PT_REGS_SP(x) ((x)->uregs[13])
|
||||||
#define PT_REGS_IP(x) ((x)->uregs[12])
|
#define PT_REGS_IP(x) ((x)->uregs[12])
|
||||||
|
|
||||||
|
#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), uregs[0])
|
||||||
|
#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), uregs[1])
|
||||||
|
#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), uregs[2])
|
||||||
|
#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), uregs[3])
|
||||||
|
#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), uregs[4])
|
||||||
|
#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), uregs[14])
|
||||||
|
#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), uregs[11])
|
||||||
|
#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), uregs[0])
|
||||||
|
#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), uregs[13])
|
||||||
|
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), uregs[12])
|
||||||
|
|
||||||
#elif defined(bpf_target_arm64)
|
#elif defined(bpf_target_arm64)
|
||||||
|
|
||||||
/* 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 */
|
||||||
@@ -134,6 +195,17 @@ struct pt_regs;
|
|||||||
#define PT_REGS_SP(x) (((PT_REGS_ARM64 *)(x))->sp)
|
#define PT_REGS_SP(x) (((PT_REGS_ARM64 *)(x))->sp)
|
||||||
#define PT_REGS_IP(x) (((PT_REGS_ARM64 *)(x))->pc)
|
#define PT_REGS_IP(x) (((PT_REGS_ARM64 *)(x))->pc)
|
||||||
|
|
||||||
|
#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[0])
|
||||||
|
#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[1])
|
||||||
|
#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[2])
|
||||||
|
#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[3])
|
||||||
|
#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[4])
|
||||||
|
#define PT_REGS_RET_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[30])
|
||||||
|
#define PT_REGS_FP_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[29])
|
||||||
|
#define PT_REGS_RC_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[0])
|
||||||
|
#define PT_REGS_SP_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), sp)
|
||||||
|
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), pc)
|
||||||
|
|
||||||
#elif defined(bpf_target_mips)
|
#elif defined(bpf_target_mips)
|
||||||
|
|
||||||
#define PT_REGS_PARM1(x) ((x)->regs[4])
|
#define PT_REGS_PARM1(x) ((x)->regs[4])
|
||||||
@@ -147,6 +219,17 @@ struct pt_regs;
|
|||||||
#define PT_REGS_SP(x) ((x)->regs[29])
|
#define PT_REGS_SP(x) ((x)->regs[29])
|
||||||
#define PT_REGS_IP(x) ((x)->cp0_epc)
|
#define PT_REGS_IP(x) ((x)->cp0_epc)
|
||||||
|
|
||||||
|
#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), regs[4])
|
||||||
|
#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), regs[5])
|
||||||
|
#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), regs[6])
|
||||||
|
#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), regs[7])
|
||||||
|
#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), regs[8])
|
||||||
|
#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), regs[31])
|
||||||
|
#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), regs[30])
|
||||||
|
#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), regs[1])
|
||||||
|
#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), regs[29])
|
||||||
|
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), cp0_epc)
|
||||||
|
|
||||||
#elif defined(bpf_target_powerpc)
|
#elif defined(bpf_target_powerpc)
|
||||||
|
|
||||||
#define PT_REGS_PARM1(x) ((x)->gpr[3])
|
#define PT_REGS_PARM1(x) ((x)->gpr[3])
|
||||||
@@ -158,6 +241,15 @@ struct pt_regs;
|
|||||||
#define PT_REGS_SP(x) ((x)->sp)
|
#define PT_REGS_SP(x) ((x)->sp)
|
||||||
#define PT_REGS_IP(x) ((x)->nip)
|
#define PT_REGS_IP(x) ((x)->nip)
|
||||||
|
|
||||||
|
#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), gpr[3])
|
||||||
|
#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), gpr[4])
|
||||||
|
#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), gpr[5])
|
||||||
|
#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), gpr[6])
|
||||||
|
#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), gpr[7])
|
||||||
|
#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), gpr[3])
|
||||||
|
#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), sp)
|
||||||
|
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), nip)
|
||||||
|
|
||||||
#elif defined(bpf_target_sparc)
|
#elif defined(bpf_target_sparc)
|
||||||
|
|
||||||
#define PT_REGS_PARM1(x) ((x)->u_regs[UREG_I0])
|
#define PT_REGS_PARM1(x) ((x)->u_regs[UREG_I0])
|
||||||
@@ -169,11 +261,22 @@ struct pt_regs;
|
|||||||
#define PT_REGS_RC(x) ((x)->u_regs[UREG_I0])
|
#define PT_REGS_RC(x) ((x)->u_regs[UREG_I0])
|
||||||
#define PT_REGS_SP(x) ((x)->u_regs[UREG_FP])
|
#define PT_REGS_SP(x) ((x)->u_regs[UREG_FP])
|
||||||
|
|
||||||
|
#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I0])
|
||||||
|
#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I1])
|
||||||
|
#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I2])
|
||||||
|
#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I3])
|
||||||
|
#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I4])
|
||||||
|
#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I7])
|
||||||
|
#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I0])
|
||||||
|
#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), u_regs[UREG_FP])
|
||||||
|
|
||||||
/* Should this also be a bpf_target check for the sparc case? */
|
/* Should this also be a bpf_target check for the sparc case? */
|
||||||
#if defined(__arch64__)
|
#if defined(__arch64__)
|
||||||
#define PT_REGS_IP(x) ((x)->tpc)
|
#define PT_REGS_IP(x) ((x)->tpc)
|
||||||
|
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), tpc)
|
||||||
#else
|
#else
|
||||||
#define PT_REGS_IP(x) ((x)->pc)
|
#define PT_REGS_IP(x) ((x)->pc)
|
||||||
|
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), pc)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -192,4 +295,122 @@ struct pt_regs;
|
|||||||
(void *)(PT_REGS_FP(ctx) + sizeof(ip))); })
|
(void *)(PT_REGS_FP(ctx) + sizeof(ip))); })
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ___bpf_concat(a, b) a ## b
|
||||||
|
#define ___bpf_apply(fn, n) ___bpf_concat(fn, n)
|
||||||
|
#define ___bpf_nth(_, _1, _2, _3, _4, _5, _6, _7, _8, _9, _a, _b, _c, N, ...) N
|
||||||
|
#define ___bpf_narg(...) \
|
||||||
|
___bpf_nth(_, ##__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||||
|
#define ___bpf_empty(...) \
|
||||||
|
___bpf_nth(_, ##__VA_ARGS__, N, N, N, N, N, N, N, N, N, N, 0)
|
||||||
|
|
||||||
|
#define ___bpf_ctx_cast0() ctx
|
||||||
|
#define ___bpf_ctx_cast1(x) ___bpf_ctx_cast0(), (void *)ctx[0]
|
||||||
|
#define ___bpf_ctx_cast2(x, args...) ___bpf_ctx_cast1(args), (void *)ctx[1]
|
||||||
|
#define ___bpf_ctx_cast3(x, args...) ___bpf_ctx_cast2(args), (void *)ctx[2]
|
||||||
|
#define ___bpf_ctx_cast4(x, args...) ___bpf_ctx_cast3(args), (void *)ctx[3]
|
||||||
|
#define ___bpf_ctx_cast5(x, args...) ___bpf_ctx_cast4(args), (void *)ctx[4]
|
||||||
|
#define ___bpf_ctx_cast6(x, args...) ___bpf_ctx_cast5(args), (void *)ctx[5]
|
||||||
|
#define ___bpf_ctx_cast7(x, args...) ___bpf_ctx_cast6(args), (void *)ctx[6]
|
||||||
|
#define ___bpf_ctx_cast8(x, args...) ___bpf_ctx_cast7(args), (void *)ctx[7]
|
||||||
|
#define ___bpf_ctx_cast9(x, args...) ___bpf_ctx_cast8(args), (void *)ctx[8]
|
||||||
|
#define ___bpf_ctx_cast10(x, args...) ___bpf_ctx_cast9(args), (void *)ctx[9]
|
||||||
|
#define ___bpf_ctx_cast11(x, args...) ___bpf_ctx_cast10(args), (void *)ctx[10]
|
||||||
|
#define ___bpf_ctx_cast12(x, args...) ___bpf_ctx_cast11(args), (void *)ctx[11]
|
||||||
|
#define ___bpf_ctx_cast(args...) \
|
||||||
|
___bpf_apply(___bpf_ctx_cast, ___bpf_narg(args))(args)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* 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
|
||||||
|
* 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
|
||||||
|
* same syntax as for normal C function. All the casting is hidden and
|
||||||
|
* performed transparently, while user code can just assume working with
|
||||||
|
* function arguments of specified type and name.
|
||||||
|
*
|
||||||
|
* Original raw context argument is preserved as well as 'ctx' argument.
|
||||||
|
* This is useful when using BPF helpers that expect original context
|
||||||
|
* as one of the parameters (e.g., for bpf_perf_event_output()).
|
||||||
|
*/
|
||||||
|
#define BPF_PROG(name, args...) \
|
||||||
|
name(unsigned long long *ctx); \
|
||||||
|
static __attribute__((always_inline)) typeof(name(0)) \
|
||||||
|
____##name(unsigned long long *ctx, ##args); \
|
||||||
|
typeof(name(0)) name(unsigned long long *ctx) \
|
||||||
|
{ \
|
||||||
|
_Pragma("GCC diagnostic push") \
|
||||||
|
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
|
||||||
|
return ____##name(___bpf_ctx_cast(args)); \
|
||||||
|
_Pragma("GCC diagnostic pop") \
|
||||||
|
} \
|
||||||
|
static __attribute__((always_inline)) typeof(name(0)) \
|
||||||
|
____##name(unsigned long long *ctx, ##args)
|
||||||
|
|
||||||
|
struct pt_regs;
|
||||||
|
|
||||||
|
#define ___bpf_kprobe_args0() ctx
|
||||||
|
#define ___bpf_kprobe_args1(x) \
|
||||||
|
___bpf_kprobe_args0(), (void *)PT_REGS_PARM1(ctx)
|
||||||
|
#define ___bpf_kprobe_args2(x, args...) \
|
||||||
|
___bpf_kprobe_args1(args), (void *)PT_REGS_PARM2(ctx)
|
||||||
|
#define ___bpf_kprobe_args3(x, args...) \
|
||||||
|
___bpf_kprobe_args2(args), (void *)PT_REGS_PARM3(ctx)
|
||||||
|
#define ___bpf_kprobe_args4(x, args...) \
|
||||||
|
___bpf_kprobe_args3(args), (void *)PT_REGS_PARM4(ctx)
|
||||||
|
#define ___bpf_kprobe_args5(x, args...) \
|
||||||
|
___bpf_kprobe_args4(args), (void *)PT_REGS_PARM5(ctx)
|
||||||
|
#define ___bpf_kprobe_args(args...) \
|
||||||
|
___bpf_apply(___bpf_kprobe_args, ___bpf_narg(args))(args)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BPF_KPROBE serves the same purpose for kprobes as BPF_PROG for
|
||||||
|
* 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
|
||||||
|
* provides a familiar typed and named function arguments syntax and
|
||||||
|
* semantics of accessing kprobe input paremeters.
|
||||||
|
*
|
||||||
|
* Original struct pt_regs* context is preserved as 'ctx' argument. This might
|
||||||
|
* be necessary when using BPF helpers like bpf_perf_event_output().
|
||||||
|
*/
|
||||||
|
#define BPF_KPROBE(name, args...) \
|
||||||
|
name(struct pt_regs *ctx); \
|
||||||
|
static __attribute__((always_inline)) typeof(name(0)) \
|
||||||
|
____##name(struct pt_regs *ctx, ##args); \
|
||||||
|
typeof(name(0)) name(struct pt_regs *ctx) \
|
||||||
|
{ \
|
||||||
|
_Pragma("GCC diagnostic push") \
|
||||||
|
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
|
||||||
|
return ____##name(___bpf_kprobe_args(args)); \
|
||||||
|
_Pragma("GCC diagnostic pop") \
|
||||||
|
} \
|
||||||
|
static __attribute__((always_inline)) typeof(name(0)) \
|
||||||
|
____##name(struct pt_regs *ctx, ##args)
|
||||||
|
|
||||||
|
#define ___bpf_kretprobe_args0() ctx
|
||||||
|
#define ___bpf_kretprobe_args1(x) \
|
||||||
|
___bpf_kretprobe_args0(), (void *)PT_REGS_RC(ctx)
|
||||||
|
#define ___bpf_kretprobe_args(args...) \
|
||||||
|
___bpf_apply(___bpf_kretprobe_args, ___bpf_narg(args))(args)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BPF_KRETPROBE is similar to BPF_KPROBE, except, it only provides optional
|
||||||
|
* return value (in addition to `struct pt_regs *ctx`), but no input
|
||||||
|
* arguments, because they will be clobbered by the time probed function
|
||||||
|
* returns.
|
||||||
|
*/
|
||||||
|
#define BPF_KRETPROBE(name, args...) \
|
||||||
|
name(struct pt_regs *ctx); \
|
||||||
|
static __attribute__((always_inline)) typeof(name(0)) \
|
||||||
|
____##name(struct pt_regs *ctx, ##args); \
|
||||||
|
typeof(name(0)) name(struct pt_regs *ctx) \
|
||||||
|
{ \
|
||||||
|
_Pragma("GCC diagnostic push") \
|
||||||
|
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
|
||||||
|
return ____##name(___bpf_kretprobe_args(args)); \
|
||||||
|
_Pragma("GCC diagnostic pop") \
|
||||||
|
} \
|
||||||
|
static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
171
src/btf.c
171
src/btf.c
@@ -8,6 +8,10 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/btf.h>
|
#include <linux/btf.h>
|
||||||
#include <gelf.h>
|
#include <gelf.h>
|
||||||
@@ -17,8 +21,11 @@
|
|||||||
#include "libbpf_internal.h"
|
#include "libbpf_internal.h"
|
||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
|
|
||||||
#define BTF_MAX_NR_TYPES 0x7fffffff
|
/* make sure libbpf doesn't use kernel-only integer typedefs */
|
||||||
#define BTF_MAX_STR_OFFSET 0x7fffffff
|
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
|
||||||
|
|
||||||
|
#define BTF_MAX_NR_TYPES 0x7fffffffU
|
||||||
|
#define BTF_MAX_STR_OFFSET 0x7fffffffU
|
||||||
|
|
||||||
static struct btf_type btf_void;
|
static struct btf_type btf_void;
|
||||||
|
|
||||||
@@ -50,7 +57,7 @@ static int btf_add_type(struct btf *btf, struct btf_type *t)
|
|||||||
if (btf->types_size == BTF_MAX_NR_TYPES)
|
if (btf->types_size == BTF_MAX_NR_TYPES)
|
||||||
return -E2BIG;
|
return -E2BIG;
|
||||||
|
|
||||||
expand_by = max(btf->types_size >> 2, 16);
|
expand_by = max(btf->types_size >> 2, 16U);
|
||||||
new_size = min(BTF_MAX_NR_TYPES, btf->types_size + expand_by);
|
new_size = min(BTF_MAX_NR_TYPES, btf->types_size + expand_by);
|
||||||
|
|
||||||
new_types = realloc(btf->types, sizeof(*new_types) * new_size);
|
new_types = realloc(btf->types, sizeof(*new_types) * new_size);
|
||||||
@@ -278,6 +285,45 @@ done:
|
|||||||
return nelems * size;
|
return nelems * size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int btf__align_of(const struct btf *btf, __u32 id)
|
||||||
|
{
|
||||||
|
const struct btf_type *t = btf__type_by_id(btf, id);
|
||||||
|
__u16 kind = btf_kind(t);
|
||||||
|
|
||||||
|
switch (kind) {
|
||||||
|
case BTF_KIND_INT:
|
||||||
|
case BTF_KIND_ENUM:
|
||||||
|
return min(sizeof(void *), (size_t)t->size);
|
||||||
|
case BTF_KIND_PTR:
|
||||||
|
return sizeof(void *);
|
||||||
|
case BTF_KIND_TYPEDEF:
|
||||||
|
case BTF_KIND_VOLATILE:
|
||||||
|
case BTF_KIND_CONST:
|
||||||
|
case BTF_KIND_RESTRICT:
|
||||||
|
return btf__align_of(btf, t->type);
|
||||||
|
case BTF_KIND_ARRAY:
|
||||||
|
return btf__align_of(btf, btf_array(t)->type);
|
||||||
|
case BTF_KIND_STRUCT:
|
||||||
|
case BTF_KIND_UNION: {
|
||||||
|
const struct btf_member *m = btf_members(t);
|
||||||
|
__u16 vlen = btf_vlen(t);
|
||||||
|
int i, max_align = 1, align;
|
||||||
|
|
||||||
|
for (i = 0; i < vlen; i++, m++) {
|
||||||
|
align = btf__align_of(btf, m->type);
|
||||||
|
if (align <= 0)
|
||||||
|
return align;
|
||||||
|
max_align = max(max_align, align);
|
||||||
|
}
|
||||||
|
|
||||||
|
return max_align;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
pr_warn("unsupported BTF_KIND:%u\n", btf_kind(t));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int btf__resolve_type(const struct btf *btf, __u32 type_id)
|
int btf__resolve_type(const struct btf *btf, __u32 type_id)
|
||||||
{
|
{
|
||||||
const struct btf_type *t;
|
const struct btf_type *t;
|
||||||
@@ -539,6 +585,12 @@ static int btf_fixup_datasec(struct bpf_object *obj, struct btf *btf,
|
|||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* .extern datasec size and var offsets were set correctly during
|
||||||
|
* extern collection step, so just skip straight to sorting variables
|
||||||
|
*/
|
||||||
|
if (t->size)
|
||||||
|
goto sort_vars;
|
||||||
|
|
||||||
ret = bpf_object__section_size(obj, name, &size);
|
ret = bpf_object__section_size(obj, name, &size);
|
||||||
if (ret || !size || (t->size && t->size != size)) {
|
if (ret || !size || (t->size && t->size != size)) {
|
||||||
pr_debug("Invalid size for section %s: %u bytes\n", name, size);
|
pr_debug("Invalid size for section %s: %u bytes\n", name, size);
|
||||||
@@ -575,7 +627,8 @@ static int btf_fixup_datasec(struct bpf_object *obj, struct btf *btf,
|
|||||||
vsi->offset = off;
|
vsi->offset = off;
|
||||||
}
|
}
|
||||||
|
|
||||||
qsort(t + 1, vars, sizeof(*vsi), compare_vsi_off);
|
sort_vars:
|
||||||
|
qsort(btf_var_secinfos(t), vars, sizeof(*vsi), compare_vsi_off);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -604,22 +657,32 @@ int btf__finalize_data(struct bpf_object *obj, struct btf *btf)
|
|||||||
|
|
||||||
int btf__load(struct btf *btf)
|
int btf__load(struct btf *btf)
|
||||||
{
|
{
|
||||||
__u32 log_buf_size = BPF_LOG_BUF_SIZE;
|
__u32 log_buf_size = 0;
|
||||||
char *log_buf = NULL;
|
char *log_buf = NULL;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (btf->fd >= 0)
|
if (btf->fd >= 0)
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
|
|
||||||
log_buf = malloc(log_buf_size);
|
retry_load:
|
||||||
if (!log_buf)
|
if (log_buf_size) {
|
||||||
return -ENOMEM;
|
log_buf = malloc(log_buf_size);
|
||||||
|
if (!log_buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
*log_buf = 0;
|
*log_buf = 0;
|
||||||
|
}
|
||||||
|
|
||||||
btf->fd = bpf_load_btf(btf->data, btf->data_size,
|
btf->fd = bpf_load_btf(btf->data, btf->data_size,
|
||||||
log_buf, log_buf_size, false);
|
log_buf, log_buf_size, false);
|
||||||
if (btf->fd < 0) {
|
if (btf->fd < 0) {
|
||||||
|
if (!log_buf || errno == ENOSPC) {
|
||||||
|
log_buf_size = max((__u32)BPF_LOG_BUF_SIZE,
|
||||||
|
log_buf_size << 1);
|
||||||
|
free(log_buf);
|
||||||
|
goto retry_load;
|
||||||
|
}
|
||||||
|
|
||||||
err = -errno;
|
err = -errno;
|
||||||
pr_warn("Error loading BTF: %s(%d)\n", strerror(errno), errno);
|
pr_warn("Error loading BTF: %s(%d)\n", strerror(errno), errno);
|
||||||
if (*log_buf)
|
if (*log_buf)
|
||||||
@@ -1352,7 +1415,7 @@ static int btf_dedup_hypot_map_add(struct btf_dedup *d,
|
|||||||
if (d->hypot_cnt == d->hypot_cap) {
|
if (d->hypot_cnt == d->hypot_cap) {
|
||||||
__u32 *new_list;
|
__u32 *new_list;
|
||||||
|
|
||||||
d->hypot_cap += max(16, d->hypot_cap / 2);
|
d->hypot_cap += max((size_t)16, d->hypot_cap / 2);
|
||||||
new_list = realloc(d->hypot_list, sizeof(__u32) * d->hypot_cap);
|
new_list = realloc(d->hypot_list, sizeof(__u32) * d->hypot_cap);
|
||||||
if (!new_list)
|
if (!new_list)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@@ -1648,7 +1711,7 @@ static int btf_dedup_strings(struct btf_dedup *d)
|
|||||||
if (strs.cnt + 1 > strs.cap) {
|
if (strs.cnt + 1 > strs.cap) {
|
||||||
struct btf_str_ptr *new_ptrs;
|
struct btf_str_ptr *new_ptrs;
|
||||||
|
|
||||||
strs.cap += max(strs.cnt / 2, 16);
|
strs.cap += max(strs.cnt / 2, 16U);
|
||||||
new_ptrs = realloc(strs.ptrs,
|
new_ptrs = realloc(strs.ptrs,
|
||||||
sizeof(strs.ptrs[0]) * strs.cap);
|
sizeof(strs.ptrs[0]) * strs.cap);
|
||||||
if (!new_ptrs) {
|
if (!new_ptrs) {
|
||||||
@@ -2882,3 +2945,89 @@ static int btf_dedup_remap_types(struct btf_dedup *d)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct btf *btf_load_raw(const char *path)
|
||||||
|
{
|
||||||
|
struct btf *btf;
|
||||||
|
size_t read_cnt;
|
||||||
|
struct stat st;
|
||||||
|
void *data;
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
if (stat(path, &st))
|
||||||
|
return ERR_PTR(-errno);
|
||||||
|
|
||||||
|
data = malloc(st.st_size);
|
||||||
|
if (!data)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
f = fopen(path, "rb");
|
||||||
|
if (!f) {
|
||||||
|
btf = ERR_PTR(-errno);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
read_cnt = fread(data, 1, st.st_size, f);
|
||||||
|
fclose(f);
|
||||||
|
if (read_cnt < st.st_size) {
|
||||||
|
btf = ERR_PTR(-EBADF);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
btf = btf__new(data, read_cnt);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
free(data);
|
||||||
|
return btf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Probe few well-known locations for vmlinux kernel image and try to load BTF
|
||||||
|
* data out of it to use for target BTF.
|
||||||
|
*/
|
||||||
|
struct btf *libbpf_find_kernel_btf(void)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
const char *path_fmt;
|
||||||
|
bool raw_btf;
|
||||||
|
} locations[] = {
|
||||||
|
/* try canonical vmlinux BTF through sysfs first */
|
||||||
|
{ "/sys/kernel/btf/vmlinux", true /* raw BTF */ },
|
||||||
|
/* fall back to trying to find vmlinux ELF on disk otherwise */
|
||||||
|
{ "/boot/vmlinux-%1$s" },
|
||||||
|
{ "/lib/modules/%1$s/vmlinux-%1$s" },
|
||||||
|
{ "/lib/modules/%1$s/build/vmlinux" },
|
||||||
|
{ "/usr/lib/modules/%1$s/kernel/vmlinux" },
|
||||||
|
{ "/usr/lib/debug/boot/vmlinux-%1$s" },
|
||||||
|
{ "/usr/lib/debug/boot/vmlinux-%1$s.debug" },
|
||||||
|
{ "/usr/lib/debug/lib/modules/%1$s/vmlinux" },
|
||||||
|
};
|
||||||
|
char path[PATH_MAX + 1];
|
||||||
|
struct utsname buf;
|
||||||
|
struct btf *btf;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
uname(&buf);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(locations); i++) {
|
||||||
|
snprintf(path, PATH_MAX, locations[i].path_fmt, buf.release);
|
||||||
|
|
||||||
|
if (access(path, R_OK))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (locations[i].raw_btf)
|
||||||
|
btf = btf_load_raw(path);
|
||||||
|
else
|
||||||
|
btf = btf__parse_elf(path, NULL);
|
||||||
|
|
||||||
|
pr_debug("loading kernel BTF '%s': %ld\n",
|
||||||
|
path, IS_ERR(btf) ? PTR_ERR(btf) : 0);
|
||||||
|
if (IS_ERR(btf))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return btf;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_warn("failed to find valid kernel BTF\n");
|
||||||
|
return ERR_PTR(-ESRCH);
|
||||||
|
}
|
||||||
|
|||||||
31
src/btf.h
31
src/btf.h
@@ -8,14 +8,12 @@
|
|||||||
#include <linux/btf.h>
|
#include <linux/btf.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#include "libbpf_common.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef LIBBPF_API
|
|
||||||
#define LIBBPF_API __attribute__((visibility("default")))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define BTF_ELF_SEC ".BTF"
|
#define BTF_ELF_SEC ".BTF"
|
||||||
#define BTF_EXT_ELF_SEC ".BTF.ext"
|
#define BTF_EXT_ELF_SEC ".BTF.ext"
|
||||||
#define MAPS_ELF_SEC ".maps"
|
#define MAPS_ELF_SEC ".maps"
|
||||||
@@ -79,6 +77,7 @@ LIBBPF_API const struct btf_type *btf__type_by_id(const struct btf *btf,
|
|||||||
__u32 id);
|
__u32 id);
|
||||||
LIBBPF_API __s64 btf__resolve_size(const struct btf *btf, __u32 type_id);
|
LIBBPF_API __s64 btf__resolve_size(const struct btf *btf, __u32 type_id);
|
||||||
LIBBPF_API int btf__resolve_type(const struct btf *btf, __u32 type_id);
|
LIBBPF_API int btf__resolve_type(const struct btf *btf, __u32 type_id);
|
||||||
|
LIBBPF_API int btf__align_of(const struct btf *btf, __u32 id);
|
||||||
LIBBPF_API int btf__fd(const struct btf *btf);
|
LIBBPF_API int btf__fd(const struct btf *btf);
|
||||||
LIBBPF_API const void *btf__get_raw_data(const struct btf *btf, __u32 *size);
|
LIBBPF_API const void *btf__get_raw_data(const struct btf *btf, __u32 *size);
|
||||||
LIBBPF_API const char *btf__name_by_offset(const struct btf *btf, __u32 offset);
|
LIBBPF_API const char *btf__name_by_offset(const struct btf *btf, __u32 offset);
|
||||||
@@ -103,6 +102,8 @@ LIBBPF_API int btf_ext__reloc_line_info(const struct btf *btf,
|
|||||||
LIBBPF_API __u32 btf_ext__func_info_rec_size(const struct btf_ext *btf_ext);
|
LIBBPF_API __u32 btf_ext__func_info_rec_size(const struct btf_ext *btf_ext);
|
||||||
LIBBPF_API __u32 btf_ext__line_info_rec_size(const struct btf_ext *btf_ext);
|
LIBBPF_API __u32 btf_ext__line_info_rec_size(const struct btf_ext *btf_ext);
|
||||||
|
|
||||||
|
LIBBPF_API struct btf *libbpf_find_kernel_btf(void);
|
||||||
|
|
||||||
struct btf_dedup_opts {
|
struct btf_dedup_opts {
|
||||||
unsigned int dedup_table_size;
|
unsigned int dedup_table_size;
|
||||||
bool dont_resolve_fwds;
|
bool dont_resolve_fwds;
|
||||||
@@ -127,6 +128,28 @@ 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 {
|
||||||
|
/* size of this struct, for forward/backward compatiblity */
|
||||||
|
size_t sz;
|
||||||
|
/* optional field name for type declaration, e.g.:
|
||||||
|
* - struct my_struct <FNAME>
|
||||||
|
* - void (*<FNAME>)(int)
|
||||||
|
* - char (*<FNAME>)[123]
|
||||||
|
*/
|
||||||
|
const char *field_name;
|
||||||
|
/* extra indentation level (in number of tabs) to emit for multi-line
|
||||||
|
* type declarations (e.g., anonymous struct); applies for lines
|
||||||
|
* starting from the second one (first line is assumed to have
|
||||||
|
* necessary indentation already
|
||||||
|
*/
|
||||||
|
int indent_level;
|
||||||
|
};
|
||||||
|
#define btf_dump_emit_type_decl_opts__last_field indent_level
|
||||||
|
|
||||||
|
LIBBPF_API int
|
||||||
|
btf_dump__emit_type_decl(struct btf_dump *d, __u32 id,
|
||||||
|
const struct btf_dump_emit_type_decl_opts *opts);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A set of helpers for easier BTF types handling
|
* A set of helpers for easier BTF types handling
|
||||||
*/
|
*/
|
||||||
|
|||||||
127
src/btf_dump.c
127
src/btf_dump.c
@@ -18,6 +18,9 @@
|
|||||||
#include "libbpf.h"
|
#include "libbpf.h"
|
||||||
#include "libbpf_internal.h"
|
#include "libbpf_internal.h"
|
||||||
|
|
||||||
|
/* make sure libbpf doesn't use kernel-only integer typedefs */
|
||||||
|
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
|
||||||
|
|
||||||
static const char PREFIXES[] = "\t\t\t\t\t\t\t\t\t\t\t\t\t";
|
static const char PREFIXES[] = "\t\t\t\t\t\t\t\t\t\t\t\t\t";
|
||||||
static const size_t PREFIX_CNT = sizeof(PREFIXES) - 1;
|
static const size_t PREFIX_CNT = sizeof(PREFIXES) - 1;
|
||||||
|
|
||||||
@@ -116,6 +119,8 @@ static void btf_dump_printf(const struct btf_dump *d, const char *fmt, ...)
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int btf_dump_mark_referenced(struct btf_dump *d);
|
||||||
|
|
||||||
struct btf_dump *btf_dump__new(const struct btf *btf,
|
struct btf_dump *btf_dump__new(const struct btf *btf,
|
||||||
const struct btf_ext *btf_ext,
|
const struct btf_ext *btf_ext,
|
||||||
const struct btf_dump_opts *opts,
|
const struct btf_dump_opts *opts,
|
||||||
@@ -137,18 +142,40 @@ struct btf_dump *btf_dump__new(const struct btf *btf,
|
|||||||
if (IS_ERR(d->type_names)) {
|
if (IS_ERR(d->type_names)) {
|
||||||
err = PTR_ERR(d->type_names);
|
err = PTR_ERR(d->type_names);
|
||||||
d->type_names = NULL;
|
d->type_names = NULL;
|
||||||
btf_dump__free(d);
|
goto err;
|
||||||
return ERR_PTR(err);
|
|
||||||
}
|
}
|
||||||
d->ident_names = hashmap__new(str_hash_fn, str_equal_fn, NULL);
|
d->ident_names = hashmap__new(str_hash_fn, str_equal_fn, NULL);
|
||||||
if (IS_ERR(d->ident_names)) {
|
if (IS_ERR(d->ident_names)) {
|
||||||
err = PTR_ERR(d->ident_names);
|
err = PTR_ERR(d->ident_names);
|
||||||
d->ident_names = NULL;
|
d->ident_names = NULL;
|
||||||
btf_dump__free(d);
|
goto err;
|
||||||
return ERR_PTR(err);
|
}
|
||||||
|
d->type_states = calloc(1 + btf__get_nr_types(d->btf),
|
||||||
|
sizeof(d->type_states[0]));
|
||||||
|
if (!d->type_states) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
d->cached_names = calloc(1 + btf__get_nr_types(d->btf),
|
||||||
|
sizeof(d->cached_names[0]));
|
||||||
|
if (!d->cached_names) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* VOID is special */
|
||||||
|
d->type_states[0].order_state = ORDERED;
|
||||||
|
d->type_states[0].emit_state = EMITTED;
|
||||||
|
|
||||||
|
/* eagerly determine referenced types for anon enums */
|
||||||
|
err = btf_dump_mark_referenced(d);
|
||||||
|
if (err)
|
||||||
|
goto err;
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
|
err:
|
||||||
|
btf_dump__free(d);
|
||||||
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
void btf_dump__free(struct btf_dump *d)
|
void btf_dump__free(struct btf_dump *d)
|
||||||
@@ -175,7 +202,6 @@ void btf_dump__free(struct btf_dump *d)
|
|||||||
free(d);
|
free(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int btf_dump_mark_referenced(struct btf_dump *d);
|
|
||||||
static int btf_dump_order_type(struct btf_dump *d, __u32 id, bool through_ptr);
|
static int btf_dump_order_type(struct btf_dump *d, __u32 id, bool through_ptr);
|
||||||
static void btf_dump_emit_type(struct btf_dump *d, __u32 id, __u32 cont_id);
|
static void btf_dump_emit_type(struct btf_dump *d, __u32 id, __u32 cont_id);
|
||||||
|
|
||||||
@@ -202,27 +228,6 @@ int btf_dump__dump_type(struct btf_dump *d, __u32 id)
|
|||||||
if (id > btf__get_nr_types(d->btf))
|
if (id > btf__get_nr_types(d->btf))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* type states are lazily allocated, as they might not be needed */
|
|
||||||
if (!d->type_states) {
|
|
||||||
d->type_states = calloc(1 + btf__get_nr_types(d->btf),
|
|
||||||
sizeof(d->type_states[0]));
|
|
||||||
if (!d->type_states)
|
|
||||||
return -ENOMEM;
|
|
||||||
d->cached_names = calloc(1 + btf__get_nr_types(d->btf),
|
|
||||||
sizeof(d->cached_names[0]));
|
|
||||||
if (!d->cached_names)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
/* VOID is special */
|
|
||||||
d->type_states[0].order_state = ORDERED;
|
|
||||||
d->type_states[0].emit_state = EMITTED;
|
|
||||||
|
|
||||||
/* eagerly determine referenced types for anon enums */
|
|
||||||
err = btf_dump_mark_referenced(d);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->emit_queue_cnt = 0;
|
d->emit_queue_cnt = 0;
|
||||||
err = btf_dump_order_type(d, id, false);
|
err = btf_dump_order_type(d, id, false);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
@@ -752,41 +757,6 @@ static void btf_dump_emit_type(struct btf_dump *d, __u32 id, __u32 cont_id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int btf_align_of(const struct btf *btf, __u32 id)
|
|
||||||
{
|
|
||||||
const struct btf_type *t = btf__type_by_id(btf, id);
|
|
||||||
__u16 kind = btf_kind(t);
|
|
||||||
|
|
||||||
switch (kind) {
|
|
||||||
case BTF_KIND_INT:
|
|
||||||
case BTF_KIND_ENUM:
|
|
||||||
return min(sizeof(void *), t->size);
|
|
||||||
case BTF_KIND_PTR:
|
|
||||||
return sizeof(void *);
|
|
||||||
case BTF_KIND_TYPEDEF:
|
|
||||||
case BTF_KIND_VOLATILE:
|
|
||||||
case BTF_KIND_CONST:
|
|
||||||
case BTF_KIND_RESTRICT:
|
|
||||||
return btf_align_of(btf, t->type);
|
|
||||||
case BTF_KIND_ARRAY:
|
|
||||||
return btf_align_of(btf, btf_array(t)->type);
|
|
||||||
case BTF_KIND_STRUCT:
|
|
||||||
case BTF_KIND_UNION: {
|
|
||||||
const struct btf_member *m = btf_members(t);
|
|
||||||
__u16 vlen = btf_vlen(t);
|
|
||||||
int i, align = 1;
|
|
||||||
|
|
||||||
for (i = 0; i < vlen; i++, m++)
|
|
||||||
align = max(align, btf_align_of(btf, m->type));
|
|
||||||
|
|
||||||
return align;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
pr_warn("unsupported BTF_KIND:%u\n", btf_kind(t));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool btf_is_struct_packed(const struct btf *btf, __u32 id,
|
static bool btf_is_struct_packed(const struct btf *btf, __u32 id,
|
||||||
const struct btf_type *t)
|
const struct btf_type *t)
|
||||||
{
|
{
|
||||||
@@ -794,18 +764,18 @@ static bool btf_is_struct_packed(const struct btf *btf, __u32 id,
|
|||||||
int align, i, bit_sz;
|
int align, i, bit_sz;
|
||||||
__u16 vlen;
|
__u16 vlen;
|
||||||
|
|
||||||
align = btf_align_of(btf, id);
|
align = btf__align_of(btf, id);
|
||||||
/* size of a non-packed struct has to be a multiple of its alignment*/
|
/* size of a non-packed struct has to be a multiple of its alignment*/
|
||||||
if (t->size % align)
|
if (align && t->size % align)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
m = btf_members(t);
|
m = btf_members(t);
|
||||||
vlen = btf_vlen(t);
|
vlen = btf_vlen(t);
|
||||||
/* all non-bitfield fields have to be naturally aligned */
|
/* all non-bitfield fields have to be naturally aligned */
|
||||||
for (i = 0; i < vlen; i++, m++) {
|
for (i = 0; i < vlen; i++, m++) {
|
||||||
align = btf_align_of(btf, m->type);
|
align = btf__align_of(btf, m->type);
|
||||||
bit_sz = btf_member_bitfield_size(t, i);
|
bit_sz = btf_member_bitfield_size(t, i);
|
||||||
if (bit_sz == 0 && m->offset % (8 * align) != 0)
|
if (align && bit_sz == 0 && m->offset % (8 * align) != 0)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -889,7 +859,7 @@ static void btf_dump_emit_struct_def(struct btf_dump *d,
|
|||||||
fname = btf_name_of(d, m->name_off);
|
fname = btf_name_of(d, m->name_off);
|
||||||
m_sz = btf_member_bitfield_size(t, i);
|
m_sz = btf_member_bitfield_size(t, i);
|
||||||
m_off = btf_member_bit_offset(t, i);
|
m_off = btf_member_bit_offset(t, i);
|
||||||
align = packed ? 1 : btf_align_of(d->btf, m->type);
|
align = packed ? 1 : btf__align_of(d->btf, m->type);
|
||||||
|
|
||||||
btf_dump_emit_bit_padding(d, off, m_off, m_sz, align, lvl + 1);
|
btf_dump_emit_bit_padding(d, off, m_off, m_sz, align, lvl + 1);
|
||||||
btf_dump_printf(d, "\n%s", pfx(lvl + 1));
|
btf_dump_printf(d, "\n%s", pfx(lvl + 1));
|
||||||
@@ -907,7 +877,7 @@ static void btf_dump_emit_struct_def(struct btf_dump *d,
|
|||||||
|
|
||||||
/* pad at the end, if necessary */
|
/* pad at the end, if necessary */
|
||||||
if (is_struct) {
|
if (is_struct) {
|
||||||
align = packed ? 1 : btf_align_of(d->btf, id);
|
align = packed ? 1 : btf__align_of(d->btf, id);
|
||||||
btf_dump_emit_bit_padding(d, off, t->size * 8, 0, align,
|
btf_dump_emit_bit_padding(d, off, t->size * 8, 0, align,
|
||||||
lvl + 1);
|
lvl + 1);
|
||||||
}
|
}
|
||||||
@@ -946,13 +916,13 @@ static void btf_dump_emit_enum_def(struct btf_dump *d, __u32 id,
|
|||||||
/* enumerators share namespace with typedef idents */
|
/* enumerators share namespace with typedef idents */
|
||||||
dup_cnt = btf_dump_name_dups(d, d->ident_names, name);
|
dup_cnt = btf_dump_name_dups(d, d->ident_names, name);
|
||||||
if (dup_cnt > 1) {
|
if (dup_cnt > 1) {
|
||||||
btf_dump_printf(d, "\n%s%s___%zu = %d,",
|
btf_dump_printf(d, "\n%s%s___%zu = %u,",
|
||||||
pfx(lvl + 1), name, dup_cnt,
|
pfx(lvl + 1), name, dup_cnt,
|
||||||
(__s32)v->val);
|
(__u32)v->val);
|
||||||
} else {
|
} else {
|
||||||
btf_dump_printf(d, "\n%s%s = %d,",
|
btf_dump_printf(d, "\n%s%s = %u,",
|
||||||
pfx(lvl + 1), name,
|
pfx(lvl + 1), name,
|
||||||
(__s32)v->val);
|
(__u32)v->val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
btf_dump_printf(d, "\n%s}", pfx(lvl));
|
btf_dump_printf(d, "\n%s}", pfx(lvl));
|
||||||
@@ -1051,6 +1021,21 @@ static int btf_dump_push_decl_stack_id(struct btf_dump *d, __u32 id)
|
|||||||
* of a stack frame. Some care is required to "pop" stack frames after
|
* of a stack frame. Some care is required to "pop" stack frames after
|
||||||
* processing type declaration chain.
|
* processing type declaration chain.
|
||||||
*/
|
*/
|
||||||
|
int btf_dump__emit_type_decl(struct btf_dump *d, __u32 id,
|
||||||
|
const struct btf_dump_emit_type_decl_opts *opts)
|
||||||
|
{
|
||||||
|
const char *fname;
|
||||||
|
int lvl;
|
||||||
|
|
||||||
|
if (!OPTS_VALID(opts, btf_dump_emit_type_decl_opts))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
fname = OPTS_GET(opts, field_name, "");
|
||||||
|
lvl = OPTS_GET(opts, indent_level, 0);
|
||||||
|
btf_dump_emit_type_decl(d, id, fname, lvl);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void btf_dump_emit_type_decl(struct btf_dump *d, __u32 id,
|
static void btf_dump_emit_type_decl(struct btf_dump *d, __u32 id,
|
||||||
const char *fname, int lvl)
|
const char *fname, int lvl)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,6 +12,9 @@
|
|||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
|
|
||||||
|
/* make sure libbpf doesn't use kernel-only integer typedefs */
|
||||||
|
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
|
||||||
|
|
||||||
/* start with 4 buckets */
|
/* start with 4 buckets */
|
||||||
#define HASHMAP_MIN_CAP_BITS 2
|
#define HASHMAP_MIN_CAP_BITS 2
|
||||||
|
|
||||||
|
|||||||
3128
src/libbpf.c
3128
src/libbpf.c
File diff suppressed because it is too large
Load Diff
152
src/libbpf.h
152
src/libbpf.h
@@ -17,14 +17,12 @@
|
|||||||
#include <sys/types.h> // for size_t
|
#include <sys/types.h> // for size_t
|
||||||
#include <linux/bpf.h>
|
#include <linux/bpf.h>
|
||||||
|
|
||||||
|
#include "libbpf_common.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef LIBBPF_API
|
|
||||||
#define LIBBPF_API __attribute__((visibility("default")))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum libbpf_errno {
|
enum libbpf_errno {
|
||||||
__LIBBPF_ERRNO__START = 4000,
|
__LIBBPF_ERRNO__START = 4000,
|
||||||
|
|
||||||
@@ -67,28 +65,6 @@ struct bpf_object_open_attr {
|
|||||||
enum bpf_prog_type prog_type;
|
enum bpf_prog_type prog_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Helper macro to declare and initialize libbpf options struct
|
|
||||||
*
|
|
||||||
* This dance with uninitialized declaration, followed by memset to zero,
|
|
||||||
* followed by assignment using compound literal syntax is done to preserve
|
|
||||||
* ability to use a nice struct field initialization syntax and **hopefully**
|
|
||||||
* have all the padding bytes initialized to zero. It's not guaranteed though,
|
|
||||||
* when copying literal, that compiler won't copy garbage in literal's padding
|
|
||||||
* bytes, but that's the best way I've found and it seems to work in practice.
|
|
||||||
*
|
|
||||||
* Macro declares opts struct of given type and name, zero-initializes,
|
|
||||||
* including any extra padding, it with memset() and then assigns initial
|
|
||||||
* values provided by users in struct initializer-syntax as varargs.
|
|
||||||
*/
|
|
||||||
#define DECLARE_LIBBPF_OPTS(TYPE, NAME, ...) \
|
|
||||||
struct TYPE NAME = ({ \
|
|
||||||
memset(&NAME, 0, sizeof(struct TYPE)); \
|
|
||||||
(struct TYPE) { \
|
|
||||||
.sz = sizeof(struct TYPE), \
|
|
||||||
__VA_ARGS__ \
|
|
||||||
}; \
|
|
||||||
})
|
|
||||||
|
|
||||||
struct bpf_object_open_opts {
|
struct bpf_object_open_opts {
|
||||||
/* size of this struct, for forward/backward compatiblity */
|
/* size of this struct, for forward/backward compatiblity */
|
||||||
size_t sz;
|
size_t sz;
|
||||||
@@ -101,7 +77,11 @@ struct bpf_object_open_opts {
|
|||||||
const char *object_name;
|
const char *object_name;
|
||||||
/* parse map definitions non-strictly, allowing extra attributes/data */
|
/* parse map definitions non-strictly, allowing extra attributes/data */
|
||||||
bool relaxed_maps;
|
bool relaxed_maps;
|
||||||
/* process CO-RE relocations non-strictly, allowing them to fail */
|
/* DEPRECATED: handle CO-RE relocations non-strictly, allowing failures.
|
||||||
|
* Value is ignored. Relocations always are processed non-strictly.
|
||||||
|
* Non-relocatable instructions are replaced with invalid ones to
|
||||||
|
* prevent accidental errors.
|
||||||
|
* */
|
||||||
bool relaxed_core_relocs;
|
bool relaxed_core_relocs;
|
||||||
/* maps that set the 'pinning' attribute in their definition will have
|
/* maps that set the 'pinning' attribute in their definition will have
|
||||||
* their pin_path attribute set to a file in this directory, and be
|
* their pin_path attribute set to a file in this directory, and be
|
||||||
@@ -109,15 +89,19 @@ struct bpf_object_open_opts {
|
|||||||
*/
|
*/
|
||||||
const char *pin_root_path;
|
const char *pin_root_path;
|
||||||
__u32 attach_prog_fd;
|
__u32 attach_prog_fd;
|
||||||
|
/* Additional kernel config content that augments and overrides
|
||||||
|
* system Kconfig for CONFIG_xxx externs.
|
||||||
|
*/
|
||||||
|
const char *kconfig;
|
||||||
};
|
};
|
||||||
#define bpf_object_open_opts__last_field attach_prog_fd
|
#define bpf_object_open_opts__last_field kconfig
|
||||||
|
|
||||||
LIBBPF_API struct bpf_object *bpf_object__open(const char *path);
|
LIBBPF_API struct bpf_object *bpf_object__open(const char *path);
|
||||||
LIBBPF_API struct bpf_object *
|
LIBBPF_API struct bpf_object *
|
||||||
bpf_object__open_file(const char *path, struct bpf_object_open_opts *opts);
|
bpf_object__open_file(const char *path, const struct bpf_object_open_opts *opts);
|
||||||
LIBBPF_API struct bpf_object *
|
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,
|
||||||
struct bpf_object_open_opts *opts);
|
const struct bpf_object_open_opts *opts);
|
||||||
|
|
||||||
/* deprecated bpf_object__open variants */
|
/* deprecated bpf_object__open variants */
|
||||||
LIBBPF_API struct bpf_object *
|
LIBBPF_API struct bpf_object *
|
||||||
@@ -126,11 +110,6 @@ bpf_object__open_buffer(const void *obj_buf, size_t obj_buf_sz,
|
|||||||
LIBBPF_API struct bpf_object *
|
LIBBPF_API struct bpf_object *
|
||||||
bpf_object__open_xattr(struct bpf_object_open_attr *attr);
|
bpf_object__open_xattr(struct bpf_object_open_attr *attr);
|
||||||
|
|
||||||
int bpf_object__section_size(const struct bpf_object *obj, const char *name,
|
|
||||||
__u32 *size);
|
|
||||||
int bpf_object__variable_offset(const struct bpf_object *obj, const char *name,
|
|
||||||
__u32 *off);
|
|
||||||
|
|
||||||
enum libbpf_pin_type {
|
enum libbpf_pin_type {
|
||||||
LIBBPF_PIN_NONE,
|
LIBBPF_PIN_NONE,
|
||||||
/* PIN_BY_NAME: pin maps by name (in /sys/fs/bpf by default) */
|
/* PIN_BY_NAME: pin maps by name (in /sys/fs/bpf by default) */
|
||||||
@@ -161,6 +140,7 @@ struct bpf_object_load_attr {
|
|||||||
LIBBPF_API int bpf_object__load(struct bpf_object *obj);
|
LIBBPF_API int bpf_object__load(struct bpf_object *obj);
|
||||||
LIBBPF_API int bpf_object__load_xattr(struct bpf_object_load_attr *attr);
|
LIBBPF_API int bpf_object__load_xattr(struct bpf_object_load_attr *attr);
|
||||||
LIBBPF_API int bpf_object__unload(struct bpf_object *obj);
|
LIBBPF_API int bpf_object__unload(struct bpf_object *obj);
|
||||||
|
|
||||||
LIBBPF_API const char *bpf_object__name(const struct bpf_object *obj);
|
LIBBPF_API const char *bpf_object__name(const struct bpf_object *obj);
|
||||||
LIBBPF_API unsigned int bpf_object__kversion(const struct bpf_object *obj);
|
LIBBPF_API unsigned int bpf_object__kversion(const struct bpf_object *obj);
|
||||||
|
|
||||||
@@ -171,6 +151,9 @@ LIBBPF_API int bpf_object__btf_fd(const struct bpf_object *obj);
|
|||||||
LIBBPF_API struct bpf_program *
|
LIBBPF_API struct bpf_program *
|
||||||
bpf_object__find_program_by_title(const struct bpf_object *obj,
|
bpf_object__find_program_by_title(const struct bpf_object *obj,
|
||||||
const char *title);
|
const char *title);
|
||||||
|
LIBBPF_API struct bpf_program *
|
||||||
|
bpf_object__find_program_by_name(const struct bpf_object *obj,
|
||||||
|
const char *name);
|
||||||
|
|
||||||
LIBBPF_API struct bpf_object *bpf_object__next(struct bpf_object *prev);
|
LIBBPF_API struct bpf_object *bpf_object__next(struct bpf_object *prev);
|
||||||
#define bpf_object__for_each_safe(pos, tmp) \
|
#define bpf_object__for_each_safe(pos, tmp) \
|
||||||
@@ -214,6 +197,7 @@ LIBBPF_API void *bpf_program__priv(const struct bpf_program *prog);
|
|||||||
LIBBPF_API void bpf_program__set_ifindex(struct bpf_program *prog,
|
LIBBPF_API void bpf_program__set_ifindex(struct bpf_program *prog,
|
||||||
__u32 ifindex);
|
__u32 ifindex);
|
||||||
|
|
||||||
|
LIBBPF_API const char *bpf_program__name(const struct bpf_program *prog);
|
||||||
LIBBPF_API const char *bpf_program__title(const struct bpf_program *prog,
|
LIBBPF_API const char *bpf_program__title(const struct bpf_program *prog,
|
||||||
bool needs_copy);
|
bool needs_copy);
|
||||||
|
|
||||||
@@ -235,8 +219,18 @@ LIBBPF_API void bpf_program__unload(struct bpf_program *prog);
|
|||||||
|
|
||||||
struct bpf_link;
|
struct bpf_link;
|
||||||
|
|
||||||
|
LIBBPF_API struct bpf_link *bpf_link__open(const char *path);
|
||||||
|
LIBBPF_API int bpf_link__fd(const struct bpf_link *link);
|
||||||
|
LIBBPF_API const char *bpf_link__pin_path(const struct bpf_link *link);
|
||||||
|
LIBBPF_API int bpf_link__pin(struct bpf_link *link, const char *path);
|
||||||
|
LIBBPF_API int bpf_link__unpin(struct bpf_link *link);
|
||||||
|
LIBBPF_API int bpf_link__update_program(struct bpf_link *link,
|
||||||
|
struct bpf_program *prog);
|
||||||
|
LIBBPF_API void bpf_link__disconnect(struct bpf_link *link);
|
||||||
LIBBPF_API int bpf_link__destroy(struct bpf_link *link);
|
LIBBPF_API int bpf_link__destroy(struct bpf_link *link);
|
||||||
|
|
||||||
|
LIBBPF_API struct bpf_link *
|
||||||
|
bpf_program__attach(struct bpf_program *prog);
|
||||||
LIBBPF_API struct bpf_link *
|
LIBBPF_API struct bpf_link *
|
||||||
bpf_program__attach_perf_event(struct bpf_program *prog, int pfd);
|
bpf_program__attach_perf_event(struct bpf_program *prog, int pfd);
|
||||||
LIBBPF_API struct bpf_link *
|
LIBBPF_API struct bpf_link *
|
||||||
@@ -253,9 +247,17 @@ bpf_program__attach_tracepoint(struct bpf_program *prog,
|
|||||||
LIBBPF_API struct bpf_link *
|
LIBBPF_API struct bpf_link *
|
||||||
bpf_program__attach_raw_tracepoint(struct bpf_program *prog,
|
bpf_program__attach_raw_tracepoint(struct bpf_program *prog,
|
||||||
const char *tp_name);
|
const char *tp_name);
|
||||||
|
|
||||||
LIBBPF_API struct bpf_link *
|
LIBBPF_API struct bpf_link *
|
||||||
bpf_program__attach_trace(struct bpf_program *prog);
|
bpf_program__attach_trace(struct bpf_program *prog);
|
||||||
|
LIBBPF_API struct bpf_link *
|
||||||
|
bpf_program__attach_lsm(struct bpf_program *prog);
|
||||||
|
LIBBPF_API struct bpf_link *
|
||||||
|
bpf_program__attach_cgroup(struct bpf_program *prog, int cgroup_fd);
|
||||||
|
|
||||||
|
struct bpf_map;
|
||||||
|
|
||||||
|
LIBBPF_API struct bpf_link *bpf_map__attach_struct_ops(struct bpf_map *map);
|
||||||
|
|
||||||
struct bpf_insn;
|
struct bpf_insn;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -327,11 +329,14 @@ LIBBPF_API int bpf_program__set_socket_filter(struct bpf_program *prog);
|
|||||||
LIBBPF_API int bpf_program__set_tracepoint(struct bpf_program *prog);
|
LIBBPF_API int bpf_program__set_tracepoint(struct bpf_program *prog);
|
||||||
LIBBPF_API int bpf_program__set_raw_tracepoint(struct bpf_program *prog);
|
LIBBPF_API int bpf_program__set_raw_tracepoint(struct bpf_program *prog);
|
||||||
LIBBPF_API int bpf_program__set_kprobe(struct bpf_program *prog);
|
LIBBPF_API int bpf_program__set_kprobe(struct bpf_program *prog);
|
||||||
|
LIBBPF_API int bpf_program__set_lsm(struct bpf_program *prog);
|
||||||
LIBBPF_API int bpf_program__set_sched_cls(struct bpf_program *prog);
|
LIBBPF_API int bpf_program__set_sched_cls(struct bpf_program *prog);
|
||||||
LIBBPF_API int bpf_program__set_sched_act(struct bpf_program *prog);
|
LIBBPF_API int bpf_program__set_sched_act(struct bpf_program *prog);
|
||||||
LIBBPF_API int bpf_program__set_xdp(struct bpf_program *prog);
|
LIBBPF_API int bpf_program__set_xdp(struct bpf_program *prog);
|
||||||
LIBBPF_API int bpf_program__set_perf_event(struct bpf_program *prog);
|
LIBBPF_API int bpf_program__set_perf_event(struct bpf_program *prog);
|
||||||
LIBBPF_API int bpf_program__set_tracing(struct bpf_program *prog);
|
LIBBPF_API int bpf_program__set_tracing(struct bpf_program *prog);
|
||||||
|
LIBBPF_API int bpf_program__set_struct_ops(struct bpf_program *prog);
|
||||||
|
LIBBPF_API int bpf_program__set_extension(struct bpf_program *prog);
|
||||||
|
|
||||||
LIBBPF_API enum bpf_prog_type bpf_program__get_type(struct bpf_program *prog);
|
LIBBPF_API enum bpf_prog_type bpf_program__get_type(struct bpf_program *prog);
|
||||||
LIBBPF_API void bpf_program__set_type(struct bpf_program *prog,
|
LIBBPF_API void bpf_program__set_type(struct bpf_program *prog,
|
||||||
@@ -343,15 +348,22 @@ LIBBPF_API void
|
|||||||
bpf_program__set_expected_attach_type(struct bpf_program *prog,
|
bpf_program__set_expected_attach_type(struct bpf_program *prog,
|
||||||
enum bpf_attach_type type);
|
enum bpf_attach_type type);
|
||||||
|
|
||||||
|
LIBBPF_API int
|
||||||
|
bpf_program__set_attach_target(struct bpf_program *prog, int attach_prog_fd,
|
||||||
|
const char *attach_func_name);
|
||||||
|
|
||||||
LIBBPF_API bool bpf_program__is_socket_filter(const struct bpf_program *prog);
|
LIBBPF_API bool bpf_program__is_socket_filter(const struct bpf_program *prog);
|
||||||
LIBBPF_API bool bpf_program__is_tracepoint(const struct bpf_program *prog);
|
LIBBPF_API bool bpf_program__is_tracepoint(const struct bpf_program *prog);
|
||||||
LIBBPF_API bool bpf_program__is_raw_tracepoint(const struct bpf_program *prog);
|
LIBBPF_API bool bpf_program__is_raw_tracepoint(const struct bpf_program *prog);
|
||||||
LIBBPF_API bool bpf_program__is_kprobe(const struct bpf_program *prog);
|
LIBBPF_API bool bpf_program__is_kprobe(const struct bpf_program *prog);
|
||||||
|
LIBBPF_API bool bpf_program__is_lsm(const struct bpf_program *prog);
|
||||||
LIBBPF_API bool bpf_program__is_sched_cls(const struct bpf_program *prog);
|
LIBBPF_API bool bpf_program__is_sched_cls(const struct bpf_program *prog);
|
||||||
LIBBPF_API bool bpf_program__is_sched_act(const struct bpf_program *prog);
|
LIBBPF_API bool bpf_program__is_sched_act(const struct bpf_program *prog);
|
||||||
LIBBPF_API bool bpf_program__is_xdp(const struct bpf_program *prog);
|
LIBBPF_API bool bpf_program__is_xdp(const struct bpf_program *prog);
|
||||||
LIBBPF_API bool bpf_program__is_perf_event(const struct bpf_program *prog);
|
LIBBPF_API bool bpf_program__is_perf_event(const struct bpf_program *prog);
|
||||||
LIBBPF_API bool bpf_program__is_tracing(const struct bpf_program *prog);
|
LIBBPF_API bool bpf_program__is_tracing(const struct bpf_program *prog);
|
||||||
|
LIBBPF_API bool bpf_program__is_struct_ops(const struct bpf_program *prog);
|
||||||
|
LIBBPF_API bool bpf_program__is_extension(const struct bpf_program *prog);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* No need for __attribute__((packed)), all members of 'bpf_map_def'
|
* No need for __attribute__((packed)), all members of 'bpf_map_def'
|
||||||
@@ -371,7 +383,6 @@ struct bpf_map_def {
|
|||||||
* The 'struct bpf_map' in include/linux/bpf.h is internal to the kernel,
|
* The 'struct bpf_map' in include/linux/bpf.h is internal to the kernel,
|
||||||
* so no need to worry about a name clash.
|
* so no need to worry about a name clash.
|
||||||
*/
|
*/
|
||||||
struct bpf_map;
|
|
||||||
LIBBPF_API struct bpf_map *
|
LIBBPF_API struct bpf_map *
|
||||||
bpf_object__find_map_by_name(const struct bpf_object *obj, const char *name);
|
bpf_object__find_map_by_name(const struct bpf_object *obj, const char *name);
|
||||||
|
|
||||||
@@ -406,6 +417,8 @@ typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);
|
|||||||
LIBBPF_API int bpf_map__set_priv(struct bpf_map *map, void *priv,
|
LIBBPF_API int bpf_map__set_priv(struct bpf_map *map, void *priv,
|
||||||
bpf_map_clear_priv_t clear_priv);
|
bpf_map_clear_priv_t clear_priv);
|
||||||
LIBBPF_API void *bpf_map__priv(const struct bpf_map *map);
|
LIBBPF_API void *bpf_map__priv(const struct bpf_map *map);
|
||||||
|
LIBBPF_API int bpf_map__set_initial_value(struct bpf_map *map,
|
||||||
|
const void *data, size_t size);
|
||||||
LIBBPF_API int bpf_map__reuse_fd(struct bpf_map *map, int fd);
|
LIBBPF_API int bpf_map__reuse_fd(struct bpf_map *map, int fd);
|
||||||
LIBBPF_API int bpf_map__resize(struct bpf_map *map, __u32 max_entries);
|
LIBBPF_API int bpf_map__resize(struct bpf_map *map, __u32 max_entries);
|
||||||
LIBBPF_API bool bpf_map__is_offload_neutral(const struct bpf_map *map);
|
LIBBPF_API bool bpf_map__is_offload_neutral(const struct bpf_map *map);
|
||||||
@@ -443,7 +456,15 @@ struct xdp_link_info {
|
|||||||
__u8 attach_mode;
|
__u8 attach_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct bpf_xdp_set_link_opts {
|
||||||
|
size_t sz;
|
||||||
|
int old_fd;
|
||||||
|
};
|
||||||
|
#define bpf_xdp_set_link_opts__last_field old_fd
|
||||||
|
|
||||||
LIBBPF_API int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags);
|
LIBBPF_API int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags);
|
||||||
|
LIBBPF_API int bpf_set_link_xdp_fd_opts(int ifindex, int fd, __u32 flags,
|
||||||
|
const struct bpf_xdp_set_link_opts *opts);
|
||||||
LIBBPF_API int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags);
|
LIBBPF_API int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags);
|
||||||
LIBBPF_API int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info,
|
LIBBPF_API int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info,
|
||||||
size_t info_size, __u32 flags);
|
size_t info_size, __u32 flags);
|
||||||
@@ -512,18 +533,6 @@ bpf_perf_event_read_simple(void *mmap_mem, size_t mmap_size, size_t page_size,
|
|||||||
void **copy_mem, size_t *copy_size,
|
void **copy_mem, size_t *copy_size,
|
||||||
bpf_perf_event_print_t fn, void *private_data);
|
bpf_perf_event_print_t fn, void *private_data);
|
||||||
|
|
||||||
struct nlattr;
|
|
||||||
typedef int (*libbpf_dump_nlmsg_t)(void *cookie, void *msg, struct nlattr **tb);
|
|
||||||
int libbpf_netlink_open(unsigned int *nl_pid);
|
|
||||||
int libbpf_nl_get_link(int sock, unsigned int nl_pid,
|
|
||||||
libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie);
|
|
||||||
int libbpf_nl_get_class(int sock, unsigned int nl_pid, int ifindex,
|
|
||||||
libbpf_dump_nlmsg_t dump_class_nlmsg, void *cookie);
|
|
||||||
int libbpf_nl_get_qdisc(int sock, unsigned int nl_pid, int ifindex,
|
|
||||||
libbpf_dump_nlmsg_t dump_qdisc_nlmsg, void *cookie);
|
|
||||||
int libbpf_nl_get_filter(int sock, unsigned int nl_pid, int ifindex, int handle,
|
|
||||||
libbpf_dump_nlmsg_t dump_filter_nlmsg, void *cookie);
|
|
||||||
|
|
||||||
struct bpf_prog_linfo;
|
struct bpf_prog_linfo;
|
||||||
struct bpf_prog_info;
|
struct bpf_prog_info;
|
||||||
|
|
||||||
@@ -550,6 +559,7 @@ LIBBPF_API bool bpf_probe_prog_type(enum bpf_prog_type prog_type,
|
|||||||
LIBBPF_API bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex);
|
LIBBPF_API bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex);
|
||||||
LIBBPF_API bool bpf_probe_helper(enum bpf_func_id id,
|
LIBBPF_API bool bpf_probe_helper(enum bpf_func_id id,
|
||||||
enum bpf_prog_type prog_type, __u32 ifindex);
|
enum bpf_prog_type prog_type, __u32 ifindex);
|
||||||
|
LIBBPF_API bool bpf_probe_large_insn_limit(__u32 ifindex);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get bpf_prog_info in continuous memory
|
* Get bpf_prog_info in continuous memory
|
||||||
@@ -630,6 +640,50 @@ bpf_program__bpil_offs_to_addr(struct bpf_prog_info_linear *info_linear);
|
|||||||
*/
|
*/
|
||||||
LIBBPF_API int libbpf_num_possible_cpus(void);
|
LIBBPF_API int libbpf_num_possible_cpus(void);
|
||||||
|
|
||||||
|
struct bpf_map_skeleton {
|
||||||
|
const char *name;
|
||||||
|
struct bpf_map **map;
|
||||||
|
void **mmaped;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bpf_prog_skeleton {
|
||||||
|
const char *name;
|
||||||
|
struct bpf_program **prog;
|
||||||
|
struct bpf_link **link;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bpf_object_skeleton {
|
||||||
|
size_t sz; /* size of this struct, for forward/backward compatibility */
|
||||||
|
|
||||||
|
const char *name;
|
||||||
|
void *data;
|
||||||
|
size_t data_sz;
|
||||||
|
|
||||||
|
struct bpf_object **obj;
|
||||||
|
|
||||||
|
int map_cnt;
|
||||||
|
int map_skel_sz; /* sizeof(struct bpf_skeleton_map) */
|
||||||
|
struct bpf_map_skeleton *maps;
|
||||||
|
|
||||||
|
int prog_cnt;
|
||||||
|
int prog_skel_sz; /* sizeof(struct bpf_skeleton_prog) */
|
||||||
|
struct bpf_prog_skeleton *progs;
|
||||||
|
};
|
||||||
|
|
||||||
|
LIBBPF_API int
|
||||||
|
bpf_object__open_skeleton(struct bpf_object_skeleton *s,
|
||||||
|
const struct bpf_object_open_opts *opts);
|
||||||
|
LIBBPF_API int bpf_object__load_skeleton(struct bpf_object_skeleton *s);
|
||||||
|
LIBBPF_API int bpf_object__attach_skeleton(struct bpf_object_skeleton *s);
|
||||||
|
LIBBPF_API void bpf_object__detach_skeleton(struct bpf_object_skeleton *s);
|
||||||
|
LIBBPF_API void bpf_object__destroy_skeleton(struct bpf_object_skeleton *s);
|
||||||
|
|
||||||
|
enum libbpf_tristate {
|
||||||
|
TRI_NO = 0,
|
||||||
|
TRI_YES = 1,
|
||||||
|
TRI_MODULE = 2,
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -208,3 +208,49 @@ LIBBPF_0.0.6 {
|
|||||||
btf__find_by_name_kind;
|
btf__find_by_name_kind;
|
||||||
libbpf_find_vmlinux_btf_id;
|
libbpf_find_vmlinux_btf_id;
|
||||||
} LIBBPF_0.0.5;
|
} LIBBPF_0.0.5;
|
||||||
|
|
||||||
|
LIBBPF_0.0.7 {
|
||||||
|
global:
|
||||||
|
btf_dump__emit_type_decl;
|
||||||
|
bpf_link__disconnect;
|
||||||
|
bpf_map__attach_struct_ops;
|
||||||
|
bpf_map_delete_batch;
|
||||||
|
bpf_map_lookup_and_delete_batch;
|
||||||
|
bpf_map_lookup_batch;
|
||||||
|
bpf_map_update_batch;
|
||||||
|
bpf_object__find_program_by_name;
|
||||||
|
bpf_object__attach_skeleton;
|
||||||
|
bpf_object__destroy_skeleton;
|
||||||
|
bpf_object__detach_skeleton;
|
||||||
|
bpf_object__load_skeleton;
|
||||||
|
bpf_object__open_skeleton;
|
||||||
|
bpf_probe_large_insn_limit;
|
||||||
|
bpf_prog_attach_xattr;
|
||||||
|
bpf_program__attach;
|
||||||
|
bpf_program__name;
|
||||||
|
bpf_program__is_extension;
|
||||||
|
bpf_program__is_struct_ops;
|
||||||
|
bpf_program__set_extension;
|
||||||
|
bpf_program__set_struct_ops;
|
||||||
|
btf__align_of;
|
||||||
|
libbpf_find_kernel_btf;
|
||||||
|
} LIBBPF_0.0.6;
|
||||||
|
|
||||||
|
LIBBPF_0.0.8 {
|
||||||
|
global:
|
||||||
|
bpf_link__fd;
|
||||||
|
bpf_link__open;
|
||||||
|
bpf_link__pin;
|
||||||
|
bpf_link__pin_path;
|
||||||
|
bpf_link__unpin;
|
||||||
|
bpf_link__update_program;
|
||||||
|
bpf_link_create;
|
||||||
|
bpf_link_update;
|
||||||
|
bpf_map__set_initial_value;
|
||||||
|
bpf_program__attach_cgroup;
|
||||||
|
bpf_program__attach_lsm;
|
||||||
|
bpf_program__is_lsm;
|
||||||
|
bpf_program__set_attach_target;
|
||||||
|
bpf_program__set_lsm;
|
||||||
|
bpf_set_link_xdp_fd_opts;
|
||||||
|
} LIBBPF_0.0.7;
|
||||||
|
|||||||
@@ -8,5 +8,5 @@ Name: libbpf
|
|||||||
Description: BPF library
|
Description: BPF library
|
||||||
Version: @VERSION@
|
Version: @VERSION@
|
||||||
Libs: -L${libdir} -lbpf
|
Libs: -L${libdir} -lbpf
|
||||||
Requires.private: libelf
|
Requires.private: libelf zlib
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|||||||
40
src/libbpf_common.h
Normal file
40
src/libbpf_common.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Common user-facing libbpf helpers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Facebook
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIBBPF_LIBBPF_COMMON_H
|
||||||
|
#define __LIBBPF_LIBBPF_COMMON_H
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef LIBBPF_API
|
||||||
|
#define LIBBPF_API __attribute__((visibility("default")))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Helper macro to declare and initialize libbpf options struct
|
||||||
|
*
|
||||||
|
* This dance with uninitialized declaration, followed by memset to zero,
|
||||||
|
* followed by assignment using compound literal syntax is done to preserve
|
||||||
|
* ability to use a nice struct field initialization syntax and **hopefully**
|
||||||
|
* have all the padding bytes initialized to zero. It's not guaranteed though,
|
||||||
|
* when copying literal, that compiler won't copy garbage in literal's padding
|
||||||
|
* bytes, but that's the best way I've found and it seems to work in practice.
|
||||||
|
*
|
||||||
|
* Macro declares opts struct of given type and name, zero-initializes,
|
||||||
|
* including any extra padding, it with memset() and then assigns initial
|
||||||
|
* values provided by users in struct initializer-syntax as varargs.
|
||||||
|
*/
|
||||||
|
#define DECLARE_LIBBPF_OPTS(TYPE, NAME, ...) \
|
||||||
|
struct TYPE NAME = ({ \
|
||||||
|
memset(&NAME, 0, sizeof(struct TYPE)); \
|
||||||
|
(struct TYPE) { \
|
||||||
|
.sz = sizeof(struct TYPE), \
|
||||||
|
__VA_ARGS__ \
|
||||||
|
}; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#endif /* __LIBBPF_LIBBPF_COMMON_H */
|
||||||
@@ -13,6 +13,9 @@
|
|||||||
|
|
||||||
#include "libbpf.h"
|
#include "libbpf.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 ERRNO_OFFSET(e) ((e) - __LIBBPF_ERRNO__START)
|
||||||
#define ERRCODE_OFFSET(c) ERRNO_OFFSET(LIBBPF_ERRNO__##c)
|
#define ERRCODE_OFFSET(c) ERRNO_OFFSET(LIBBPF_ERRNO__##c)
|
||||||
#define NR_ERRNO (__LIBBPF_ERRNO__END - __LIBBPF_ERRNO__START)
|
#define NR_ERRNO (__LIBBPF_ERRNO__END - __LIBBPF_ERRNO__START)
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ static inline bool libbpf_validate_opts(const char *opts,
|
|||||||
|
|
||||||
for (i = opts_sz; i < user_sz; i++) {
|
for (i = opts_sz; i < user_sz; i++) {
|
||||||
if (opts[i]) {
|
if (opts[i]) {
|
||||||
pr_warn("%s has non-zero extra bytes",
|
pr_warn("%s has non-zero extra bytes\n",
|
||||||
type_name);
|
type_name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -95,9 +95,28 @@ static inline bool libbpf_validate_opts(const char *opts,
|
|||||||
#define OPTS_GET(opts, field, fallback_value) \
|
#define OPTS_GET(opts, field, fallback_value) \
|
||||||
(OPTS_HAS(opts, field) ? (opts)->field : fallback_value)
|
(OPTS_HAS(opts, field) ? (opts)->field : fallback_value)
|
||||||
|
|
||||||
|
int parse_cpu_mask_str(const char *s, bool **mask, int *mask_sz);
|
||||||
|
int parse_cpu_mask_file(const char *fcpu, bool **mask, int *mask_sz);
|
||||||
int libbpf__load_raw_btf(const char *raw_types, size_t types_len,
|
int libbpf__load_raw_btf(const char *raw_types, size_t types_len,
|
||||||
const char *str_sec, size_t str_len);
|
const char *str_sec, size_t str_len);
|
||||||
|
|
||||||
|
int bpf_object__section_size(const struct bpf_object *obj, const char *name,
|
||||||
|
__u32 *size);
|
||||||
|
int bpf_object__variable_offset(const struct bpf_object *obj, const char *name,
|
||||||
|
__u32 *off);
|
||||||
|
|
||||||
|
struct nlattr;
|
||||||
|
typedef int (*libbpf_dump_nlmsg_t)(void *cookie, void *msg, struct nlattr **tb);
|
||||||
|
int libbpf_netlink_open(unsigned int *nl_pid);
|
||||||
|
int libbpf_nl_get_link(int sock, unsigned int nl_pid,
|
||||||
|
libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie);
|
||||||
|
int libbpf_nl_get_class(int sock, unsigned int nl_pid, int ifindex,
|
||||||
|
libbpf_dump_nlmsg_t dump_class_nlmsg, void *cookie);
|
||||||
|
int libbpf_nl_get_qdisc(int sock, unsigned int nl_pid, int ifindex,
|
||||||
|
libbpf_dump_nlmsg_t dump_qdisc_nlmsg, void *cookie);
|
||||||
|
int libbpf_nl_get_filter(int sock, unsigned int nl_pid, int ifindex, int handle,
|
||||||
|
libbpf_dump_nlmsg_t dump_filter_nlmsg, void *cookie);
|
||||||
|
|
||||||
struct btf_ext_info {
|
struct btf_ext_info {
|
||||||
/*
|
/*
|
||||||
* info points to the individual info section (e.g. func_info and
|
* info points to the individual info section (e.g. func_info and
|
||||||
|
|||||||
@@ -17,6 +17,9 @@
|
|||||||
#include "libbpf.h"
|
#include "libbpf.h"
|
||||||
#include "libbpf_internal.h"
|
#include "libbpf_internal.h"
|
||||||
|
|
||||||
|
/* make sure libbpf doesn't use kernel-only integer typedefs */
|
||||||
|
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
|
||||||
|
|
||||||
static bool grep(const char *buffer, const char *pattern)
|
static bool grep(const char *buffer, const char *pattern)
|
||||||
{
|
{
|
||||||
return !!strstr(buffer, pattern);
|
return !!strstr(buffer, pattern);
|
||||||
@@ -103,6 +106,9 @@ probe_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns,
|
|||||||
case BPF_PROG_TYPE_CGROUP_SYSCTL:
|
case BPF_PROG_TYPE_CGROUP_SYSCTL:
|
||||||
case BPF_PROG_TYPE_CGROUP_SOCKOPT:
|
case BPF_PROG_TYPE_CGROUP_SOCKOPT:
|
||||||
case BPF_PROG_TYPE_TRACING:
|
case BPF_PROG_TYPE_TRACING:
|
||||||
|
case BPF_PROG_TYPE_STRUCT_OPS:
|
||||||
|
case BPF_PROG_TYPE_EXT:
|
||||||
|
case BPF_PROG_TYPE_LSM:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -251,6 +257,7 @@ bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex)
|
|||||||
case BPF_MAP_TYPE_XSKMAP:
|
case BPF_MAP_TYPE_XSKMAP:
|
||||||
case BPF_MAP_TYPE_SOCKHASH:
|
case BPF_MAP_TYPE_SOCKHASH:
|
||||||
case BPF_MAP_TYPE_REUSEPORT_SOCKARRAY:
|
case BPF_MAP_TYPE_REUSEPORT_SOCKARRAY:
|
||||||
|
case BPF_MAP_TYPE_STRUCT_OPS:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -321,3 +328,24 @@ bool bpf_probe_helper(enum bpf_func_id id, enum bpf_prog_type prog_type,
|
|||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Probe for availability of kernel commit (5.3):
|
||||||
|
*
|
||||||
|
* c04c0d2b968a ("bpf: increase complexity limit and maximum program size")
|
||||||
|
*/
|
||||||
|
bool bpf_probe_large_insn_limit(__u32 ifindex)
|
||||||
|
{
|
||||||
|
struct bpf_insn insns[BPF_MAXINSNS + 1];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < BPF_MAXINSNS; i++)
|
||||||
|
insns[i] = BPF_MOV64_IMM(BPF_REG_0, 1);
|
||||||
|
insns[BPF_MAXINSNS] = BPF_EXIT_INSN();
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
probe_load(BPF_PROG_TYPE_SCHED_CLS, insns, ARRAY_SIZE(insns), NULL, 0,
|
||||||
|
ifindex);
|
||||||
|
|
||||||
|
return errno != E2BIG && errno != EINVAL;
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,6 +15,9 @@
|
|||||||
#include "libbpf_internal.h"
|
#include "libbpf_internal.h"
|
||||||
#include "nlattr.h"
|
#include "nlattr.h"
|
||||||
|
|
||||||
|
/* make sure libbpf doesn't use kernel-only integer typedefs */
|
||||||
|
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
|
||||||
|
|
||||||
#ifndef SOL_NETLINK
|
#ifndef SOL_NETLINK
|
||||||
#define SOL_NETLINK 270
|
#define SOL_NETLINK 270
|
||||||
#endif
|
#endif
|
||||||
@@ -129,7 +132,8 @@ done:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
|
static int __bpf_set_link_xdp_fd_replace(int ifindex, int fd, int old_fd,
|
||||||
|
__u32 flags)
|
||||||
{
|
{
|
||||||
int sock, seq = 0, ret;
|
int sock, seq = 0, ret;
|
||||||
struct nlattr *nla, *nla_xdp;
|
struct nlattr *nla, *nla_xdp;
|
||||||
@@ -138,7 +142,7 @@ int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
|
|||||||
struct ifinfomsg ifinfo;
|
struct ifinfomsg ifinfo;
|
||||||
char attrbuf[64];
|
char attrbuf[64];
|
||||||
} req;
|
} req;
|
||||||
__u32 nl_pid;
|
__u32 nl_pid = 0;
|
||||||
|
|
||||||
sock = libbpf_netlink_open(&nl_pid);
|
sock = libbpf_netlink_open(&nl_pid);
|
||||||
if (sock < 0)
|
if (sock < 0)
|
||||||
@@ -175,6 +179,14 @@ int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
|
|||||||
nla->nla_len += nla_xdp->nla_len;
|
nla->nla_len += nla_xdp->nla_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & XDP_FLAGS_REPLACE) {
|
||||||
|
nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
|
||||||
|
nla_xdp->nla_type = IFLA_XDP_EXPECTED_FD;
|
||||||
|
nla_xdp->nla_len = NLA_HDRLEN + sizeof(old_fd);
|
||||||
|
memcpy((char *)nla_xdp + NLA_HDRLEN, &old_fd, sizeof(old_fd));
|
||||||
|
nla->nla_len += nla_xdp->nla_len;
|
||||||
|
}
|
||||||
|
|
||||||
req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);
|
req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);
|
||||||
|
|
||||||
if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
|
if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
|
||||||
@@ -188,6 +200,29 @@ cleanup:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bpf_set_link_xdp_fd_opts(int ifindex, int fd, __u32 flags,
|
||||||
|
const struct bpf_xdp_set_link_opts *opts)
|
||||||
|
{
|
||||||
|
int old_fd = -1;
|
||||||
|
|
||||||
|
if (!OPTS_VALID(opts, bpf_xdp_set_link_opts))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (OPTS_HAS(opts, old_fd)) {
|
||||||
|
old_fd = OPTS_GET(opts, old_fd, -1);
|
||||||
|
flags |= XDP_FLAGS_REPLACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return __bpf_set_link_xdp_fd_replace(ifindex, fd,
|
||||||
|
old_fd,
|
||||||
|
flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
|
||||||
|
{
|
||||||
|
return __bpf_set_link_xdp_fd_replace(ifindex, fd, 0, flags);
|
||||||
|
}
|
||||||
|
|
||||||
static int __dump_link_nlmsg(struct nlmsghdr *nlh,
|
static int __dump_link_nlmsg(struct nlmsghdr *nlh,
|
||||||
libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie)
|
libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie)
|
||||||
{
|
{
|
||||||
@@ -253,7 +288,7 @@ int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info,
|
|||||||
{
|
{
|
||||||
struct xdp_id_md xdp_id = {};
|
struct xdp_id_md xdp_id = {};
|
||||||
int sock, ret;
|
int sock, ret;
|
||||||
__u32 nl_pid;
|
__u32 nl_pid = 0;
|
||||||
__u32 mask;
|
__u32 mask;
|
||||||
|
|
||||||
if (flags & ~XDP_FLAGS_MASK || !info_size)
|
if (flags & ~XDP_FLAGS_MASK || !info_size)
|
||||||
@@ -286,7 +321,7 @@ int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info,
|
|||||||
|
|
||||||
static __u32 get_xdp_id(struct xdp_link_info *info, __u32 flags)
|
static __u32 get_xdp_id(struct xdp_link_info *info, __u32 flags)
|
||||||
{
|
{
|
||||||
if (info->attach_mode != XDP_ATTACHED_MULTI)
|
if (info->attach_mode != XDP_ATTACHED_MULTI && !flags)
|
||||||
return info->prog_id;
|
return info->prog_id;
|
||||||
if (flags & XDP_FLAGS_DRV_MODE)
|
if (flags & XDP_FLAGS_DRV_MODE)
|
||||||
return info->drv_prog_id;
|
return info->drv_prog_id;
|
||||||
|
|||||||
@@ -13,6 +13,9 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* make sure libbpf doesn't use kernel-only integer typedefs */
|
||||||
|
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
|
||||||
|
|
||||||
static uint16_t nla_attr_minlen[LIBBPF_NLA_TYPE_MAX+1] = {
|
static uint16_t nla_attr_minlen[LIBBPF_NLA_TYPE_MAX+1] = {
|
||||||
[LIBBPF_NLA_U8] = sizeof(uint8_t),
|
[LIBBPF_NLA_U8] = sizeof(uint8_t),
|
||||||
[LIBBPF_NLA_U16] = sizeof(uint16_t),
|
[LIBBPF_NLA_U16] = sizeof(uint16_t),
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "str_error.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
|
* 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
|
* libc, while checking strerror_r() return to avoid having to check this in
|
||||||
|
|||||||
19
src/xsk.c
19
src/xsk.c
@@ -32,6 +32,9 @@
|
|||||||
#include "libbpf_internal.h"
|
#include "libbpf_internal.h"
|
||||||
#include "xsk.h"
|
#include "xsk.h"
|
||||||
|
|
||||||
|
/* make sure libbpf doesn't use kernel-only integer typedefs */
|
||||||
|
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
|
||||||
|
|
||||||
#ifndef SOL_XDP
|
#ifndef SOL_XDP
|
||||||
#define SOL_XDP 283
|
#define SOL_XDP 283
|
||||||
#endif
|
#endif
|
||||||
@@ -277,7 +280,11 @@ int xsk_umem__create_v0_0_4(struct xsk_umem **umem_ptr, void *umem_area,
|
|||||||
fill->consumer = map + off.fr.consumer;
|
fill->consumer = map + off.fr.consumer;
|
||||||
fill->flags = map + off.fr.flags;
|
fill->flags = map + off.fr.flags;
|
||||||
fill->ring = map + off.fr.desc;
|
fill->ring = map + off.fr.desc;
|
||||||
fill->cached_cons = umem->config.fill_size;
|
fill->cached_prod = *fill->producer;
|
||||||
|
/* cached_cons is "size" bigger than the real consumer pointer
|
||||||
|
* See xsk_prod_nb_free
|
||||||
|
*/
|
||||||
|
fill->cached_cons = *fill->consumer + umem->config.fill_size;
|
||||||
|
|
||||||
map = mmap(NULL, off.cr.desc + umem->config.comp_size * sizeof(__u64),
|
map = mmap(NULL, off.cr.desc + umem->config.comp_size * sizeof(__u64),
|
||||||
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, umem->fd,
|
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, umem->fd,
|
||||||
@@ -294,6 +301,8 @@ int xsk_umem__create_v0_0_4(struct xsk_umem **umem_ptr, void *umem_area,
|
|||||||
comp->consumer = map + off.cr.consumer;
|
comp->consumer = map + off.cr.consumer;
|
||||||
comp->flags = map + off.cr.flags;
|
comp->flags = map + off.cr.flags;
|
||||||
comp->ring = map + off.cr.desc;
|
comp->ring = map + off.cr.desc;
|
||||||
|
comp->cached_prod = *comp->producer;
|
||||||
|
comp->cached_cons = *comp->consumer;
|
||||||
|
|
||||||
*umem_ptr = umem;
|
*umem_ptr = umem;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -669,6 +678,8 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
|
|||||||
rx->consumer = rx_map + off.rx.consumer;
|
rx->consumer = rx_map + off.rx.consumer;
|
||||||
rx->flags = rx_map + off.rx.flags;
|
rx->flags = rx_map + off.rx.flags;
|
||||||
rx->ring = rx_map + off.rx.desc;
|
rx->ring = rx_map + off.rx.desc;
|
||||||
|
rx->cached_prod = *rx->producer;
|
||||||
|
rx->cached_cons = *rx->consumer;
|
||||||
}
|
}
|
||||||
xsk->rx = rx;
|
xsk->rx = rx;
|
||||||
|
|
||||||
@@ -688,7 +699,11 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
|
|||||||
tx->consumer = tx_map + off.tx.consumer;
|
tx->consumer = tx_map + off.tx.consumer;
|
||||||
tx->flags = tx_map + off.tx.flags;
|
tx->flags = tx_map + off.tx.flags;
|
||||||
tx->ring = tx_map + off.tx.desc;
|
tx->ring = tx_map + off.tx.desc;
|
||||||
tx->cached_cons = xsk->config.tx_size;
|
tx->cached_prod = *tx->producer;
|
||||||
|
/* cached_cons is r->size bigger than the real consumer pointer
|
||||||
|
* See xsk_prod_nb_free
|
||||||
|
*/
|
||||||
|
tx->cached_cons = *tx->consumer + xsk->config.tx_size;
|
||||||
}
|
}
|
||||||
xsk->tx = tx;
|
xsk->tx = tx;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
PHASES=(${@:-SETUP RUN RUN_ASAN CLEANUP})
|
PHASES=(${@:-SETUP RUN RUN_ASAN CLEANUP})
|
||||||
DEBIAN_RELEASE="${DEBIAN_RELEASE:-testing}"
|
DEBIAN_RELEASE="${DEBIAN_RELEASE:-testing}"
|
||||||
CONT_NAME="${CONT_NAME:-debian-$DEBIAN_RELEASE-$RANDOM}"
|
CONT_NAME="${CONT_NAME:-libbpf-debian-$DEBIAN_RELEASE}"
|
||||||
ENV_VARS="${ENV_VARS:-}"
|
ENV_VARS="${ENV_VARS:-}"
|
||||||
DOCKER_RUN="${DOCKER_RUN:-docker run}"
|
DOCKER_RUN="${DOCKER_RUN:-docker run}"
|
||||||
REPO_ROOT="${REPO_ROOT:-$PWD}"
|
REPO_ROOT="${REPO_ROOT:-$PWD}"
|
||||||
@@ -30,6 +30,10 @@ for phase in "${PHASES[@]}"; do
|
|||||||
SETUP)
|
SETUP)
|
||||||
info "Setup phase"
|
info "Setup phase"
|
||||||
info "Using Debian $DEBIAN_RELEASE"
|
info "Using Debian $DEBIAN_RELEASE"
|
||||||
|
|
||||||
|
sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
|
||||||
|
docker --version
|
||||||
|
|
||||||
docker pull debian:$DEBIAN_RELEASE
|
docker pull debian:$DEBIAN_RELEASE
|
||||||
info "Starting container $CONT_NAME"
|
info "Starting container $CONT_NAME"
|
||||||
$DOCKER_RUN -v $REPO_ROOT:/build:rw \
|
$DOCKER_RUN -v $REPO_ROOT:/build:rw \
|
||||||
@@ -57,7 +61,7 @@ for phase in "${PHASES[@]}"; do
|
|||||||
docker_exec mkdir build install
|
docker_exec mkdir build install
|
||||||
docker_exec ${CC:-cc} --version
|
docker_exec ${CC:-cc} --version
|
||||||
info "build"
|
info "build"
|
||||||
docker_exec make CFLAGS="${CFLAGS}" -C ./src -B OBJDIR=../build
|
docker_exec make -j$((4*$(nproc))) CFLAGS="${CFLAGS}" -C ./src -B OBJDIR=../build
|
||||||
info "ldd build/libbpf.so:"
|
info "ldd build/libbpf.so:"
|
||||||
docker_exec ldd build/libbpf.so
|
docker_exec ldd build/libbpf.so
|
||||||
if ! docker_exec ldd build/libbpf.so | grep -q libelf; then
|
if ! docker_exec ldd build/libbpf.so | grep -q libelf; then
|
||||||
@@ -65,7 +69,7 @@ for phase in "${PHASES[@]}"; do
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
info "install"
|
info "install"
|
||||||
docker_exec make -C src OBJDIR=../build DESTDIR=../install install
|
docker_exec make -j$((4*$(nproc))) -C src OBJDIR=../build DESTDIR=../install install
|
||||||
docker_exec rm -rf build install
|
docker_exec rm -rf build install
|
||||||
;;
|
;;
|
||||||
CLEANUP)
|
CLEANUP)
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ cd $REPO_ROOT
|
|||||||
CFLAGS="-g -O2 -Werror -Wall -fsanitize=address,undefined"
|
CFLAGS="-g -O2 -Werror -Wall -fsanitize=address,undefined"
|
||||||
mkdir build install
|
mkdir build install
|
||||||
cc --version
|
cc --version
|
||||||
make CFLAGS="${CFLAGS}" -C ./src -B OBJDIR=../build
|
make -j$((4*$(nproc))) CFLAGS="${CFLAGS}" -C ./src -B OBJDIR=../build
|
||||||
ldd build/libbpf.so
|
ldd build/libbpf.so
|
||||||
if ! ldd build/libbpf.so | grep -q libelf; then
|
if ! ldd build/libbpf.so | grep -q libelf; then
|
||||||
echo "FAIL: No reference to libelf.so in libbpf.so!"
|
echo "FAIL: No reference to libelf.so in libbpf.so!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
make -C src OBJDIR=../build DESTDIR=../install install
|
make -j$((4*$(nproc))) -C src OBJDIR=../build DESTDIR=../install install
|
||||||
rm -rf build install
|
rm -rf build install
|
||||||
|
|||||||
25
travis-ci/vmtest/build_pahole.sh
Executable file
25
travis-ci/vmtest/build_pahole.sh
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
CWD=$(pwd)
|
||||||
|
REPO_PATH=$1
|
||||||
|
PAHOLE_ORIGIN=https://git.kernel.org/pub/scm/devel/pahole/pahole.git
|
||||||
|
|
||||||
|
mkdir -p ${REPO_PATH}
|
||||||
|
cd ${REPO_PATH}
|
||||||
|
git init
|
||||||
|
git remote add origin ${PAHOLE_ORIGIN}
|
||||||
|
git fetch origin
|
||||||
|
git checkout master
|
||||||
|
|
||||||
|
mkdir -p build
|
||||||
|
cd build
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -D__LIB=lib ..
|
||||||
|
make -j$((4*$(nproc))) all
|
||||||
|
sudo make install
|
||||||
|
|
||||||
|
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH:-}:/usr/local/lib
|
||||||
|
ldd $(which pahole)
|
||||||
|
pahole --version
|
||||||
|
|
||||||
25
travis-ci/vmtest/build_selftests.sh
Executable file
25
travis-ci/vmtest/build_selftests.sh
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
LLVM_VER=11
|
||||||
|
LIBBPF_PATH="${REPO_ROOT}"
|
||||||
|
REPO_PATH="travis-ci/vmtest/bpf-next"
|
||||||
|
|
||||||
|
# temporary work-around for failing tests
|
||||||
|
rm "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c"
|
||||||
|
|
||||||
|
make \
|
||||||
|
CLANG=clang-${LLVM_VER} \
|
||||||
|
LLC=llc-${LLVM_VER} \
|
||||||
|
LLVM_STRIP=llvm-strip-${LLVM_VER} \
|
||||||
|
VMLINUX_BTF="${VMLINUX_BTF}" \
|
||||||
|
-C "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" \
|
||||||
|
-j $((4*$(nproc)))
|
||||||
|
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
|
||||||
|
|
||||||
|
blacklist_path="${VMTEST_ROOT}/configs/blacklist"
|
||||||
|
git add "${blacklist_path}"
|
||||||
24
travis-ci/vmtest/checkout_latest_kernel.sh
Executable file
24
travis-ci/vmtest/checkout_latest_kernel.sh
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
CWD=$(pwd)
|
||||||
|
LIBBPF_PATH=$(pwd)
|
||||||
|
REPO_PATH=$1
|
||||||
|
|
||||||
|
BPF_NEXT_ORIGIN=https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git
|
||||||
|
LINUX_SHA=$(cat ${LIBBPF_PATH}/CHECKPOINT-COMMIT)
|
||||||
|
|
||||||
|
echo REPO_PATH = ${REPO_PATH}
|
||||||
|
echo LINUX_SHA = ${LINUX_SHA}
|
||||||
|
|
||||||
|
if [ ! -d "${REPO_PATH}" ]; then
|
||||||
|
mkdir -p ${REPO_PATH}
|
||||||
|
cd ${REPO_PATH}
|
||||||
|
git init
|
||||||
|
git remote add bpf-next ${BPF_NEXT_ORIGIN}
|
||||||
|
for depth in 32 64 128; do
|
||||||
|
git fetch --depth ${depth} bpf-next
|
||||||
|
git reset --hard ${LINUX_SHA} && break
|
||||||
|
done
|
||||||
|
fi
|
||||||
6
travis-ci/vmtest/configs/INDEX
Normal file
6
travis-ci/vmtest/configs/INDEX
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
INDEX https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/INDEX
|
||||||
|
libbpf-vmtest-rootfs-2020.03.11.tar.zst https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/libbpf-vmtest-rootfs-2020.03.11.tar.zst
|
||||||
|
vmlinux-5.5.0-rc6.zst https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinux-5.5.0-rc6.zst
|
||||||
|
vmlinux-5.5.0.zst https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinux-5.5.0.zst
|
||||||
|
vmlinuz-5.5.0-rc6 https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinuz-5.5.0-rc6
|
||||||
|
vmlinuz-5.5.0 https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinuz-5.5.0
|
||||||
27
travis-ci/vmtest/configs/blacklist/BLACKLIST-5.5.0
Normal file
27
travis-ci/vmtest/configs/blacklist/BLACKLIST-5.5.0
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# PERMANENTLY DISABLED
|
||||||
|
bpf_tcp_ca # STRUCT_OPS is missing
|
||||||
|
cgroup_attach_multi # BPF_F_REPLACE_PROG missing
|
||||||
|
cgroup_link # LINK_CREATE is missing
|
||||||
|
fentry_fexit # bpf_prog_test_tracing missing
|
||||||
|
fentry_test # bpf_prog_test_tracing missing
|
||||||
|
fexit_bpf2bpf # freplace is missing
|
||||||
|
fexit_test # bpf_prog_test_tracing missing
|
||||||
|
get_stack_raw_tp # exercising BPF verifier bug causing infinite loop
|
||||||
|
link_pinning # bpf_link is missing
|
||||||
|
mmap # 5.5 kernel is too permissive with re-mmaping
|
||||||
|
modify_return # fmod_ret is missing
|
||||||
|
ns_current_pid_tgid # bpf_get_ns_current_pid_tgid() helper is missing
|
||||||
|
perf_branches # bpf_read_branch_records() helper is missing
|
||||||
|
select_reuseport # UDP support is missing
|
||||||
|
sk_assign # bpf_sk_assign helper missing
|
||||||
|
sockmap_listen # no listen socket supportin SOCKMAP
|
||||||
|
skb_ctx # ctx_{size, }_{in, out} in BPF_PROG_TEST_RUN is missing
|
||||||
|
test_global_funcs # kernel doesn't support BTF linkage=global on FUNCs
|
||||||
|
test_lsm # no BPF_LSM support
|
||||||
|
vmlinux # hrtimer_nanosleep() signature changed incompatibly
|
||||||
|
xdp_attach # IFLA_XDP_EXPECTED_FD support is missing
|
||||||
|
xdp_bpf2bpf # freplace is missing
|
||||||
|
|
||||||
|
|
||||||
|
# TEMPORARILY DISABLED
|
||||||
|
send_signal # flaky
|
||||||
4
travis-ci/vmtest/configs/blacklist/BLACKLIST-latest
Normal file
4
travis-ci/vmtest/configs/blacklist/BLACKLIST-latest
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# TEMPORARILY DISABLED
|
||||||
|
send_signal # flaky
|
||||||
|
test_lsm # semi-working
|
||||||
|
sk_assign # needs better setup in Travis CI
|
||||||
3001
travis-ci/vmtest/configs/latest.config
Normal file
3001
travis-ci/vmtest/configs/latest.config
Normal file
File diff suppressed because it is too large
Load Diff
148
travis-ci/vmtest/mkrootfs.sh
Executable file
148
travis-ci/vmtest/mkrootfs.sh
Executable file
@@ -0,0 +1,148 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# This script is based on drgn script for generating Arch Linux bootstrap
|
||||||
|
# images.
|
||||||
|
# https://github.com/osandov/drgn/blob/master/scripts/vmtest/mkrootfs.sh
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
usage () {
|
||||||
|
USAGE_STRING="usage: $0 [NAME]
|
||||||
|
$0 -h
|
||||||
|
|
||||||
|
Build an Arch Linux root filesystem image for testing libbpf in a virtual
|
||||||
|
machine.
|
||||||
|
|
||||||
|
The image is generated as a zstd-compressed tarball.
|
||||||
|
|
||||||
|
This must be run as root, as most of the installation is done in a chroot.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
NAME name of generated image file (default:
|
||||||
|
libbpf-vmtest-rootfs-\$DATE.tar.zst)
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h display this help message and exit"
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
out)
|
||||||
|
echo "$USAGE_STRING"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
err)
|
||||||
|
echo "$USAGE_STRING" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
while getopts "h" OPT; do
|
||||||
|
case "$OPT" in
|
||||||
|
h)
|
||||||
|
usage out
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage err
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
if [[ $OPTIND -eq $# ]]; then
|
||||||
|
NAME="${!OPTIND}"
|
||||||
|
elif [[ $OPTIND -gt $# ]]; then
|
||||||
|
NAME="libbpf-vmtest-rootfs-$(date +%Y.%m.%d).tar.zst"
|
||||||
|
else
|
||||||
|
usage err
|
||||||
|
fi
|
||||||
|
|
||||||
|
pacman_conf=
|
||||||
|
root=
|
||||||
|
trap 'rm -rf "$pacman_conf" "$root"' EXIT
|
||||||
|
pacman_conf="$(mktemp -p "$PWD")"
|
||||||
|
cat > "$pacman_conf" << "EOF"
|
||||||
|
[options]
|
||||||
|
Architecture = x86_64
|
||||||
|
CheckSpace
|
||||||
|
SigLevel = Required DatabaseOptional
|
||||||
|
[core]
|
||||||
|
Include = /etc/pacman.d/mirrorlist
|
||||||
|
[extra]
|
||||||
|
Include = /etc/pacman.d/mirrorlist
|
||||||
|
[community]
|
||||||
|
Include = /etc/pacman.d/mirrorlist
|
||||||
|
EOF
|
||||||
|
root="$(mktemp -d -p "$PWD")"
|
||||||
|
|
||||||
|
packages=(
|
||||||
|
busybox
|
||||||
|
# libbpf dependencies.
|
||||||
|
libelf
|
||||||
|
zlib
|
||||||
|
# selftests test_progs dependencies.
|
||||||
|
binutils
|
||||||
|
elfutils
|
||||||
|
glibc
|
||||||
|
# selftests test_verifier dependencies.
|
||||||
|
libcap
|
||||||
|
)
|
||||||
|
|
||||||
|
pacstrap -C "$pacman_conf" -cGM "$root" "${packages[@]}"
|
||||||
|
|
||||||
|
# Remove unnecessary files from the chroot.
|
||||||
|
|
||||||
|
# We don't need the pacman databases anymore.
|
||||||
|
rm -rf "$root/var/lib/pacman/sync/"
|
||||||
|
# We don't need D, Fortran, or Go.
|
||||||
|
rm -f "$root/usr/lib/libgdruntime."* \
|
||||||
|
"$root/usr/lib/libgphobos."* \
|
||||||
|
"$root/usr/lib/libgfortran."* \
|
||||||
|
"$root/usr/lib/libgo."*
|
||||||
|
# We don't need any documentation.
|
||||||
|
rm -rf "$root/usr/share/{doc,help,man,texinfo}"
|
||||||
|
|
||||||
|
chroot "${root}" /bin/busybox --install
|
||||||
|
|
||||||
|
cat > "$root/etc/fstab" << "EOF"
|
||||||
|
dev /dev devtmpfs rw,nosuid 0 0
|
||||||
|
proc /proc proc rw,nosuid,nodev,noexec 0 0
|
||||||
|
sys /sys sysfs rw,nosuid,nodev,noexec 0 0
|
||||||
|
debugfs /sys/kernel/debug debugfs mode=755,realtime 0 0
|
||||||
|
bpffs /sys/fs/bpf bpf realtime 0 0
|
||||||
|
EOF
|
||||||
|
chmod 644 "$root/etc/fstab"
|
||||||
|
|
||||||
|
cat > "$root/etc/inittab" << "EOF"
|
||||||
|
::sysinit:/etc/init.d/rcS
|
||||||
|
::ctrlaltdel:/sbin/reboot
|
||||||
|
::shutdown:/sbin/swapoff -a
|
||||||
|
::shutdown:/bin/umount -a -r
|
||||||
|
::restart:/sbin/init
|
||||||
|
EOF
|
||||||
|
chmod 644 "$root/etc/inittab"
|
||||||
|
|
||||||
|
mkdir -m 755 "$root/etc/init.d" "$root/etc/rcS.d"
|
||||||
|
cat > "$root/etc/rcS.d/S10-mount" << "EOF"
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
/bin/mount -a
|
||||||
|
EOF
|
||||||
|
chmod 755 "$root/etc/rcS.d/S10-mount"
|
||||||
|
|
||||||
|
cat > "$root/etc/rcS.d/S40-network" << "EOF"
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
ip link set lo up
|
||||||
|
EOF
|
||||||
|
chmod 755 "$root/etc/rcS.d/S40-network"
|
||||||
|
|
||||||
|
cat > "$root/etc/init.d/rcS" << "EOF"
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
for path in /etc/rcS.d/S*; do
|
||||||
|
[ -x "$path" ] && "$path"
|
||||||
|
done
|
||||||
|
EOF
|
||||||
|
chmod 755 "$root/etc/init.d/rcS"
|
||||||
|
|
||||||
|
chmod 755 "$root"
|
||||||
|
tar -C "$root" -c . | zstd -T0 -19 -o "$NAME"
|
||||||
|
chmod 644 "$NAME"
|
||||||
14
travis-ci/vmtest/prepare_selftests.sh
Executable file
14
travis-ci/vmtest/prepare_selftests.sh
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
REPO_PATH=$1
|
||||||
|
|
||||||
|
${VMTEST_ROOT}/checkout_latest_kernel.sh ${REPO_PATH}
|
||||||
|
cd ${REPO_PATH}
|
||||||
|
|
||||||
|
if [[ "${KERNEL}" = 'LATEST' ]]; then
|
||||||
|
cp ${VMTEST_ROOT}/configs/latest.config .config
|
||||||
|
make -j $((4*$(nproc))) olddefconfig all
|
||||||
|
fi
|
||||||
|
|
||||||
438
travis-ci/vmtest/run.sh
Executable file
438
travis-ci/vmtest/run.sh
Executable file
@@ -0,0 +1,438 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -uo pipefail
|
||||||
|
trap 'exit 2' ERR
|
||||||
|
|
||||||
|
usage () {
|
||||||
|
USAGE_STRING="usage: $0 [-k KERNELRELEASE|-b DIR] [[-r ROOTFSVERSION] [-fo]|-I] [-Si] [-d DIR] IMG
|
||||||
|
$0 [-k KERNELRELEASE] -l
|
||||||
|
$0 -h
|
||||||
|
|
||||||
|
Run "${PROJECT_NAME}" tests in a virtual machine.
|
||||||
|
|
||||||
|
This exits with status 0 on success, 1 if the virtual machine ran successfully
|
||||||
|
but tests failed, and 2 if we encountered a fatal error.
|
||||||
|
|
||||||
|
This script uses sudo to mount and modify the disk image.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
IMG path of virtual machine disk image to create
|
||||||
|
|
||||||
|
Versions:
|
||||||
|
-k, --kernel=KERNELRELEASE
|
||||||
|
kernel release to test. This is a glob pattern; the
|
||||||
|
newest (sorted by version number) release that matches
|
||||||
|
the pattern is used (default: newest available release)
|
||||||
|
|
||||||
|
-b, --build DIR use the kernel built in the given directory. This option
|
||||||
|
cannot be combined with -k
|
||||||
|
|
||||||
|
-r, --rootfs=ROOTFSVERSION
|
||||||
|
version of root filesystem to use (default: newest
|
||||||
|
available version)
|
||||||
|
|
||||||
|
Setup:
|
||||||
|
-f, --force overwrite IMG if it already exists
|
||||||
|
|
||||||
|
-o, --one-shot one-shot mode. By default, this script saves a clean copy
|
||||||
|
of the downloaded root filesystem image and vmlinux and
|
||||||
|
makes a copy (reflinked, when possible) for executing the
|
||||||
|
virtual machine. This allows subsequent runs to skip
|
||||||
|
downloading these files. If this option is given, the
|
||||||
|
root filesystem image and vmlinux are always
|
||||||
|
re-downloaded and are not saved. This option implies -f
|
||||||
|
|
||||||
|
-s, --setup-cmd setup commands run on VM boot. Whitespace characters
|
||||||
|
should be escaped with preceding '\'.
|
||||||
|
|
||||||
|
-I, --skip-image skip creating the disk image; use the existing one at
|
||||||
|
IMG. This option cannot be combined with -r, -f, or -o
|
||||||
|
|
||||||
|
-S, --skip-source skip copying the source files and init scripts
|
||||||
|
|
||||||
|
Miscellaneous:
|
||||||
|
-i, --interactive interactive mode. Boot the virtual machine into an
|
||||||
|
interactive shell instead of automatically running tests
|
||||||
|
|
||||||
|
-d, --dir=DIR working directory to use for downloading and caching
|
||||||
|
files (default: current working directory)
|
||||||
|
|
||||||
|
-l, --list list available kernel releases instead of running tests.
|
||||||
|
The list may be filtered with -k
|
||||||
|
|
||||||
|
-h, --help display this help message and exit"
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
out)
|
||||||
|
echo "$USAGE_STRING"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
err)
|
||||||
|
echo "$USAGE_STRING" >&2
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
TEMP=$(getopt -o 'k:b:r:fos:ISid:lh' --long 'kernel:,build:,rootfs:,force,one-shot,setup-cmd,skip-image,skip-source:,interactive,dir:,list,help' -n "$0" -- "$@")
|
||||||
|
eval set -- "$TEMP"
|
||||||
|
unset TEMP
|
||||||
|
|
||||||
|
unset KERNELRELEASE
|
||||||
|
unset BUILDDIR
|
||||||
|
unset ROOTFSVERSION
|
||||||
|
unset IMG
|
||||||
|
unset SETUPCMD
|
||||||
|
FORCE=0
|
||||||
|
ONESHOT=0
|
||||||
|
SKIPIMG=0
|
||||||
|
SKIPSOURCE=0
|
||||||
|
APPEND=""
|
||||||
|
DIR="$PWD"
|
||||||
|
LIST=0
|
||||||
|
while true; do
|
||||||
|
case "$1" in
|
||||||
|
-k|--kernel)
|
||||||
|
KERNELRELEASE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-b|--build)
|
||||||
|
BUILDDIR="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-r|--rootfs)
|
||||||
|
ROOTFSVERSION="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-f|--force)
|
||||||
|
FORCE=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-o|--one-shot)
|
||||||
|
ONESHOT=1
|
||||||
|
FORCE=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-s|--setup-cmd)
|
||||||
|
SETUPCMD="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-I|--skip-image)
|
||||||
|
SKIPIMG=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-S|--skip-source)
|
||||||
|
SKIPSOURCE=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-i|--interactive)
|
||||||
|
APPEND=" single"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-d|--dir)
|
||||||
|
DIR="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-l|--list)
|
||||||
|
LIST=1
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage out
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage err
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
if [[ -v BUILDDIR ]]; then
|
||||||
|
if [[ -v KERNELRELEASE ]]; then
|
||||||
|
usage err
|
||||||
|
fi
|
||||||
|
elif [[ ! -v KERNELRELEASE ]]; then
|
||||||
|
KERNELRELEASE='*'
|
||||||
|
fi
|
||||||
|
if [[ $SKIPIMG -ne 0 && ( -v ROOTFSVERSION || $FORCE -ne 0 ) ]]; then
|
||||||
|
usage err
|
||||||
|
fi
|
||||||
|
if (( LIST )); then
|
||||||
|
if [[ $# -ne 0 || -v BUILDDIR || -v ROOTFSVERSION || $FORCE -ne 0 ||
|
||||||
|
$SKIPIMG -ne 0 || $SKIPSOURCE -ne 0 || -n $APPEND ]]; then
|
||||||
|
usage err
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [[ $# -ne 1 ]]; then
|
||||||
|
usage err
|
||||||
|
fi
|
||||||
|
IMG="${!OPTIND}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
unset URLS
|
||||||
|
cache_urls() {
|
||||||
|
if ! declare -p URLS &> /dev/null; then
|
||||||
|
# This URL contains a mapping from file names to URLs where
|
||||||
|
# those files can be downloaded.
|
||||||
|
declare -gA URLS
|
||||||
|
while IFS=$'\t' read -r name url; do
|
||||||
|
URLS["$name"]="$url"
|
||||||
|
done < <(cat "${VMTEST_ROOT}/configs/INDEX")
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
matching_kernel_releases() {
|
||||||
|
local pattern="$1"
|
||||||
|
{
|
||||||
|
for file in "${!URLS[@]}"; do
|
||||||
|
if [[ $file =~ ^vmlinux-(.*).zst$ ]]; then
|
||||||
|
release="${BASH_REMATCH[1]}"
|
||||||
|
case "$release" in
|
||||||
|
$pattern)
|
||||||
|
# sort -V handles rc versions properly
|
||||||
|
# if we use "~" instead of "-".
|
||||||
|
echo "${release//-rc/~rc}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
} | sort -rV | sed 's/~rc/-rc/g'
|
||||||
|
}
|
||||||
|
|
||||||
|
newest_rootfs_version() {
|
||||||
|
{
|
||||||
|
for file in "${!URLS[@]}"; do
|
||||||
|
if [[ $file =~ ^${PROJECT_NAME}-vmtest-rootfs-(.*)\.tar\.zst$ ]]; then
|
||||||
|
echo "${BASH_REMATCH[1]}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
} | sort -rV | head -1
|
||||||
|
}
|
||||||
|
|
||||||
|
download() {
|
||||||
|
local file="$1"
|
||||||
|
cache_urls
|
||||||
|
if [[ ! -v URLS[$file] ]]; then
|
||||||
|
echo "$file not found" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
echo "Downloading $file..." >&2
|
||||||
|
curl -Lf "${URLS[$file]}" "${@:2}"
|
||||||
|
}
|
||||||
|
|
||||||
|
set_nocow() {
|
||||||
|
touch "$@"
|
||||||
|
chattr +C "$@" >/dev/null 2>&1 || true
|
||||||
|
}
|
||||||
|
|
||||||
|
cp_img() {
|
||||||
|
set_nocow "$2"
|
||||||
|
cp --reflink=auto "$1" "$2"
|
||||||
|
}
|
||||||
|
|
||||||
|
create_rootfs_img() {
|
||||||
|
local path="$1"
|
||||||
|
set_nocow "$path"
|
||||||
|
truncate -s 2G "$path"
|
||||||
|
mkfs.ext4 -q "$path"
|
||||||
|
}
|
||||||
|
|
||||||
|
download_rootfs() {
|
||||||
|
local rootfsversion="$1"
|
||||||
|
local dir="$2"
|
||||||
|
download "${PROJECT_NAME}-vmtest-rootfs-$rootfsversion.tar.zst" |
|
||||||
|
zstd -d | sudo tar -C "$dir" -x
|
||||||
|
}
|
||||||
|
|
||||||
|
if (( LIST )); then
|
||||||
|
cache_urls
|
||||||
|
matching_kernel_releases "$KERNELRELEASE"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $FORCE -eq 0 && $SKIPIMG -eq 0 && -e $IMG ]]; then
|
||||||
|
echo "$IMG already exists; use -f to overwrite it or -I to reuse it" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Only go to the network if it's actually a glob pattern.
|
||||||
|
if [[ -v BUILDDIR ]]; then
|
||||||
|
KERNELRELEASE="$(make -C "$BUILDDIR" -s kernelrelease)"
|
||||||
|
elif [[ ! $KERNELRELEASE =~ ^([^\\*?[]|\\[*?[])*\\?$ ]]; then
|
||||||
|
# We need to cache the list of URLs outside of the command
|
||||||
|
# substitution, which happens in a subshell.
|
||||||
|
cache_urls
|
||||||
|
KERNELRELEASE="$(matching_kernel_releases "$KERNELRELEASE" | head -1)"
|
||||||
|
if [[ -z $KERNELRELEASE ]]; then
|
||||||
|
echo "No matching kernel release found" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ $SKIPIMG -eq 0 && ! -v ROOTFSVERSION ]]; then
|
||||||
|
cache_urls
|
||||||
|
ROOTFSVERSION="$(newest_rootfs_version)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Kernel release: $KERNELRELEASE" >&2
|
||||||
|
if (( SKIPIMG )); then
|
||||||
|
echo "Not extracting root filesystem" >&2
|
||||||
|
else
|
||||||
|
echo "Root filesystem version: $ROOTFSVERSION" >&2
|
||||||
|
fi
|
||||||
|
echo "Disk image: $IMG" >&2
|
||||||
|
|
||||||
|
tmp=
|
||||||
|
ARCH_DIR="$DIR/x86_64"
|
||||||
|
mkdir -p "$ARCH_DIR"
|
||||||
|
mnt="$(mktemp -d -p "$DIR" mnt.XXXXXXXXXX)"
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
if [[ -n $tmp ]]; then
|
||||||
|
rm -f "$tmp" || true
|
||||||
|
fi
|
||||||
|
if mountpoint -q "$mnt"; then
|
||||||
|
sudo umount "$mnt" || true
|
||||||
|
fi
|
||||||
|
if [[ -d "$mnt" ]]; then
|
||||||
|
rmdir "$mnt" || true
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
if [[ -v BUILDDIR ]]; then
|
||||||
|
vmlinuz="$BUILDDIR/$(make -C "$BUILDDIR" -s image_name)"
|
||||||
|
else
|
||||||
|
vmlinuz="${ARCH_DIR}/vmlinuz-${KERNELRELEASE}"
|
||||||
|
if [[ ! -e $vmlinuz ]]; then
|
||||||
|
tmp="$(mktemp "$vmlinuz.XXX.part")"
|
||||||
|
download "vmlinuz-${KERNELRELEASE}" -o "$tmp"
|
||||||
|
mv "$tmp" "$vmlinuz"
|
||||||
|
tmp=
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Mount and set up the rootfs image.
|
||||||
|
if (( ONESHOT )); then
|
||||||
|
rm -f "$IMG"
|
||||||
|
create_rootfs_img "$IMG"
|
||||||
|
sudo mount -o loop "$IMG" "$mnt"
|
||||||
|
download_rootfs "$ROOTFSVERSION" "$mnt"
|
||||||
|
else
|
||||||
|
if (( ! SKIPIMG )); then
|
||||||
|
rootfs_img="${ARCH_DIR}/${PROJECT_NAME}-vmtest-rootfs-${ROOTFSVERSION}.img"
|
||||||
|
|
||||||
|
if [[ ! -e $rootfs_img ]]; then
|
||||||
|
tmp="$(mktemp "$rootfs_img.XXX.part")"
|
||||||
|
set_nocow "$tmp"
|
||||||
|
truncate -s 2G "$tmp"
|
||||||
|
mkfs.ext4 -q "$tmp"
|
||||||
|
sudo mount -o loop "$tmp" "$mnt"
|
||||||
|
|
||||||
|
download_rootfs "$ROOTFSVERSION" "$mnt"
|
||||||
|
|
||||||
|
sudo umount "$mnt"
|
||||||
|
mv "$tmp" "$rootfs_img"
|
||||||
|
tmp=
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f "$IMG"
|
||||||
|
cp_img "$rootfs_img" "$IMG"
|
||||||
|
fi
|
||||||
|
sudo mount -o loop "$IMG" "$mnt"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install vmlinux.
|
||||||
|
vmlinux="$mnt/boot/vmlinux-${KERNELRELEASE}"
|
||||||
|
if [[ -v BUILDDIR || $ONESHOT -eq 0 ]]; then
|
||||||
|
if [[ -v BUILDDIR ]]; then
|
||||||
|
source_vmlinux="${BUILDDIR}/vmlinux"
|
||||||
|
else
|
||||||
|
source_vmlinux="${ARCH_DIR}/vmlinux-${KERNELRELEASE}"
|
||||||
|
if [[ ! -e $source_vmlinux ]]; then
|
||||||
|
tmp="$(mktemp "$source_vmlinux.XXX.part")"
|
||||||
|
download "vmlinux-${KERNELRELEASE}.zst" | zstd -dfo "$tmp"
|
||||||
|
mv "$tmp" "$source_vmlinux"
|
||||||
|
tmp=
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "Copying vmlinux..." >&2
|
||||||
|
sudo rsync -cp --chmod 0644 "$source_vmlinux" "$vmlinux"
|
||||||
|
else
|
||||||
|
# We could use "sudo zstd -o", but let's not run zstd as root with
|
||||||
|
# input from the internet.
|
||||||
|
download "vmlinux-${KERNELRELEASE}.zst" |
|
||||||
|
zstd -d | sudo tee "$vmlinux" > /dev/null
|
||||||
|
sudo chmod 644 "$vmlinux"
|
||||||
|
fi
|
||||||
|
|
||||||
|
LIBBPF_PATH="${REPO_ROOT}" \
|
||||||
|
REPO_PATH="travis-ci/vmtest/bpf-next" \
|
||||||
|
VMTEST_ROOT="${VMTEST_ROOT}" \
|
||||||
|
VMLINUX_BTF=${vmlinux} ${VMTEST_ROOT}/build_selftests.sh
|
||||||
|
|
||||||
|
if (( SKIPSOURCE )); then
|
||||||
|
echo "Not copying source files..." >&2
|
||||||
|
else
|
||||||
|
echo "Copying source files..." >&2
|
||||||
|
|
||||||
|
# Copy the source files in.
|
||||||
|
sudo mkdir -p -m 0755 "$mnt/${PROJECT_NAME}"
|
||||||
|
{
|
||||||
|
if [[ -e .git ]]; then
|
||||||
|
git ls-files -z
|
||||||
|
else
|
||||||
|
tr '\n' '\0' < "${PROJECT_NAME}.egg-info/SOURCES.txt"
|
||||||
|
fi
|
||||||
|
} | sudo rsync --files-from=- -0cpt . "$mnt/${PROJECT_NAME}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
setup_script="#!/bin/sh
|
||||||
|
|
||||||
|
echo 'Skipping setup commands'
|
||||||
|
echo 0 > /exitstatus
|
||||||
|
chmod 644 /exitstatus"
|
||||||
|
|
||||||
|
# Create the init scripts.
|
||||||
|
if [[ ! -z SETUPCMD ]]; then
|
||||||
|
# Unescape whitespace characters.
|
||||||
|
setup_cmd=$(sed 's/\(\\\)\([[:space:]]\)/\2/g' <<< "${SETUPCMD}")
|
||||||
|
kernel="${KERNELRELEASE}"
|
||||||
|
if [[ -v BUILDDIR ]]; then kernel='latest'; fi
|
||||||
|
setup_envvars="export KERNEL=${kernel}"
|
||||||
|
setup_script=$(printf "#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo 'Running setup commands'
|
||||||
|
%s
|
||||||
|
%s
|
||||||
|
echo $? > /exitstatus
|
||||||
|
chmod 644 /exitstatus" "${setup_envvars}" "${setup_cmd}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "${setup_script}" | sudo tee "$mnt/etc/rcS.d/S50-run-tests" > /dev/null
|
||||||
|
sudo chmod 755 "$mnt/etc/rcS.d/S50-run-tests"
|
||||||
|
|
||||||
|
poweroff_script="#!/bin/sh
|
||||||
|
|
||||||
|
poweroff"
|
||||||
|
echo "${poweroff_script}" | sudo tee "$mnt/etc/rcS.d/S99-poweroff" > /dev/null
|
||||||
|
sudo chmod 755 "$mnt/etc/rcS.d/S99-poweroff"
|
||||||
|
|
||||||
|
sudo umount "$mnt"
|
||||||
|
|
||||||
|
echo "Starting virtual machine..." >&2
|
||||||
|
qemu-system-x86_64 -nodefaults -display none -serial mon:stdio \
|
||||||
|
-cpu kvm64 -enable-kvm -smp "$(nproc)" -m 2G \
|
||||||
|
-drive file="$IMG",format=raw,index=1,media=disk,if=virtio,cache=none \
|
||||||
|
-kernel "$vmlinuz" -append "root=/dev/vda rw console=ttyS0,115200$APPEND"
|
||||||
|
|
||||||
|
sudo mount -o loop "$IMG" "$mnt"
|
||||||
|
if exitstatus="$(cat "$mnt/exitstatus" 2>/dev/null)"; then
|
||||||
|
printf '\nTests exit status: %s\n' "$exitstatus" >&2
|
||||||
|
else
|
||||||
|
printf '\nCould not read tests exit status\n' >&2
|
||||||
|
exitstatus=1
|
||||||
|
fi
|
||||||
|
sudo umount "$mnt"
|
||||||
|
exit "$exitstatus"
|
||||||
39
travis-ci/vmtest/run_selftests.sh
Executable file
39
travis-ci/vmtest/run_selftests.sh
Executable file
@@ -0,0 +1,39 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euxo pipefail
|
||||||
|
|
||||||
|
test_progs() {
|
||||||
|
echo TEST_PROGS
|
||||||
|
./test_progs ${BLACKLIST:+-b$BLACKLIST} ${WHITELIST:+-t$WHITELIST}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_maps() {
|
||||||
|
echo TEST_MAPS
|
||||||
|
# Allow failing on older kernels.
|
||||||
|
./test_maps
|
||||||
|
}
|
||||||
|
|
||||||
|
test_verifier() {
|
||||||
|
echo TEST_VERIFIER
|
||||||
|
./test_verifier
|
||||||
|
}
|
||||||
|
|
||||||
|
configs_path='libbpf/travis-ci/vmtest/configs'
|
||||||
|
blacklist_path="$configs_path/blacklist/BLACKLIST-${KERNEL}"
|
||||||
|
if [[ -s "${blacklist_path}" ]]; then
|
||||||
|
BLACKLIST=$(cat "${blacklist_path}" | cut -d'#' -f1 | tr -s '[:space:]' ',')
|
||||||
|
fi
|
||||||
|
|
||||||
|
whitelist_path="$configs_path/whitelist/WHITELIST-${KERNEL}"
|
||||||
|
if [[ -s "${whitelist_path}" ]]; then
|
||||||
|
WHITELIST=$(cat "${whitelist_path}" | cut -d'#' -f1 | tr -s '[:space:]' ',')
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd libbpf/selftests/bpf
|
||||||
|
|
||||||
|
test_progs
|
||||||
|
|
||||||
|
if [[ "${KERNEL}" == 'latest' ]]; then
|
||||||
|
test_maps
|
||||||
|
test_verifier
|
||||||
|
fi
|
||||||
30
travis-ci/vmtest/run_vmtest.sh
Executable file
30
travis-ci/vmtest/run_vmtest.sh
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
VMTEST_SETUPCMD="PROJECT_NAME=${PROJECT_NAME} ./${PROJECT_NAME}/travis-ci/vmtest/run_selftests.sh"
|
||||||
|
|
||||||
|
echo "KERNEL: $KERNEL"
|
||||||
|
|
||||||
|
# Build latest pahole
|
||||||
|
${VMTEST_ROOT}/build_pahole.sh travis-ci/vmtest/pahole
|
||||||
|
|
||||||
|
# Install required packages
|
||||||
|
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||||
|
echo "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main" | sudo tee -a /etc/apt/sources.list
|
||||||
|
sudo apt-get -qq update
|
||||||
|
sudo apt-get -qq -y install clang lld llvm
|
||||||
|
|
||||||
|
# Build selftests (and latest kernel, if necessary)
|
||||||
|
KERNEL="${KERNEL}" ${VMTEST_ROOT}/prepare_selftests.sh travis-ci/vmtest/bpf-next
|
||||||
|
|
||||||
|
# Escape whitespace characters.
|
||||||
|
setup_cmd=$(sed 's/\([[:space:]]\)/\\\1/g' <<< "${VMTEST_SETUPCMD}")
|
||||||
|
|
||||||
|
sudo adduser "${USER}" kvm
|
||||||
|
|
||||||
|
if [[ "${KERNEL}" = 'LATEST' ]]; then
|
||||||
|
sudo -E sudo -E -u "${USER}" "${VMTEST_ROOT}/run.sh" -b travis-ci/vmtest/bpf-next -o -d ~ -s "${setup_cmd}" ~/root.img;
|
||||||
|
else
|
||||||
|
sudo -E sudo -E -u "${USER}" "${VMTEST_ROOT}/run.sh" -k "${KERNEL}*" -o -d ~ -s "${setup_cmd}" ~/root.img;
|
||||||
|
fi
|
||||||
Reference in New Issue
Block a user