mirror of
https://github.com/netdata/libbpf.git
synced 2026-03-25 10:49:06 +08:00
Compare commits
82 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
60
.travis.yml
60
.travis.yml
@@ -1,13 +1,54 @@
|
|||||||
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"
|
- CI_MANAGERS="$TRAVIS_BUILD_DIR/travis-ci/managers"
|
||||||
|
- VMTEST_ROOT="$TRAVIS_BUILD_DIR/travis-ci/vmtest"
|
||||||
- REPO_ROOT="$TRAVIS_BUILD_DIR"
|
- REPO_ROOT="$TRAVIS_BUILD_DIR"
|
||||||
|
- GIT_FETCH_DEPTH=64
|
||||||
|
- VMTEST_SETUPCMD="PROJECT_NAME=${PROJECT_NAME} ./${PROJECT_NAME}/travis-ci/vmtest/run_selftests.sh"
|
||||||
|
jobs:
|
||||||
|
# Setup command override.
|
||||||
|
# 5.5.0-rc6 is built from bpf-next; TODO(hex@): remove when pahole v1.16 is available
|
||||||
|
- KERNEL=5.5.0-rc6
|
||||||
|
- KERNEL=5.5.0
|
||||||
|
- KERNEL=LATEST
|
||||||
|
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- qemu-kvm
|
||||||
|
- zstd
|
||||||
|
- binutils-dev
|
||||||
|
- elfutils
|
||||||
|
- libcap-dev
|
||||||
|
- libelf-dev
|
||||||
|
install: sudo adduser "${USER}" kvm
|
||||||
|
before_script:
|
||||||
|
- wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||||
|
- echo "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main" | sudo tee -a /etc/apt/sources.list
|
||||||
|
- echo "deb http://archive.ubuntu.com/ubuntu eoan main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list
|
||||||
|
- sudo apt-get -qq update
|
||||||
|
- sudo apt-get -y install dwarves=1.15-1
|
||||||
|
- sudo apt-get -qq -y install clang-10 lld-10 llvm-10
|
||||||
|
- if [[ "${KERNEL}" = 'LATEST' ]]; then ${VMTEST_ROOT}/build_latest_kernel.sh travis-ci/vmtest/bpf-next; fi
|
||||||
|
- ${VMTEST_ROOT}/prepare_selftests.sh travis-ci/vmtest/bpf-next
|
||||||
|
# Escape whitespace characters.
|
||||||
|
- setup_cmd=$(sed 's/\([[:space:]]\)/\\\1/g' <<< "${VMTEST_SETUPCMD}")
|
||||||
|
- 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; exitstatus=$?
|
||||||
|
- test $exitstatus -le 1
|
||||||
|
script:
|
||||||
|
- test $exitstatus -eq 0
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
# Run Coverity periodically instead of for each PR for following reasons:
|
# Run Coverity periodically instead of for each PR for following reasons:
|
||||||
@@ -32,6 +73,8 @@ jobs:
|
|||||||
- docker --version
|
- docker --version
|
||||||
install:
|
install:
|
||||||
- $CI_MANAGERS/debian.sh SETUP
|
- $CI_MANAGERS/debian.sh SETUP
|
||||||
|
# Override before_script: so VMTEST before_install commands are not executed.
|
||||||
|
before_script: true
|
||||||
script:
|
script:
|
||||||
- $CI_MANAGERS/debian.sh RUN || travis_terminate
|
- $CI_MANAGERS/debian.sh RUN || travis_terminate
|
||||||
after_script:
|
after_script:
|
||||||
@@ -47,6 +90,7 @@ jobs:
|
|||||||
- docker --version
|
- docker --version
|
||||||
install:
|
install:
|
||||||
- $CI_MANAGERS/debian.sh SETUP
|
- $CI_MANAGERS/debian.sh SETUP
|
||||||
|
before_script: true
|
||||||
script:
|
script:
|
||||||
- $CI_MANAGERS/debian.sh RUN_ASAN || travis_terminate
|
- $CI_MANAGERS/debian.sh RUN_ASAN || travis_terminate
|
||||||
after_script:
|
after_script:
|
||||||
@@ -62,6 +106,7 @@ jobs:
|
|||||||
- docker --version
|
- docker --version
|
||||||
install:
|
install:
|
||||||
- $CI_MANAGERS/debian.sh SETUP
|
- $CI_MANAGERS/debian.sh SETUP
|
||||||
|
before_script: true
|
||||||
script:
|
script:
|
||||||
- $CI_MANAGERS/debian.sh RUN_CLANG || travis_terminate
|
- $CI_MANAGERS/debian.sh RUN_CLANG || travis_terminate
|
||||||
after_script:
|
after_script:
|
||||||
@@ -77,6 +122,7 @@ jobs:
|
|||||||
- docker --version
|
- docker --version
|
||||||
install:
|
install:
|
||||||
- $CI_MANAGERS/debian.sh SETUP
|
- $CI_MANAGERS/debian.sh SETUP
|
||||||
|
before_script: true
|
||||||
script:
|
script:
|
||||||
- $CI_MANAGERS/debian.sh RUN_CLANG_ASAN || travis_terminate
|
- $CI_MANAGERS/debian.sh RUN_CLANG_ASAN || travis_terminate
|
||||||
after_script:
|
after_script:
|
||||||
@@ -92,6 +138,7 @@ jobs:
|
|||||||
- docker --version
|
- docker --version
|
||||||
install:
|
install:
|
||||||
- $CI_MANAGERS/debian.sh SETUP
|
- $CI_MANAGERS/debian.sh SETUP
|
||||||
|
before_script: true
|
||||||
script:
|
script:
|
||||||
- $CI_MANAGERS/debian.sh RUN_GCC8 || travis_terminate
|
- $CI_MANAGERS/debian.sh RUN_GCC8 || travis_terminate
|
||||||
after_script:
|
after_script:
|
||||||
@@ -107,6 +154,7 @@ jobs:
|
|||||||
- docker --version
|
- docker --version
|
||||||
install:
|
install:
|
||||||
- $CI_MANAGERS/debian.sh SETUP
|
- $CI_MANAGERS/debian.sh SETUP
|
||||||
|
before_script: true
|
||||||
script:
|
script:
|
||||||
- $CI_MANAGERS/debian.sh RUN_GCC8_ASAN || travis_terminate
|
- $CI_MANAGERS/debian.sh RUN_GCC8_ASAN || travis_terminate
|
||||||
after_script:
|
after_script:
|
||||||
@@ -114,18 +162,28 @@ jobs:
|
|||||||
|
|
||||||
- name: Ubuntu Bionic
|
- name: Ubuntu Bionic
|
||||||
language: bash
|
language: bash
|
||||||
|
before_script: true
|
||||||
script:
|
script:
|
||||||
- sudo $CI_MANAGERS/ubuntu.sh || travis_terminate
|
- sudo $CI_MANAGERS/ubuntu.sh || travis_terminate
|
||||||
|
|
||||||
- name: Ubuntu Bionic (arm)
|
- name: Ubuntu Bionic (arm)
|
||||||
arch: arm64
|
arch: arm64
|
||||||
language: bash
|
language: bash
|
||||||
|
before_script: true
|
||||||
script:
|
script:
|
||||||
- sudo $CI_MANAGERS/ubuntu.sh || travis_terminate
|
- sudo $CI_MANAGERS/ubuntu.sh || travis_terminate
|
||||||
|
|
||||||
- name: Ubuntu Bionic (s390x)
|
- name: Ubuntu Bionic (s390x)
|
||||||
arch: s390x
|
arch: s390x
|
||||||
language: bash
|
language: bash
|
||||||
|
before_script: true
|
||||||
|
script:
|
||||||
|
- sudo $CI_MANAGERS/ubuntu.sh || travis_terminate
|
||||||
|
|
||||||
|
- name: Ubuntu Bionic (ppc64le)
|
||||||
|
arch: ppc64le
|
||||||
|
language: bash
|
||||||
|
before_script: true
|
||||||
script:
|
script:
|
||||||
- sudo $CI_MANAGERS/ubuntu.sh || travis_terminate
|
- sudo $CI_MANAGERS/ubuntu.sh || travis_terminate
|
||||||
|
|
||||||
@@ -147,5 +205,7 @@ jobs:
|
|||||||
- sudo apt-get update
|
- sudo apt-get update
|
||||||
- sudo apt-get -y build-dep libelf-dev
|
- sudo apt-get -y build-dep libelf-dev
|
||||||
- sudo apt-get install -y libelf-dev pkg-config
|
- sudo apt-get install -y libelf-dev pkg-config
|
||||||
|
# Override before_script: so VMTEST before_script commands are not executed.
|
||||||
|
before_script: true
|
||||||
script:
|
script:
|
||||||
- scripts/coverity.sh || travis_terminate
|
- scripts/coverity.sh || travis_terminate
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
e42617b825f8073569da76dc4510bfa019b1c35a
|
08dc225d8868d5094ada62f471ebdfcce9dbc298
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
e7096c131e5161fa3b8e52a650d7719d2857adfd
|
35b9211c0a2427e8f39e534f442f43804fc8d5ca
|
||||||
|
|||||||
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
|
||||||
=====
|
=====
|
||||||
|
|
||||||
|
|||||||
@@ -107,6 +107,10 @@ 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,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum bpf_map_type {
|
enum bpf_map_type {
|
||||||
@@ -136,6 +140,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 +179,8 @@ 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,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum bpf_attach_type {
|
enum bpf_attach_type {
|
||||||
@@ -231,6 +238,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 +261,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
|
||||||
@@ -351,7 +364,12 @@ enum bpf_attach_type {
|
|||||||
/* Enable memory-mapping BPF map */
|
/* Enable memory-mapping BPF map */
|
||||||
#define BPF_F_MMAPABLE (1U << 10)
|
#define 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 {
|
||||||
@@ -391,6 +409,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 +425,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 +481,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 */
|
||||||
@@ -2693,7 +2736,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 +2865,33 @@ 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
|
||||||
*/
|
*/
|
||||||
#define __BPF_FUNC_MAPPER(FN) \
|
#define __BPF_FUNC_MAPPER(FN) \
|
||||||
FN(unspec), \
|
FN(unspec), \
|
||||||
@@ -2938,7 +3009,10 @@ 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),
|
||||||
|
|
||||||
/* 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
|
||||||
@@ -3339,7 +3413,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;
|
||||||
|
|||||||
@@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -485,6 +486,13 @@ 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_END,
|
||||||
|
MACSEC_OFFLOAD_MAX = __MACSEC_OFFLOAD_END - 1,
|
||||||
|
};
|
||||||
|
|
||||||
/* IPVLAN section */
|
/* IPVLAN section */
|
||||||
enum {
|
enum {
|
||||||
IFLA_IPVLAN_UNSPEC,
|
IFLA_IPVLAN_UNSPEC,
|
||||||
|
|||||||
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
|
||||||
|
|||||||
89
src/bpf.c
89
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,10 @@ 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.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 +453,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 +534,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));
|
||||||
}
|
}
|
||||||
|
|||||||
44
src/bpf.h
44
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,10 +127,43 @@ 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);
|
||||||
|
|||||||
@@ -2600,7 +2600,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 +2757,43 @@ 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;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
151
src/btf.c
151
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1352,7 +1405,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 +1701,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 +2935,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
|
||||||
*/
|
*/
|
||||||
|
|||||||
119
src/btf_dump.c
119
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);
|
||||||
}
|
}
|
||||||
@@ -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, NULL);
|
||||||
|
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
|
||||||
|
|
||||||
|
|||||||
2756
src/libbpf.c
2756
src/libbpf.c
File diff suppressed because it is too large
Load Diff
121
src/libbpf.h
121
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,11 @@ LIBBPF_API void bpf_program__unload(struct bpf_program *prog);
|
|||||||
|
|
||||||
struct bpf_link;
|
struct bpf_link;
|
||||||
|
|
||||||
|
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 *
|
||||||
@@ -256,6 +243,8 @@ bpf_program__attach_raw_tracepoint(struct bpf_program *prog,
|
|||||||
|
|
||||||
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);
|
||||||
|
struct bpf_map;
|
||||||
|
LIBBPF_API struct bpf_link *bpf_map__attach_struct_ops(struct bpf_map *map);
|
||||||
struct bpf_insn;
|
struct bpf_insn;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -332,6 +321,8 @@ 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,
|
||||||
@@ -352,6 +343,8 @@ 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 +364,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);
|
||||||
|
|
||||||
@@ -512,18 +504,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 +530,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 +611,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,30 @@ 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;
|
||||||
|
|||||||
@@ -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,8 @@ 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:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -251,6 +256,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 +327,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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
8
travis-ci/vmtest/build_latest_kernel.sh
Executable file
8
travis-ci/vmtest/build_latest_kernel.sh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
GIT_FETCH_DEPTH="${GIT_FETCH_DEPTH}" ${VMTEST_ROOT}/checkout_latest_kernel.sh $1
|
||||||
|
cd $1
|
||||||
|
cp ${VMTEST_ROOT}/configs/latest.config .config
|
||||||
|
make -j $((4*$(nproc))) olddefconfig all
|
||||||
20
travis-ci/vmtest/build_selftests.sh
Executable file
20
travis-ci/vmtest/build_selftests.sh
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
LIBBPF_PATH="${REPO_ROOT}"
|
||||||
|
REPO_PATH="travis-ci/vmtest/bpf-next"
|
||||||
|
make \
|
||||||
|
CLANG=clang-10 \
|
||||||
|
LLC=llc-10 \
|
||||||
|
LLVM_STRIP=llvm-strip-10 \
|
||||||
|
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}
|
||||||
|
git fetch --depth ${GIT_FETCH_DEPTH} bpf-next
|
||||||
|
git reset --hard ${LINUX_SHA}
|
||||||
|
else
|
||||||
|
cd ${REPO_PATH}
|
||||||
|
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.01.10.tar.zst https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/libbpf-vmtest-rootfs-2020.01.10.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
|
||||||
21
travis-ci/vmtest/configs/blacklist/BLACKLIST-5.5.0
Normal file
21
travis-ci/vmtest/configs/blacklist/BLACKLIST-5.5.0
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
mmap
|
||||||
|
dctcp
|
||||||
|
cubic
|
||||||
|
bpf_tcp_ca
|
||||||
|
bpf_verif_scale
|
||||||
|
cgroup_attach
|
||||||
|
pinning
|
||||||
|
send_signal_tracepoint_thread
|
||||||
|
test_syncookie
|
||||||
|
select_reuseport
|
||||||
|
send_signal
|
||||||
|
sockopt_inherit
|
||||||
|
strobemeta_nounroll2
|
||||||
|
stacktrace_build_id
|
||||||
|
tp_attach_query
|
||||||
|
tcp_rtt
|
||||||
|
task_fd_query_tp
|
||||||
|
stacktrace_map
|
||||||
|
test_global_funcs
|
||||||
|
skb_ctx
|
||||||
|
fexit_bpf2bpf
|
||||||
18
travis-ci/vmtest/configs/blacklist/BLACKLIST-5.5.0-rc6
Normal file
18
travis-ci/vmtest/configs/blacklist/BLACKLIST-5.5.0-rc6
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
mmap
|
||||||
|
dctcp
|
||||||
|
cubic
|
||||||
|
bpf_tcp_ca
|
||||||
|
bpf_verif_scale
|
||||||
|
cgroup_attach
|
||||||
|
pinning
|
||||||
|
send_signal_tracepoint_thread
|
||||||
|
test_syncookie
|
||||||
|
select_reuseport
|
||||||
|
send_signal
|
||||||
|
sockopt_inherit
|
||||||
|
strobemeta_nounroll2
|
||||||
|
stacktrace_build_id
|
||||||
|
tp_attach_query
|
||||||
|
tcp_rtt
|
||||||
|
task_fd_query_tp
|
||||||
|
stacktrace_map
|
||||||
23
travis-ci/vmtest/configs/blacklist/BLACKLIST-latest
Normal file
23
travis-ci/vmtest/configs/blacklist/BLACKLIST-latest
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
mmap
|
||||||
|
dctcp
|
||||||
|
cubic
|
||||||
|
bpf_tcp_ca
|
||||||
|
bpf_verif_scale
|
||||||
|
cgroup_attach
|
||||||
|
pinning
|
||||||
|
send_signal_tracepoint_thread
|
||||||
|
test_syncookie
|
||||||
|
select_reuseport
|
||||||
|
send_signal
|
||||||
|
sockopt_inherit
|
||||||
|
strobemeta_nounroll2
|
||||||
|
stacktrace_build_id
|
||||||
|
tp_attach_query
|
||||||
|
tcp_rtt
|
||||||
|
task_fd_query_tp
|
||||||
|
stacktrace_map
|
||||||
|
fentry
|
||||||
|
test_overhead
|
||||||
|
kfree_skb
|
||||||
|
fexit_stress
|
||||||
|
fexit_test
|
||||||
4228
travis-ci/vmtest/configs/latest.config
Normal file
4228
travis-ci/vmtest/configs/latest.config
Normal file
File diff suppressed because it is too large
Load Diff
11
travis-ci/vmtest/prepare_selftests.sh
Executable file
11
travis-ci/vmtest/prepare_selftests.sh
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
GIT_FETCH_DEPTH="${GIT_FETCH_DEPTH}" ${VMTEST_ROOT}/checkout_latest_kernel.sh $1
|
||||||
|
|
||||||
|
# Fix runqslower build
|
||||||
|
# TODO(hex@): remove after the patch is merged from bpf to bpf-next tree
|
||||||
|
cd $1
|
||||||
|
wget https://lore.kernel.org/bpf/908498f794661c44dca54da9e09dc0c382df6fcb.1580425879.git.hex@fb.com/t.mbox.gz
|
||||||
|
gunzip t.mbox.gz
|
||||||
|
git apply t.mbox
|
||||||
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"
|
||||||
19
travis-ci/vmtest/run_selftests.sh
Executable file
19
travis-ci/vmtest/run_selftests.sh
Executable file
@@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
configs_path='libbpf/travis-ci/vmtest/configs'
|
||||||
|
blacklist_path="$configs_path/blacklist/BLACKLIST-${KERNEL}"
|
||||||
|
if [[ -s "${blacklist_path}" ]]; then
|
||||||
|
BLACKLIST=$(cat "${blacklist_path}" | tr '\n' ',')
|
||||||
|
fi
|
||||||
|
|
||||||
|
whitelist_path="$configs_path/whitelist/WHITELIST-${KERNEL}"
|
||||||
|
if [[ -s "${whitelist_path}" ]]; then
|
||||||
|
WHITELIST=$(cat "${whitelist_path}" | tr '\n' ',')
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd libbpf/selftests/bpf
|
||||||
|
|
||||||
|
echo TEST_PROGS
|
||||||
|
./test_progs ${BLACKLIST:+-b$BLACKLIST} ${WHITELIST:+-t$WHITELIST}
|
||||||
11
travis-ci/vmtest/setup_example.sh
Executable file
11
travis-ci/vmtest/setup_example.sh
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# An example of a script run on VM boot.
|
||||||
|
# To execute it in TravisCI set VMTEST_SETUPCMD env var of .travis.yml in
|
||||||
|
# libbpf root folder, e.g.
|
||||||
|
# VMTEST_SETUPCMD="./${PROJECT_NAME}/travis-ci/vmtest/setup_example.sh"
|
||||||
|
|
||||||
|
if [ ! -z "${PROJECT_NAME}" ]; then
|
||||||
|
echo "Running ${PROJECT_NAME} setup scripts..."
|
||||||
|
fi
|
||||||
|
echo "Hello, ${USER}!"
|
||||||
Reference in New Issue
Block a user