mirror of
https://github.com/netdata/libbpf.git
synced 2026-03-25 10:49:06 +08:00
Compare commits
70 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a1615c263 | ||
|
|
e66d297441 | ||
|
|
632afdff45 | ||
|
|
6e706b38bd | ||
|
|
850293ba1c | ||
|
|
fb528063b2 | ||
|
|
97ada10bd8 | ||
|
|
9a35753b42 | ||
|
|
c4af2093cc | ||
|
|
1543a19f36 | ||
|
|
8b41602694 | ||
|
|
cecb299ac4 | ||
|
|
90e89264b9 | ||
|
|
f69cc97272 | ||
|
|
a6e9750c8a | ||
|
|
60bade6674 | ||
|
|
e13c1b7b85 | ||
|
|
1d8451ccaf | ||
|
|
fad6e249ea | ||
|
|
64f7fa917c | ||
|
|
240b8fa098 | ||
|
|
3756d20499 | ||
|
|
9e8b23289f | ||
|
|
902eca48e5 | ||
|
|
9f0d55c24a | ||
|
|
e53dd1c436 | ||
|
|
da790d6014 | ||
|
|
3d81b13b36 | ||
|
|
64bd9e074b | ||
|
|
53d473dd8e | ||
|
|
6d64d927a2 | ||
|
|
cd87f1568e | ||
|
|
c417a4cb6f | ||
|
|
fa21d33fff | ||
|
|
84cf76de9c | ||
|
|
2ef4fdac6c | ||
|
|
1d72c9c382 | ||
|
|
7930230b43 | ||
|
|
483a8c238f | ||
|
|
26cbe2384c | ||
|
|
cb4a430c8a | ||
|
|
f67d535cdb | ||
|
|
ef4785f065 | ||
|
|
9a424bea42 | ||
|
|
10e4311ad7 | ||
|
|
50febacba1 | ||
|
|
ef7d57fcec | ||
|
|
7e7a15321e | ||
|
|
77ac09c3eb | ||
|
|
40a08ef216 | ||
|
|
b6683d1aeb | ||
|
|
5247b0b0dc | ||
|
|
c2b01ad4f3 | ||
|
|
c4468dec74 | ||
|
|
40229b3ffd | ||
|
|
7f2d538c27 | ||
|
|
b7c162a433 | ||
|
|
36c26f12f1 | ||
|
|
22d5d40493 | ||
|
|
17c26b7da6 | ||
|
|
e287979374 | ||
|
|
552af3d963 | ||
|
|
c772c9cbde | ||
|
|
031a38cceb | ||
|
|
6ff5062480 | ||
|
|
fdff85e63e | ||
|
|
5c7661fd5e | ||
|
|
1feb21b081 | ||
|
|
fa8cb316fb | ||
|
|
f72fe00e70 |
181
.travis.yml
181
.travis.yml
@@ -8,17 +8,9 @@ env:
|
|||||||
global:
|
global:
|
||||||
- PROJECT_NAME='libbpf'
|
- 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"
|
|
||||||
- VMTEST_ROOT="$TRAVIS_BUILD_DIR/travis-ci/vmtest"
|
|
||||||
- REPO_ROOT="$TRAVIS_BUILD_DIR"
|
- REPO_ROOT="$TRAVIS_BUILD_DIR"
|
||||||
- GIT_FETCH_DEPTH=64
|
- CI_ROOT="$REPO_ROOT/travis-ci"
|
||||||
- VMTEST_SETUPCMD="PROJECT_NAME=${PROJECT_NAME} ./${PROJECT_NAME}/travis-ci/vmtest/run_selftests.sh"
|
- VMTEST_ROOT="$CI_ROOT/vmtest"
|
||||||
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:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
@@ -29,26 +21,7 @@ addons:
|
|||||||
- elfutils
|
- elfutils
|
||||||
- libcap-dev
|
- libcap-dev
|
||||||
- libelf-dev
|
- libelf-dev
|
||||||
install: sudo adduser "${USER}" kvm
|
- libdw-dev
|
||||||
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:
|
||||||
@@ -62,130 +35,72 @@ stages:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
include:
|
include:
|
||||||
- stage: Build & test
|
- stage: Build
|
||||||
name: Debian Testing
|
name: Debian Build
|
||||||
language: bash
|
language: bash
|
||||||
env:
|
install: $CI_ROOT/managers/debian.sh SETUP
|
||||||
- DEBIAN_RELEASE="testing"
|
script: $CI_ROOT/managers/debian.sh RUN || travis_terminate
|
||||||
- CONT_NAME="libbpf-debian-$DEBIAN_RELEASE"
|
after_script: $CI_ROOT/managers/debian.sh CLEANUP
|
||||||
before_install:
|
|
||||||
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
|
|
||||||
- docker --version
|
|
||||||
install:
|
|
||||||
- $CI_MANAGERS/debian.sh SETUP
|
|
||||||
# Override before_script: so VMTEST before_install commands are not executed.
|
|
||||||
before_script: true
|
|
||||||
script:
|
|
||||||
- $CI_MANAGERS/debian.sh RUN || travis_terminate
|
|
||||||
after_script:
|
|
||||||
- $CI_MANAGERS/debian.sh CLEANUP
|
|
||||||
|
|
||||||
- name: Debian Testing (ASan+UBSan)
|
- name: Debian Build (ASan+UBSan)
|
||||||
language: bash
|
language: bash
|
||||||
env:
|
install: $CI_ROOT/managers/debian.sh SETUP
|
||||||
- DEBIAN_RELEASE="testing"
|
script: $CI_ROOT/managers/debian.sh RUN_ASAN || travis_terminate
|
||||||
- CONT_NAME="libbpf-debian-$DEBIAN_RELEASE"
|
after_script: $CI_ROOT/managers/debian.sh CLEANUP
|
||||||
before_install:
|
|
||||||
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
|
|
||||||
- docker --version
|
|
||||||
install:
|
|
||||||
- $CI_MANAGERS/debian.sh SETUP
|
|
||||||
before_script: true
|
|
||||||
script:
|
|
||||||
- $CI_MANAGERS/debian.sh RUN_ASAN || travis_terminate
|
|
||||||
after_script:
|
|
||||||
- $CI_MANAGERS/debian.sh CLEANUP
|
|
||||||
|
|
||||||
- name: Debian Testing (clang)
|
- name: Debian Build (clang)
|
||||||
language: bash
|
language: bash
|
||||||
env:
|
install: $CI_ROOT/managers/debian.sh SETUP
|
||||||
- DEBIAN_RELEASE="testing"
|
script: $CI_ROOT/managers/debian.sh RUN_CLANG || travis_terminate
|
||||||
- CONT_NAME="libbpf-debian-$DEBIAN_RELEASE"
|
after_script: $CI_ROOT/managers/debian.sh CLEANUP
|
||||||
before_install:
|
|
||||||
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
|
|
||||||
- docker --version
|
|
||||||
install:
|
|
||||||
- $CI_MANAGERS/debian.sh SETUP
|
|
||||||
before_script: true
|
|
||||||
script:
|
|
||||||
- $CI_MANAGERS/debian.sh RUN_CLANG || travis_terminate
|
|
||||||
after_script:
|
|
||||||
- $CI_MANAGERS/debian.sh CLEANUP
|
|
||||||
|
|
||||||
- name: Debian Testing (clang ASan+UBSan)
|
- name: Debian Build (clang ASan+UBSan)
|
||||||
language: bash
|
language: bash
|
||||||
env:
|
install: $CI_ROOT/managers/debian.sh SETUP
|
||||||
- DEBIAN_RELEASE="testing"
|
script: $CI_ROOT/managers/debian.sh RUN_CLANG_ASAN || travis_terminate
|
||||||
- CONT_NAME="libbpf-debian-$DEBIAN_RELEASE"
|
after_script: $CI_ROOT/managers/debian.sh CLEANUP
|
||||||
before_install:
|
|
||||||
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
|
|
||||||
- docker --version
|
|
||||||
install:
|
|
||||||
- $CI_MANAGERS/debian.sh SETUP
|
|
||||||
before_script: true
|
|
||||||
script:
|
|
||||||
- $CI_MANAGERS/debian.sh RUN_CLANG_ASAN || travis_terminate
|
|
||||||
after_script:
|
|
||||||
- $CI_MANAGERS/debian.sh CLEANUP
|
|
||||||
|
|
||||||
- name: Debian Testing (gcc-8)
|
- name: Debian Build (gcc-8)
|
||||||
language: bash
|
language: bash
|
||||||
env:
|
install: $CI_ROOT/managers/debian.sh SETUP
|
||||||
- DEBIAN_RELEASE="testing"
|
script: $CI_ROOT/managers/debian.sh RUN_GCC8 || travis_terminate
|
||||||
- CONT_NAME="libbpf-debian-$DEBIAN_RELEASE"
|
after_script: $CI_ROOT/managers/debian.sh CLEANUP
|
||||||
before_install:
|
|
||||||
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
|
|
||||||
- docker --version
|
|
||||||
install:
|
|
||||||
- $CI_MANAGERS/debian.sh SETUP
|
|
||||||
before_script: true
|
|
||||||
script:
|
|
||||||
- $CI_MANAGERS/debian.sh RUN_GCC8 || travis_terminate
|
|
||||||
after_script:
|
|
||||||
- $CI_MANAGERS/debian.sh CLEANUP
|
|
||||||
|
|
||||||
- name: Debian Testing (gcc-8 ASan+UBSan)
|
- name: Debian Build (gcc-8 ASan+UBSan)
|
||||||
language: bash
|
language: bash
|
||||||
env:
|
install: $CI_ROOT/managers/debian.sh SETUP
|
||||||
- DEBIAN_RELEASE="testing"
|
script: $CI_ROOT/managers/debian.sh RUN_GCC8_ASAN || travis_terminate
|
||||||
- CONT_NAME="libbpf-debian-$DEBIAN_RELEASE"
|
after_script: $CI_ROOT/managers/debian.sh CLEANUP
|
||||||
before_install:
|
|
||||||
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
|
|
||||||
- docker --version
|
|
||||||
install:
|
|
||||||
- $CI_MANAGERS/debian.sh SETUP
|
|
||||||
before_script: true
|
|
||||||
script:
|
|
||||||
- $CI_MANAGERS/debian.sh RUN_GCC8_ASAN || travis_terminate
|
|
||||||
after_script:
|
|
||||||
- $CI_MANAGERS/debian.sh CLEANUP
|
|
||||||
|
|
||||||
- name: Ubuntu Bionic
|
- name: Ubuntu Bionic Build
|
||||||
language: bash
|
language: bash
|
||||||
before_script: true
|
script: sudo $CI_ROOT/managers/ubuntu.sh || travis_terminate
|
||||||
script:
|
|
||||||
- sudo $CI_MANAGERS/ubuntu.sh || travis_terminate
|
|
||||||
|
|
||||||
- name: Ubuntu Bionic (arm)
|
- name: Ubuntu Bionic Build (arm)
|
||||||
arch: arm64
|
arch: arm64
|
||||||
language: bash
|
language: bash
|
||||||
before_script: true
|
script: sudo $CI_ROOT/managers/ubuntu.sh || travis_terminate
|
||||||
script:
|
|
||||||
- sudo $CI_MANAGERS/ubuntu.sh || travis_terminate
|
|
||||||
|
|
||||||
- name: Ubuntu Bionic (s390x)
|
- name: Ubuntu Bionic Build (s390x)
|
||||||
arch: s390x
|
arch: s390x
|
||||||
language: bash
|
language: bash
|
||||||
before_script: true
|
script: sudo $CI_ROOT/managers/ubuntu.sh || travis_terminate
|
||||||
script:
|
|
||||||
- sudo $CI_MANAGERS/ubuntu.sh || travis_terminate
|
|
||||||
|
|
||||||
- name: Ubuntu Bionic (ppc64le)
|
- name: Ubuntu Bionic Build (ppc64le)
|
||||||
arch: ppc64le
|
arch: ppc64le
|
||||||
language: bash
|
language: bash
|
||||||
before_script: true
|
script: sudo $CI_ROOT/managers/ubuntu.sh || travis_terminate
|
||||||
script:
|
|
||||||
- sudo $CI_MANAGERS/ubuntu.sh || travis_terminate
|
- stage: Build & Test
|
||||||
|
name: Kernel 5.5.0 + selftests
|
||||||
|
language: bash
|
||||||
|
env: KERNEL=5.5.0
|
||||||
|
script: $CI_ROOT/vmtest/run_vmtest.sh || travis_terminate
|
||||||
|
|
||||||
|
- name: Kernel LATEST + selftests
|
||||||
|
language: bash
|
||||||
|
env: KERNEL=LATEST
|
||||||
|
script: $CI_ROOT/vmtest/run_vmtest.sh || travis_terminate
|
||||||
|
|
||||||
- stage: Coverity
|
- stage: Coverity
|
||||||
language: bash
|
language: bash
|
||||||
@@ -205,7 +120,5 @@ 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 @@
|
|||||||
08dc225d8868d5094ada62f471ebdfcce9dbc298
|
edadedf1c5b4e4404192a0a4c3c0c05e3b7672ab
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
35b9211c0a2427e8f39e534f442f43804fc8d5ca
|
2fcd80144b93ff90836a44f2054b4d82133d3a85
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ struct bpf_insn {
|
|||||||
/* Key of an a BPF_MAP_TYPE_LPM_TRIE entry */
|
/* Key of an a BPF_MAP_TYPE_LPM_TRIE entry */
|
||||||
struct bpf_lpm_trie_key {
|
struct bpf_lpm_trie_key {
|
||||||
__u32 prefixlen; /* up to 32 for AF_INET, 128 for AF_INET6 */
|
__u32 prefixlen; /* up to 32 for AF_INET, 128 for AF_INET6 */
|
||||||
__u8 data[0]; /* Arbitrary size */
|
__u8 data[]; /* Arbitrary size */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bpf_cgroup_storage_key {
|
struct bpf_cgroup_storage_key {
|
||||||
@@ -111,6 +111,8 @@ enum bpf_cmd {
|
|||||||
BPF_MAP_LOOKUP_AND_DELETE_BATCH,
|
BPF_MAP_LOOKUP_AND_DELETE_BATCH,
|
||||||
BPF_MAP_UPDATE_BATCH,
|
BPF_MAP_UPDATE_BATCH,
|
||||||
BPF_MAP_DELETE_BATCH,
|
BPF_MAP_DELETE_BATCH,
|
||||||
|
BPF_LINK_CREATE,
|
||||||
|
BPF_LINK_UPDATE,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum bpf_map_type {
|
enum bpf_map_type {
|
||||||
@@ -181,6 +183,7 @@ enum bpf_prog_type {
|
|||||||
BPF_PROG_TYPE_TRACING,
|
BPF_PROG_TYPE_TRACING,
|
||||||
BPF_PROG_TYPE_STRUCT_OPS,
|
BPF_PROG_TYPE_STRUCT_OPS,
|
||||||
BPF_PROG_TYPE_EXT,
|
BPF_PROG_TYPE_EXT,
|
||||||
|
BPF_PROG_TYPE_LSM,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum bpf_attach_type {
|
enum bpf_attach_type {
|
||||||
@@ -210,6 +213,8 @@ enum bpf_attach_type {
|
|||||||
BPF_TRACE_RAW_TP,
|
BPF_TRACE_RAW_TP,
|
||||||
BPF_TRACE_FENTRY,
|
BPF_TRACE_FENTRY,
|
||||||
BPF_TRACE_FEXIT,
|
BPF_TRACE_FEXIT,
|
||||||
|
BPF_MODIFY_RETURN,
|
||||||
|
BPF_LSM_MAC,
|
||||||
__MAX_BPF_ATTACH_TYPE
|
__MAX_BPF_ATTACH_TYPE
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -325,44 +330,46 @@ enum bpf_attach_type {
|
|||||||
#define BPF_PSEUDO_CALL 1
|
#define BPF_PSEUDO_CALL 1
|
||||||
|
|
||||||
/* flags for BPF_MAP_UPDATE_ELEM command */
|
/* flags for BPF_MAP_UPDATE_ELEM command */
|
||||||
#define BPF_ANY 0 /* create new element or update existing */
|
enum {
|
||||||
#define BPF_NOEXIST 1 /* create new element if it didn't exist */
|
BPF_ANY = 0, /* create new element or update existing */
|
||||||
#define BPF_EXIST 2 /* update existing element */
|
BPF_NOEXIST = 1, /* create new element if it didn't exist */
|
||||||
#define BPF_F_LOCK 4 /* spin_lock-ed map_lookup/map_update */
|
BPF_EXIST = 2, /* update existing element */
|
||||||
|
BPF_F_LOCK = 4, /* spin_lock-ed map_lookup/map_update */
|
||||||
|
};
|
||||||
|
|
||||||
/* flags for BPF_MAP_CREATE command */
|
/* flags for BPF_MAP_CREATE command */
|
||||||
#define BPF_F_NO_PREALLOC (1U << 0)
|
enum {
|
||||||
|
BPF_F_NO_PREALLOC = (1U << 0),
|
||||||
/* Instead of having one common LRU list in the
|
/* Instead of having one common LRU list in the
|
||||||
* BPF_MAP_TYPE_LRU_[PERCPU_]HASH map, use a percpu LRU list
|
* BPF_MAP_TYPE_LRU_[PERCPU_]HASH map, use a percpu LRU list
|
||||||
* which can scale and perform better.
|
* which can scale and perform better.
|
||||||
* Note, the LRU nodes (including free nodes) cannot be moved
|
* Note, the LRU nodes (including free nodes) cannot be moved
|
||||||
* across different LRU lists.
|
* across different LRU lists.
|
||||||
*/
|
*/
|
||||||
#define BPF_F_NO_COMMON_LRU (1U << 1)
|
BPF_F_NO_COMMON_LRU = (1U << 1),
|
||||||
/* Specify numa node during map creation */
|
/* Specify numa node during map creation */
|
||||||
#define BPF_F_NUMA_NODE (1U << 2)
|
BPF_F_NUMA_NODE = (1U << 2),
|
||||||
|
|
||||||
#define BPF_OBJ_NAME_LEN 16U
|
|
||||||
|
|
||||||
/* Flags for accessing BPF object from syscall side. */
|
/* Flags for accessing BPF object from syscall side. */
|
||||||
#define BPF_F_RDONLY (1U << 3)
|
BPF_F_RDONLY = (1U << 3),
|
||||||
#define BPF_F_WRONLY (1U << 4)
|
BPF_F_WRONLY = (1U << 4),
|
||||||
|
|
||||||
/* Flag for stack_map, store build_id+offset instead of pointer */
|
/* Flag for stack_map, store build_id+offset instead of pointer */
|
||||||
#define BPF_F_STACK_BUILD_ID (1U << 5)
|
BPF_F_STACK_BUILD_ID = (1U << 5),
|
||||||
|
|
||||||
/* Zero-initialize hash function seed. This should only be used for testing. */
|
/* Zero-initialize hash function seed. This should only be used for testing. */
|
||||||
#define BPF_F_ZERO_SEED (1U << 6)
|
BPF_F_ZERO_SEED = (1U << 6),
|
||||||
|
|
||||||
/* Flags for accessing BPF object from program side. */
|
/* Flags for accessing BPF object from program side. */
|
||||||
#define BPF_F_RDONLY_PROG (1U << 7)
|
BPF_F_RDONLY_PROG = (1U << 7),
|
||||||
#define BPF_F_WRONLY_PROG (1U << 8)
|
BPF_F_WRONLY_PROG = (1U << 8),
|
||||||
|
|
||||||
/* Clone map from listener for newly accepted socket */
|
/* Clone map from listener for newly accepted socket */
|
||||||
#define BPF_F_CLONE (1U << 9)
|
BPF_F_CLONE = (1U << 9),
|
||||||
|
|
||||||
/* Enable memory-mapping BPF map */
|
/* Enable memory-mapping BPF map */
|
||||||
#define BPF_F_MMAPABLE (1U << 10)
|
BPF_F_MMAPABLE = (1U << 10),
|
||||||
|
};
|
||||||
|
|
||||||
/* Flags for BPF_PROG_QUERY. */
|
/* Flags for BPF_PROG_QUERY. */
|
||||||
|
|
||||||
@@ -391,6 +398,8 @@ struct bpf_stack_build_id {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define BPF_OBJ_NAME_LEN 16U
|
||||||
|
|
||||||
union bpf_attr {
|
union bpf_attr {
|
||||||
struct { /* anonymous struct used by BPF_MAP_CREATE command */
|
struct { /* anonymous struct used by BPF_MAP_CREATE command */
|
||||||
__u32 map_type; /* one of enum bpf_map_type */
|
__u32 map_type; /* one of enum bpf_map_type */
|
||||||
@@ -534,7 +543,7 @@ union bpf_attr {
|
|||||||
__u32 prog_cnt;
|
__u32 prog_cnt;
|
||||||
} query;
|
} query;
|
||||||
|
|
||||||
struct {
|
struct { /* anonymous struct used by BPF_RAW_TRACEPOINT_OPEN command */
|
||||||
__u64 name;
|
__u64 name;
|
||||||
__u32 prog_fd;
|
__u32 prog_fd;
|
||||||
} raw_tracepoint;
|
} raw_tracepoint;
|
||||||
@@ -562,6 +571,24 @@ union bpf_attr {
|
|||||||
__u64 probe_offset; /* output: probe_offset */
|
__u64 probe_offset; /* output: probe_offset */
|
||||||
__u64 probe_addr; /* output: probe_addr */
|
__u64 probe_addr; /* output: probe_addr */
|
||||||
} task_fd_query;
|
} task_fd_query;
|
||||||
|
|
||||||
|
struct { /* struct used by BPF_LINK_CREATE command */
|
||||||
|
__u32 prog_fd; /* eBPF program to attach */
|
||||||
|
__u32 target_fd; /* object to attach to */
|
||||||
|
__u32 attach_type; /* attach type */
|
||||||
|
__u32 flags; /* extra flags */
|
||||||
|
} link_create;
|
||||||
|
|
||||||
|
struct { /* struct used by BPF_LINK_UPDATE command */
|
||||||
|
__u32 link_fd; /* link fd */
|
||||||
|
/* new program fd to update link with */
|
||||||
|
__u32 new_prog_fd;
|
||||||
|
__u32 flags; /* extra flags */
|
||||||
|
/* expected link's program fd; is specified only if
|
||||||
|
* BPF_F_REPLACE flag is set in flags */
|
||||||
|
__u32 old_prog_fd;
|
||||||
|
} link_update;
|
||||||
|
|
||||||
} __attribute__((aligned(8)));
|
} __attribute__((aligned(8)));
|
||||||
|
|
||||||
/* The description below is an attempt at providing documentation to eBPF
|
/* The description below is an attempt at providing documentation to eBPF
|
||||||
@@ -1045,9 +1072,9 @@ union bpf_attr {
|
|||||||
* supports redirection to the egress interface, and accepts no
|
* supports redirection to the egress interface, and accepts no
|
||||||
* flag at all.
|
* flag at all.
|
||||||
*
|
*
|
||||||
* The same effect can be attained with the more generic
|
* The same effect can also be attained with the more generic
|
||||||
* **bpf_redirect_map**\ (), which requires specific maps to be
|
* **bpf_redirect_map**\ (), which uses a BPF map to store the
|
||||||
* used but offers better performance.
|
* redirect target instead of providing it directly to the helper.
|
||||||
* Return
|
* Return
|
||||||
* For XDP, the helper returns **XDP_REDIRECT** on success or
|
* For XDP, the helper returns **XDP_REDIRECT** on success or
|
||||||
* **XDP_ABORTED** on error. For other program types, the values
|
* **XDP_ABORTED** on error. For other program types, the values
|
||||||
@@ -1611,13 +1638,11 @@ union bpf_attr {
|
|||||||
* the caller. Any higher bits in the *flags* argument must be
|
* the caller. Any higher bits in the *flags* argument must be
|
||||||
* unset.
|
* unset.
|
||||||
*
|
*
|
||||||
* When used to redirect packets to net devices, this helper
|
* See also bpf_redirect(), which only supports redirecting to an
|
||||||
* provides a high performance increase over **bpf_redirect**\ ().
|
* ifindex, but doesn't require a map to do so.
|
||||||
* This is due to various implementation details of the underlying
|
|
||||||
* mechanisms, one of which is the fact that **bpf_redirect_map**\
|
|
||||||
* () tries to send packet as a "bulk" to the device.
|
|
||||||
* Return
|
* Return
|
||||||
* **XDP_REDIRECT** on success, or **XDP_ABORTED** on error.
|
* **XDP_REDIRECT** on success, or the value of the two lower bits
|
||||||
|
* of the **flags* argument on error.
|
||||||
*
|
*
|
||||||
* int bpf_sk_redirect_map(struct sk_buff *skb, struct bpf_map *map, u32 key, u64 flags)
|
* int bpf_sk_redirect_map(struct sk_buff *skb, struct bpf_map *map, u32 key, u64 flags)
|
||||||
* Description
|
* Description
|
||||||
@@ -2892,6 +2917,114 @@ union bpf_attr {
|
|||||||
* Obtain the 64bit jiffies
|
* Obtain the 64bit jiffies
|
||||||
* Return
|
* Return
|
||||||
* The 64 bit jiffies
|
* The 64 bit jiffies
|
||||||
|
*
|
||||||
|
* int bpf_read_branch_records(struct bpf_perf_event_data *ctx, void *buf, u32 size, u64 flags)
|
||||||
|
* Description
|
||||||
|
* For an eBPF program attached to a perf event, retrieve the
|
||||||
|
* branch records (struct perf_branch_entry) associated to *ctx*
|
||||||
|
* and store it in the buffer pointed by *buf* up to size
|
||||||
|
* *size* bytes.
|
||||||
|
* Return
|
||||||
|
* On success, number of bytes written to *buf*. On error, a
|
||||||
|
* negative value.
|
||||||
|
*
|
||||||
|
* The *flags* can be set to **BPF_F_GET_BRANCH_RECORDS_SIZE** to
|
||||||
|
* instead return the number of bytes required to store all the
|
||||||
|
* branch entries. If this flag is set, *buf* may be NULL.
|
||||||
|
*
|
||||||
|
* **-EINVAL** if arguments invalid or **size** not a multiple
|
||||||
|
* of sizeof(struct perf_branch_entry).
|
||||||
|
*
|
||||||
|
* **-ENOENT** if architecture does not support branch records.
|
||||||
|
*
|
||||||
|
* int bpf_get_ns_current_pid_tgid(u64 dev, u64 ino, struct bpf_pidns_info *nsdata, u32 size)
|
||||||
|
* Description
|
||||||
|
* Returns 0 on success, values for *pid* and *tgid* as seen from the current
|
||||||
|
* *namespace* will be returned in *nsdata*.
|
||||||
|
*
|
||||||
|
* On failure, the returned value is one of the following:
|
||||||
|
*
|
||||||
|
* **-EINVAL** if dev and inum supplied don't match dev_t and inode number
|
||||||
|
* with nsfs of current task, or if dev conversion to dev_t lost high bits.
|
||||||
|
*
|
||||||
|
* **-ENOENT** if pidns does not exists for the current task.
|
||||||
|
*
|
||||||
|
* int bpf_xdp_output(void *ctx, struct bpf_map *map, u64 flags, void *data, u64 size)
|
||||||
|
* Description
|
||||||
|
* Write raw *data* blob into a special BPF perf event held by
|
||||||
|
* *map* of type **BPF_MAP_TYPE_PERF_EVENT_ARRAY**. This perf
|
||||||
|
* event must have the following attributes: **PERF_SAMPLE_RAW**
|
||||||
|
* as **sample_type**, **PERF_TYPE_SOFTWARE** as **type**, and
|
||||||
|
* **PERF_COUNT_SW_BPF_OUTPUT** as **config**.
|
||||||
|
*
|
||||||
|
* The *flags* are used to indicate the index in *map* for which
|
||||||
|
* the value must be put, masked with **BPF_F_INDEX_MASK**.
|
||||||
|
* Alternatively, *flags* can be set to **BPF_F_CURRENT_CPU**
|
||||||
|
* to indicate that the index of the current CPU core should be
|
||||||
|
* used.
|
||||||
|
*
|
||||||
|
* The value to write, of *size*, is passed through eBPF stack and
|
||||||
|
* pointed by *data*.
|
||||||
|
*
|
||||||
|
* *ctx* is a pointer to in-kernel struct xdp_buff.
|
||||||
|
*
|
||||||
|
* This helper is similar to **bpf_perf_eventoutput**\ () but
|
||||||
|
* restricted to raw_tracepoint bpf programs.
|
||||||
|
* Return
|
||||||
|
* 0 on success, or a negative error in case of failure.
|
||||||
|
*
|
||||||
|
* u64 bpf_get_netns_cookie(void *ctx)
|
||||||
|
* Description
|
||||||
|
* Retrieve the cookie (generated by the kernel) of the network
|
||||||
|
* namespace the input *ctx* is associated with. The network
|
||||||
|
* namespace cookie remains stable for its lifetime and provides
|
||||||
|
* a global identifier that can be assumed unique. If *ctx* is
|
||||||
|
* NULL, then the helper returns the cookie for the initial
|
||||||
|
* network namespace. The cookie itself is very similar to that
|
||||||
|
* of bpf_get_socket_cookie() helper, but for network namespaces
|
||||||
|
* instead of sockets.
|
||||||
|
* Return
|
||||||
|
* A 8-byte long opaque number.
|
||||||
|
*
|
||||||
|
* u64 bpf_get_current_ancestor_cgroup_id(int ancestor_level)
|
||||||
|
* Description
|
||||||
|
* Return id of cgroup v2 that is ancestor of the cgroup associated
|
||||||
|
* with the current task at the *ancestor_level*. The root cgroup
|
||||||
|
* is at *ancestor_level* zero and each step down the hierarchy
|
||||||
|
* increments the level. If *ancestor_level* == level of cgroup
|
||||||
|
* associated with the current task, then return value will be the
|
||||||
|
* same as that of **bpf_get_current_cgroup_id**\ ().
|
||||||
|
*
|
||||||
|
* The helper is useful to implement policies based on cgroups
|
||||||
|
* that are upper in hierarchy than immediate cgroup associated
|
||||||
|
* with the current task.
|
||||||
|
*
|
||||||
|
* The format of returned id and helper limitations are same as in
|
||||||
|
* **bpf_get_current_cgroup_id**\ ().
|
||||||
|
* Return
|
||||||
|
* The id is returned or 0 in case the id could not be retrieved.
|
||||||
|
*
|
||||||
|
* int bpf_sk_assign(struct sk_buff *skb, struct bpf_sock *sk, u64 flags)
|
||||||
|
* Description
|
||||||
|
* Assign the *sk* to the *skb*. When combined with appropriate
|
||||||
|
* routing configuration to receive the packet towards the socket,
|
||||||
|
* will cause *skb* to be delivered to the specified socket.
|
||||||
|
* Subsequent redirection of *skb* via **bpf_redirect**\ (),
|
||||||
|
* **bpf_clone_redirect**\ () or other methods outside of BPF may
|
||||||
|
* interfere with successful delivery to the socket.
|
||||||
|
*
|
||||||
|
* This operation is only valid from TC ingress path.
|
||||||
|
*
|
||||||
|
* The *flags* argument must be zero.
|
||||||
|
* Return
|
||||||
|
* 0 on success, or a negative errno in case of failure.
|
||||||
|
*
|
||||||
|
* * **-EINVAL** Unsupported flags specified.
|
||||||
|
* * **-ENOENT** Socket is unavailable for assignment.
|
||||||
|
* * **-ENETUNREACH** Socket is unreachable (wrong netns).
|
||||||
|
* * **-EOPNOTSUPP** Unsupported operation, for example a
|
||||||
|
* call from outside of TC ingress.
|
||||||
|
* * **-ESOCKTNOSUPPORT** Socket type not supported (reuseport).
|
||||||
*/
|
*/
|
||||||
#define __BPF_FUNC_MAPPER(FN) \
|
#define __BPF_FUNC_MAPPER(FN) \
|
||||||
FN(unspec), \
|
FN(unspec), \
|
||||||
@@ -3012,7 +3145,13 @@ union bpf_attr {
|
|||||||
FN(probe_read_kernel_str), \
|
FN(probe_read_kernel_str), \
|
||||||
FN(tcp_send_ack), \
|
FN(tcp_send_ack), \
|
||||||
FN(send_signal_thread), \
|
FN(send_signal_thread), \
|
||||||
FN(jiffies64),
|
FN(jiffies64), \
|
||||||
|
FN(read_branch_records), \
|
||||||
|
FN(get_ns_current_pid_tgid), \
|
||||||
|
FN(xdp_output), \
|
||||||
|
FN(get_netns_cookie), \
|
||||||
|
FN(get_current_ancestor_cgroup_id), \
|
||||||
|
FN(sk_assign),
|
||||||
|
|
||||||
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
|
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
|
||||||
* function eBPF program intends to call
|
* function eBPF program intends to call
|
||||||
@@ -3027,69 +3166,100 @@ enum bpf_func_id {
|
|||||||
/* All flags used by eBPF helper functions, placed here. */
|
/* All flags used by eBPF helper functions, placed here. */
|
||||||
|
|
||||||
/* BPF_FUNC_skb_store_bytes flags. */
|
/* BPF_FUNC_skb_store_bytes flags. */
|
||||||
#define BPF_F_RECOMPUTE_CSUM (1ULL << 0)
|
enum {
|
||||||
#define BPF_F_INVALIDATE_HASH (1ULL << 1)
|
BPF_F_RECOMPUTE_CSUM = (1ULL << 0),
|
||||||
|
BPF_F_INVALIDATE_HASH = (1ULL << 1),
|
||||||
|
};
|
||||||
|
|
||||||
/* BPF_FUNC_l3_csum_replace and BPF_FUNC_l4_csum_replace flags.
|
/* BPF_FUNC_l3_csum_replace and BPF_FUNC_l4_csum_replace flags.
|
||||||
* First 4 bits are for passing the header field size.
|
* First 4 bits are for passing the header field size.
|
||||||
*/
|
*/
|
||||||
#define BPF_F_HDR_FIELD_MASK 0xfULL
|
enum {
|
||||||
|
BPF_F_HDR_FIELD_MASK = 0xfULL,
|
||||||
|
};
|
||||||
|
|
||||||
/* BPF_FUNC_l4_csum_replace flags. */
|
/* BPF_FUNC_l4_csum_replace flags. */
|
||||||
#define BPF_F_PSEUDO_HDR (1ULL << 4)
|
enum {
|
||||||
#define BPF_F_MARK_MANGLED_0 (1ULL << 5)
|
BPF_F_PSEUDO_HDR = (1ULL << 4),
|
||||||
#define BPF_F_MARK_ENFORCE (1ULL << 6)
|
BPF_F_MARK_MANGLED_0 = (1ULL << 5),
|
||||||
|
BPF_F_MARK_ENFORCE = (1ULL << 6),
|
||||||
|
};
|
||||||
|
|
||||||
/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */
|
/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */
|
||||||
#define BPF_F_INGRESS (1ULL << 0)
|
enum {
|
||||||
|
BPF_F_INGRESS = (1ULL << 0),
|
||||||
|
};
|
||||||
|
|
||||||
/* BPF_FUNC_skb_set_tunnel_key and BPF_FUNC_skb_get_tunnel_key flags. */
|
/* BPF_FUNC_skb_set_tunnel_key and BPF_FUNC_skb_get_tunnel_key flags. */
|
||||||
#define BPF_F_TUNINFO_IPV6 (1ULL << 0)
|
enum {
|
||||||
|
BPF_F_TUNINFO_IPV6 = (1ULL << 0),
|
||||||
|
};
|
||||||
|
|
||||||
/* flags for both BPF_FUNC_get_stackid and BPF_FUNC_get_stack. */
|
/* flags for both BPF_FUNC_get_stackid and BPF_FUNC_get_stack. */
|
||||||
#define BPF_F_SKIP_FIELD_MASK 0xffULL
|
enum {
|
||||||
#define BPF_F_USER_STACK (1ULL << 8)
|
BPF_F_SKIP_FIELD_MASK = 0xffULL,
|
||||||
|
BPF_F_USER_STACK = (1ULL << 8),
|
||||||
/* flags used by BPF_FUNC_get_stackid only. */
|
/* flags used by BPF_FUNC_get_stackid only. */
|
||||||
#define BPF_F_FAST_STACK_CMP (1ULL << 9)
|
BPF_F_FAST_STACK_CMP = (1ULL << 9),
|
||||||
#define BPF_F_REUSE_STACKID (1ULL << 10)
|
BPF_F_REUSE_STACKID = (1ULL << 10),
|
||||||
/* flags used by BPF_FUNC_get_stack only. */
|
/* flags used by BPF_FUNC_get_stack only. */
|
||||||
#define BPF_F_USER_BUILD_ID (1ULL << 11)
|
BPF_F_USER_BUILD_ID = (1ULL << 11),
|
||||||
|
};
|
||||||
|
|
||||||
/* BPF_FUNC_skb_set_tunnel_key flags. */
|
/* BPF_FUNC_skb_set_tunnel_key flags. */
|
||||||
#define BPF_F_ZERO_CSUM_TX (1ULL << 1)
|
enum {
|
||||||
#define BPF_F_DONT_FRAGMENT (1ULL << 2)
|
BPF_F_ZERO_CSUM_TX = (1ULL << 1),
|
||||||
#define BPF_F_SEQ_NUMBER (1ULL << 3)
|
BPF_F_DONT_FRAGMENT = (1ULL << 2),
|
||||||
|
BPF_F_SEQ_NUMBER = (1ULL << 3),
|
||||||
|
};
|
||||||
|
|
||||||
/* BPF_FUNC_perf_event_output, BPF_FUNC_perf_event_read and
|
/* BPF_FUNC_perf_event_output, BPF_FUNC_perf_event_read and
|
||||||
* BPF_FUNC_perf_event_read_value flags.
|
* BPF_FUNC_perf_event_read_value flags.
|
||||||
*/
|
*/
|
||||||
#define BPF_F_INDEX_MASK 0xffffffffULL
|
enum {
|
||||||
#define BPF_F_CURRENT_CPU BPF_F_INDEX_MASK
|
BPF_F_INDEX_MASK = 0xffffffffULL,
|
||||||
|
BPF_F_CURRENT_CPU = BPF_F_INDEX_MASK,
|
||||||
/* BPF_FUNC_perf_event_output for sk_buff input context. */
|
/* BPF_FUNC_perf_event_output for sk_buff input context. */
|
||||||
#define BPF_F_CTXLEN_MASK (0xfffffULL << 32)
|
BPF_F_CTXLEN_MASK = (0xfffffULL << 32),
|
||||||
|
};
|
||||||
|
|
||||||
/* Current network namespace */
|
/* Current network namespace */
|
||||||
#define BPF_F_CURRENT_NETNS (-1L)
|
enum {
|
||||||
|
BPF_F_CURRENT_NETNS = (-1L),
|
||||||
|
};
|
||||||
|
|
||||||
/* BPF_FUNC_skb_adjust_room flags. */
|
/* BPF_FUNC_skb_adjust_room flags. */
|
||||||
#define BPF_F_ADJ_ROOM_FIXED_GSO (1ULL << 0)
|
enum {
|
||||||
|
BPF_F_ADJ_ROOM_FIXED_GSO = (1ULL << 0),
|
||||||
|
BPF_F_ADJ_ROOM_ENCAP_L3_IPV4 = (1ULL << 1),
|
||||||
|
BPF_F_ADJ_ROOM_ENCAP_L3_IPV6 = (1ULL << 2),
|
||||||
|
BPF_F_ADJ_ROOM_ENCAP_L4_GRE = (1ULL << 3),
|
||||||
|
BPF_F_ADJ_ROOM_ENCAP_L4_UDP = (1ULL << 4),
|
||||||
|
};
|
||||||
|
|
||||||
#define BPF_ADJ_ROOM_ENCAP_L2_MASK 0xff
|
enum {
|
||||||
#define BPF_ADJ_ROOM_ENCAP_L2_SHIFT 56
|
BPF_ADJ_ROOM_ENCAP_L2_MASK = 0xff,
|
||||||
|
BPF_ADJ_ROOM_ENCAP_L2_SHIFT = 56,
|
||||||
|
};
|
||||||
|
|
||||||
#define BPF_F_ADJ_ROOM_ENCAP_L3_IPV4 (1ULL << 1)
|
|
||||||
#define BPF_F_ADJ_ROOM_ENCAP_L3_IPV6 (1ULL << 2)
|
|
||||||
#define BPF_F_ADJ_ROOM_ENCAP_L4_GRE (1ULL << 3)
|
|
||||||
#define BPF_F_ADJ_ROOM_ENCAP_L4_UDP (1ULL << 4)
|
|
||||||
#define BPF_F_ADJ_ROOM_ENCAP_L2(len) (((__u64)len & \
|
#define BPF_F_ADJ_ROOM_ENCAP_L2(len) (((__u64)len & \
|
||||||
BPF_ADJ_ROOM_ENCAP_L2_MASK) \
|
BPF_ADJ_ROOM_ENCAP_L2_MASK) \
|
||||||
<< BPF_ADJ_ROOM_ENCAP_L2_SHIFT)
|
<< BPF_ADJ_ROOM_ENCAP_L2_SHIFT)
|
||||||
|
|
||||||
/* BPF_FUNC_sysctl_get_name flags. */
|
/* BPF_FUNC_sysctl_get_name flags. */
|
||||||
#define BPF_F_SYSCTL_BASE_NAME (1ULL << 0)
|
enum {
|
||||||
|
BPF_F_SYSCTL_BASE_NAME = (1ULL << 0),
|
||||||
|
};
|
||||||
|
|
||||||
/* BPF_FUNC_sk_storage_get flags */
|
/* BPF_FUNC_sk_storage_get flags */
|
||||||
#define BPF_SK_STORAGE_GET_F_CREATE (1ULL << 0)
|
enum {
|
||||||
|
BPF_SK_STORAGE_GET_F_CREATE = (1ULL << 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
/* BPF_FUNC_read_branch_records flags. */
|
||||||
|
enum {
|
||||||
|
BPF_F_GET_BRANCH_RECORDS_SIZE = (1ULL << 0),
|
||||||
|
};
|
||||||
|
|
||||||
/* Mode for BPF_FUNC_skb_adjust_room helper. */
|
/* Mode for BPF_FUNC_skb_adjust_room helper. */
|
||||||
enum bpf_adj_room_mode {
|
enum bpf_adj_room_mode {
|
||||||
@@ -3155,6 +3325,7 @@ struct __sk_buff {
|
|||||||
__u32 wire_len;
|
__u32 wire_len;
|
||||||
__u32 gso_segs;
|
__u32 gso_segs;
|
||||||
__bpf_md_ptr(struct bpf_sock *, sk);
|
__bpf_md_ptr(struct bpf_sock *, sk);
|
||||||
|
__u32 gso_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bpf_tunnel_key {
|
struct bpf_tunnel_key {
|
||||||
@@ -3507,13 +3678,14 @@ struct bpf_sock_ops {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Definitions for bpf_sock_ops_cb_flags */
|
/* Definitions for bpf_sock_ops_cb_flags */
|
||||||
#define BPF_SOCK_OPS_RTO_CB_FLAG (1<<0)
|
enum {
|
||||||
#define BPF_SOCK_OPS_RETRANS_CB_FLAG (1<<1)
|
BPF_SOCK_OPS_RTO_CB_FLAG = (1<<0),
|
||||||
#define BPF_SOCK_OPS_STATE_CB_FLAG (1<<2)
|
BPF_SOCK_OPS_RETRANS_CB_FLAG = (1<<1),
|
||||||
#define BPF_SOCK_OPS_RTT_CB_FLAG (1<<3)
|
BPF_SOCK_OPS_STATE_CB_FLAG = (1<<2),
|
||||||
#define BPF_SOCK_OPS_ALL_CB_FLAGS 0xF /* Mask of all currently
|
BPF_SOCK_OPS_RTT_CB_FLAG = (1<<3),
|
||||||
* supported cb flags
|
/* Mask of all currently supported cb flags */
|
||||||
*/
|
BPF_SOCK_OPS_ALL_CB_FLAGS = 0xF,
|
||||||
|
};
|
||||||
|
|
||||||
/* List of known BPF sock_ops operators.
|
/* List of known BPF sock_ops operators.
|
||||||
* New entries can only be added at the end
|
* New entries can only be added at the end
|
||||||
@@ -3592,8 +3764,10 @@ enum {
|
|||||||
BPF_TCP_MAX_STATES /* Leave at the end! */
|
BPF_TCP_MAX_STATES /* Leave at the end! */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TCP_BPF_IW 1001 /* Set TCP initial congestion window */
|
enum {
|
||||||
#define TCP_BPF_SNDCWND_CLAMP 1002 /* Set sndcwnd_clamp */
|
TCP_BPF_IW = 1001, /* Set TCP initial congestion window */
|
||||||
|
TCP_BPF_SNDCWND_CLAMP = 1002, /* Set sndcwnd_clamp */
|
||||||
|
};
|
||||||
|
|
||||||
struct bpf_perf_event_value {
|
struct bpf_perf_event_value {
|
||||||
__u64 counter;
|
__u64 counter;
|
||||||
@@ -3601,12 +3775,16 @@ struct bpf_perf_event_value {
|
|||||||
__u64 running;
|
__u64 running;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BPF_DEVCG_ACC_MKNOD (1ULL << 0)
|
enum {
|
||||||
#define BPF_DEVCG_ACC_READ (1ULL << 1)
|
BPF_DEVCG_ACC_MKNOD = (1ULL << 0),
|
||||||
#define BPF_DEVCG_ACC_WRITE (1ULL << 2)
|
BPF_DEVCG_ACC_READ = (1ULL << 1),
|
||||||
|
BPF_DEVCG_ACC_WRITE = (1ULL << 2),
|
||||||
|
};
|
||||||
|
|
||||||
#define BPF_DEVCG_DEV_BLOCK (1ULL << 0)
|
enum {
|
||||||
#define BPF_DEVCG_DEV_CHAR (1ULL << 1)
|
BPF_DEVCG_DEV_BLOCK = (1ULL << 0),
|
||||||
|
BPF_DEVCG_DEV_CHAR = (1ULL << 1),
|
||||||
|
};
|
||||||
|
|
||||||
struct bpf_cgroup_dev_ctx {
|
struct bpf_cgroup_dev_ctx {
|
||||||
/* access_type encoded as (BPF_DEVCG_ACC_* << 16) | BPF_DEVCG_DEV_* */
|
/* access_type encoded as (BPF_DEVCG_ACC_* << 16) | BPF_DEVCG_DEV_* */
|
||||||
@@ -3622,8 +3800,10 @@ struct bpf_raw_tracepoint_args {
|
|||||||
/* DIRECT: Skip the FIB rules and go to FIB table associated with device
|
/* DIRECT: Skip the FIB rules and go to FIB table associated with device
|
||||||
* OUTPUT: Do lookup from egress perspective; default is ingress
|
* OUTPUT: Do lookup from egress perspective; default is ingress
|
||||||
*/
|
*/
|
||||||
#define BPF_FIB_LOOKUP_DIRECT (1U << 0)
|
enum {
|
||||||
#define BPF_FIB_LOOKUP_OUTPUT (1U << 1)
|
BPF_FIB_LOOKUP_DIRECT = (1U << 0),
|
||||||
|
BPF_FIB_LOOKUP_OUTPUT = (1U << 1),
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
BPF_FIB_LKUP_RET_SUCCESS, /* lookup successful */
|
BPF_FIB_LKUP_RET_SUCCESS, /* lookup successful */
|
||||||
@@ -3695,9 +3875,11 @@ enum bpf_task_fd_type {
|
|||||||
BPF_FD_TYPE_URETPROBE, /* filename + offset */
|
BPF_FD_TYPE_URETPROBE, /* filename + offset */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG (1U << 0)
|
enum {
|
||||||
#define BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL (1U << 1)
|
BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG = (1U << 0),
|
||||||
#define BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP (1U << 2)
|
BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL = (1U << 1),
|
||||||
|
BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP = (1U << 2),
|
||||||
|
};
|
||||||
|
|
||||||
struct bpf_flow_keys {
|
struct bpf_flow_keys {
|
||||||
__u16 nhoff;
|
__u16 nhoff;
|
||||||
@@ -3763,4 +3945,8 @@ struct bpf_sockopt {
|
|||||||
__s32 retval;
|
__s32 retval;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct bpf_pidns_info {
|
||||||
|
__u32 pid;
|
||||||
|
__u32 tgid;
|
||||||
|
};
|
||||||
#endif /* _UAPI__LINUX_BPF_H__ */
|
#endif /* _UAPI__LINUX_BPF_H__ */
|
||||||
|
|||||||
@@ -463,6 +463,7 @@ enum {
|
|||||||
IFLA_MACSEC_REPLAY_PROTECT,
|
IFLA_MACSEC_REPLAY_PROTECT,
|
||||||
IFLA_MACSEC_VALIDATION,
|
IFLA_MACSEC_VALIDATION,
|
||||||
IFLA_MACSEC_PAD,
|
IFLA_MACSEC_PAD,
|
||||||
|
IFLA_MACSEC_OFFLOAD,
|
||||||
__IFLA_MACSEC_MAX,
|
__IFLA_MACSEC_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -489,6 +490,7 @@ enum macsec_validation_type {
|
|||||||
enum macsec_offload {
|
enum macsec_offload {
|
||||||
MACSEC_OFFLOAD_OFF = 0,
|
MACSEC_OFFLOAD_OFF = 0,
|
||||||
MACSEC_OFFLOAD_PHY = 1,
|
MACSEC_OFFLOAD_PHY = 1,
|
||||||
|
MACSEC_OFFLOAD_MAC = 2,
|
||||||
__MACSEC_OFFLOAD_END,
|
__MACSEC_OFFLOAD_END,
|
||||||
MACSEC_OFFLOAD_MAX = __MACSEC_OFFLOAD_END - 1,
|
MACSEC_OFFLOAD_MAX = __MACSEC_OFFLOAD_END - 1,
|
||||||
};
|
};
|
||||||
@@ -960,11 +962,12 @@ enum {
|
|||||||
#define XDP_FLAGS_SKB_MODE (1U << 1)
|
#define XDP_FLAGS_SKB_MODE (1U << 1)
|
||||||
#define XDP_FLAGS_DRV_MODE (1U << 2)
|
#define XDP_FLAGS_DRV_MODE (1U << 2)
|
||||||
#define XDP_FLAGS_HW_MODE (1U << 3)
|
#define XDP_FLAGS_HW_MODE (1U << 3)
|
||||||
|
#define XDP_FLAGS_REPLACE (1U << 4)
|
||||||
#define XDP_FLAGS_MODES (XDP_FLAGS_SKB_MODE | \
|
#define XDP_FLAGS_MODES (XDP_FLAGS_SKB_MODE | \
|
||||||
XDP_FLAGS_DRV_MODE | \
|
XDP_FLAGS_DRV_MODE | \
|
||||||
XDP_FLAGS_HW_MODE)
|
XDP_FLAGS_HW_MODE)
|
||||||
#define XDP_FLAGS_MASK (XDP_FLAGS_UPDATE_IF_NOEXIST | \
|
#define XDP_FLAGS_MASK (XDP_FLAGS_UPDATE_IF_NOEXIST | \
|
||||||
XDP_FLAGS_MODES)
|
XDP_FLAGS_MODES | XDP_FLAGS_REPLACE)
|
||||||
|
|
||||||
/* These are stored into IFLA_XDP_ATTACHED on dump. */
|
/* These are stored into IFLA_XDP_ATTACHED on dump. */
|
||||||
enum {
|
enum {
|
||||||
@@ -984,6 +987,7 @@ enum {
|
|||||||
IFLA_XDP_DRV_PROG_ID,
|
IFLA_XDP_DRV_PROG_ID,
|
||||||
IFLA_XDP_SKB_PROG_ID,
|
IFLA_XDP_SKB_PROG_ID,
|
||||||
IFLA_XDP_HW_PROG_ID,
|
IFLA_XDP_HW_PROG_ID,
|
||||||
|
IFLA_XDP_EXPECTED_FD,
|
||||||
__IFLA_XDP_MAX,
|
__IFLA_XDP_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ PATH_MAP=( \
|
|||||||
[tools/include/tools/libc_compat.h]=include/tools/libc_compat.h \
|
[tools/include/tools/libc_compat.h]=include/tools/libc_compat.h \
|
||||||
)
|
)
|
||||||
|
|
||||||
LIBBPF_PATHS="${!PATH_MAP[@]}"
|
LIBBPF_PATHS="${!PATH_MAP[@]} :^tools/lib/bpf/Makefile :^tools/lib/bpf/Build :^tools/lib/bpf/.gitignore"
|
||||||
LIBBPF_VIEW_PATHS="${PATH_MAP[@]}"
|
LIBBPF_VIEW_PATHS="${PATH_MAP[@]}"
|
||||||
LIBBPF_VIEW_EXCLUDE_REGEX='^src/(Makefile|Build|test_libbpf\.c|bpf_helper_defs\.h|\.gitignore)$'
|
LIBBPF_VIEW_EXCLUDE_REGEX='^src/(Makefile|Build|test_libbpf\.c|bpf_helper_defs\.h|\.gitignore)$'
|
||||||
|
|
||||||
@@ -79,9 +79,10 @@ commit_desc()
|
|||||||
# The idea is that this single-line signature is good enough to make final
|
# The idea is that this single-line signature is good enough to make final
|
||||||
# decision about whether two commits are the same, across different repos.
|
# decision about whether two commits are the same, across different repos.
|
||||||
# $1 - commit ref
|
# $1 - commit ref
|
||||||
|
# $2 - paths filter
|
||||||
commit_signature()
|
commit_signature()
|
||||||
{
|
{
|
||||||
git log -n1 --pretty='("%s")|%aI|%b' --shortstat $1 | tr '\n' '|'
|
git show --pretty='("%s")|%aI|%b' --shortstat $1 -- ${2-.} | tr '\n' '|'
|
||||||
}
|
}
|
||||||
|
|
||||||
# Validate there are no non-empty merges (we can't handle them)
|
# Validate there are no non-empty merges (we can't handle them)
|
||||||
@@ -133,7 +134,7 @@ cherry_pick_commits()
|
|||||||
new_commits=$(git rev-list --no-merges --topo-order --reverse ${baseline_tag}..${tip_tag} ${LIBBPF_PATHS[@]})
|
new_commits=$(git rev-list --no-merges --topo-order --reverse ${baseline_tag}..${tip_tag} ${LIBBPF_PATHS[@]})
|
||||||
for new_commit in ${new_commits}; do
|
for new_commit in ${new_commits}; do
|
||||||
desc="$(commit_desc ${new_commit})"
|
desc="$(commit_desc ${new_commit})"
|
||||||
signature="$(commit_signature ${new_commit})"
|
signature="$(commit_signature ${new_commit} "${LIBBPF_PATHS[@]}")"
|
||||||
synced_cnt=$(grep -F "${signature}" ${TMP_DIR}/libbpf_commits.txt | wc -l)
|
synced_cnt=$(grep -F "${signature}" ${TMP_DIR}/libbpf_commits.txt | wc -l)
|
||||||
manual_check=0
|
manual_check=0
|
||||||
if ((${synced_cnt} > 0)); then
|
if ((${synced_cnt} > 0)); then
|
||||||
|
|||||||
37
src/bpf.c
37
src/bpf.c
@@ -235,7 +235,8 @@ 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_STRUCT_OPS) {
|
if (attr.prog_type == BPF_PROG_TYPE_STRUCT_OPS ||
|
||||||
|
attr.prog_type == BPF_PROG_TYPE_LSM) {
|
||||||
attr.attach_btf_id = load_attr->attach_btf_id;
|
attr.attach_btf_id = load_attr->attach_btf_id;
|
||||||
} else if (attr.prog_type == BPF_PROG_TYPE_TRACING ||
|
} else if (attr.prog_type == BPF_PROG_TYPE_TRACING ||
|
||||||
attr.prog_type == BPF_PROG_TYPE_EXT) {
|
attr.prog_type == BPF_PROG_TYPE_EXT) {
|
||||||
@@ -584,6 +585,40 @@ int bpf_prog_detach2(int prog_fd, int target_fd, enum bpf_attach_type type)
|
|||||||
return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
|
return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bpf_link_create(int prog_fd, int target_fd,
|
||||||
|
enum bpf_attach_type attach_type,
|
||||||
|
const struct bpf_link_create_opts *opts)
|
||||||
|
{
|
||||||
|
union bpf_attr attr;
|
||||||
|
|
||||||
|
if (!OPTS_VALID(opts, bpf_link_create_opts))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
memset(&attr, 0, sizeof(attr));
|
||||||
|
attr.link_create.prog_fd = prog_fd;
|
||||||
|
attr.link_create.target_fd = target_fd;
|
||||||
|
attr.link_create.attach_type = attach_type;
|
||||||
|
|
||||||
|
return sys_bpf(BPF_LINK_CREATE, &attr, sizeof(attr));
|
||||||
|
}
|
||||||
|
|
||||||
|
int bpf_link_update(int link_fd, int new_prog_fd,
|
||||||
|
const struct bpf_link_update_opts *opts)
|
||||||
|
{
|
||||||
|
union bpf_attr attr;
|
||||||
|
|
||||||
|
if (!OPTS_VALID(opts, bpf_link_update_opts))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
memset(&attr, 0, sizeof(attr));
|
||||||
|
attr.link_update.link_fd = link_fd;
|
||||||
|
attr.link_update.new_prog_fd = new_prog_fd;
|
||||||
|
attr.link_update.flags = OPTS_GET(opts, flags, 0);
|
||||||
|
attr.link_update.old_prog_fd = OPTS_GET(opts, old_prog_fd, 0);
|
||||||
|
|
||||||
|
return sys_bpf(BPF_LINK_UPDATE, &attr, sizeof(attr));
|
||||||
|
}
|
||||||
|
|
||||||
int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
|
int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
|
||||||
__u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt)
|
__u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt)
|
||||||
{
|
{
|
||||||
|
|||||||
19
src/bpf.h
19
src/bpf.h
@@ -168,6 +168,25 @@ LIBBPF_API int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type);
|
|||||||
LIBBPF_API int bpf_prog_detach2(int prog_fd, int attachable_fd,
|
LIBBPF_API int bpf_prog_detach2(int prog_fd, int attachable_fd,
|
||||||
enum bpf_attach_type type);
|
enum bpf_attach_type type);
|
||||||
|
|
||||||
|
struct bpf_link_create_opts {
|
||||||
|
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||||
|
};
|
||||||
|
#define bpf_link_create_opts__last_field sz
|
||||||
|
|
||||||
|
LIBBPF_API int bpf_link_create(int prog_fd, int target_fd,
|
||||||
|
enum bpf_attach_type attach_type,
|
||||||
|
const struct bpf_link_create_opts *opts);
|
||||||
|
|
||||||
|
struct bpf_link_update_opts {
|
||||||
|
size_t sz; /* size of this struct for forward/backward compatibility */
|
||||||
|
__u32 flags; /* extra flags */
|
||||||
|
__u32 old_prog_fd; /* expected old program FD */
|
||||||
|
};
|
||||||
|
#define bpf_link_update_opts__last_field old_prog_fd
|
||||||
|
|
||||||
|
LIBBPF_API int bpf_link_update(int link_fd, int new_prog_fd,
|
||||||
|
const struct bpf_link_update_opts *opts);
|
||||||
|
|
||||||
struct bpf_prog_test_run_attr {
|
struct bpf_prog_test_run_attr {
|
||||||
int prog_fd;
|
int prog_fd;
|
||||||
int repeat;
|
int repeat;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
struct bpf_fib_lookup;
|
struct bpf_fib_lookup;
|
||||||
struct bpf_perf_event_data;
|
struct bpf_perf_event_data;
|
||||||
struct bpf_perf_event_value;
|
struct bpf_perf_event_value;
|
||||||
|
struct bpf_pidns_info;
|
||||||
struct bpf_sock;
|
struct bpf_sock;
|
||||||
struct bpf_sock_addr;
|
struct bpf_sock_addr;
|
||||||
struct bpf_sock_ops;
|
struct bpf_sock_ops;
|
||||||
@@ -576,9 +577,9 @@ static __u64 (*bpf_perf_event_read)(void *map, __u64 flags) = (void *) 22;
|
|||||||
* supports redirection to the egress interface, and accepts no
|
* supports redirection to the egress interface, and accepts no
|
||||||
* flag at all.
|
* flag at all.
|
||||||
*
|
*
|
||||||
* The same effect can be attained with the more generic
|
* The same effect can also be attained with the more generic
|
||||||
* **bpf_redirect_map**\ (), which requires specific maps to be
|
* **bpf_redirect_map**\ (), which uses a BPF map to store the
|
||||||
* used but offers better performance.
|
* redirect target instead of providing it directly to the helper.
|
||||||
*
|
*
|
||||||
* Returns
|
* Returns
|
||||||
* For XDP, the helper returns **XDP_REDIRECT** on success or
|
* For XDP, the helper returns **XDP_REDIRECT** on success or
|
||||||
@@ -1242,14 +1243,12 @@ static int (*bpf_skb_adjust_room)(struct __sk_buff *skb, __s32 len_diff, __u32 m
|
|||||||
* the caller. Any higher bits in the *flags* argument must be
|
* the caller. Any higher bits in the *flags* argument must be
|
||||||
* unset.
|
* unset.
|
||||||
*
|
*
|
||||||
* When used to redirect packets to net devices, this helper
|
* See also bpf_redirect(), which only supports redirecting to an
|
||||||
* provides a high performance increase over **bpf_redirect**\ ().
|
* ifindex, but doesn't require a map to do so.
|
||||||
* This is due to various implementation details of the underlying
|
|
||||||
* mechanisms, one of which is the fact that **bpf_redirect_map**\
|
|
||||||
* () tries to send packet as a "bulk" to the device.
|
|
||||||
*
|
*
|
||||||
* Returns
|
* Returns
|
||||||
* **XDP_REDIRECT** on success, or **XDP_ABORTED** on error.
|
* **XDP_REDIRECT** on success, or the value of the two lower bits
|
||||||
|
* of the **flags* argument on error.
|
||||||
*/
|
*/
|
||||||
static int (*bpf_redirect_map)(void *map, __u32 key, __u64 flags) = (void *) 51;
|
static int (*bpf_redirect_map)(void *map, __u32 key, __u64 flags) = (void *) 51;
|
||||||
|
|
||||||
@@ -2796,4 +2795,136 @@ static int (*bpf_send_signal_thread)(__u32 sig) = (void *) 117;
|
|||||||
*/
|
*/
|
||||||
static __u64 (*bpf_jiffies64)(void) = (void *) 118;
|
static __u64 (*bpf_jiffies64)(void) = (void *) 118;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bpf_read_branch_records
|
||||||
|
*
|
||||||
|
* For an eBPF program attached to a perf event, retrieve the
|
||||||
|
* branch records (struct perf_branch_entry) associated to *ctx*
|
||||||
|
* and store it in the buffer pointed by *buf* up to size
|
||||||
|
* *size* bytes.
|
||||||
|
*
|
||||||
|
* Returns
|
||||||
|
* On success, number of bytes written to *buf*. On error, a
|
||||||
|
* negative value.
|
||||||
|
*
|
||||||
|
* The *flags* can be set to **BPF_F_GET_BRANCH_RECORDS_SIZE** to
|
||||||
|
* instead return the number of bytes required to store all the
|
||||||
|
* branch entries. If this flag is set, *buf* may be NULL.
|
||||||
|
*
|
||||||
|
* **-EINVAL** if arguments invalid or **size** not a multiple
|
||||||
|
* of sizeof(struct perf_branch_entry).
|
||||||
|
*
|
||||||
|
* **-ENOENT** if architecture does not support branch records.
|
||||||
|
*/
|
||||||
|
static int (*bpf_read_branch_records)(struct bpf_perf_event_data *ctx, void *buf, __u32 size, __u64 flags) = (void *) 119;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bpf_get_ns_current_pid_tgid
|
||||||
|
*
|
||||||
|
* Returns 0 on success, values for *pid* and *tgid* as seen from the current
|
||||||
|
* *namespace* will be returned in *nsdata*.
|
||||||
|
*
|
||||||
|
* On failure, the returned value is one of the following:
|
||||||
|
*
|
||||||
|
* **-EINVAL** if dev and inum supplied don't match dev_t and inode number
|
||||||
|
* with nsfs of current task, or if dev conversion to dev_t lost high bits.
|
||||||
|
*
|
||||||
|
* **-ENOENT** if pidns does not exists for the current task.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int (*bpf_get_ns_current_pid_tgid)(__u64 dev, __u64 ino, struct bpf_pidns_info *nsdata, __u32 size) = (void *) 120;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bpf_xdp_output
|
||||||
|
*
|
||||||
|
* Write raw *data* blob into a special BPF perf event held by
|
||||||
|
* *map* of type **BPF_MAP_TYPE_PERF_EVENT_ARRAY**. This perf
|
||||||
|
* event must have the following attributes: **PERF_SAMPLE_RAW**
|
||||||
|
* as **sample_type**, **PERF_TYPE_SOFTWARE** as **type**, and
|
||||||
|
* **PERF_COUNT_SW_BPF_OUTPUT** as **config**.
|
||||||
|
*
|
||||||
|
* The *flags* are used to indicate the index in *map* for which
|
||||||
|
* the value must be put, masked with **BPF_F_INDEX_MASK**.
|
||||||
|
* Alternatively, *flags* can be set to **BPF_F_CURRENT_CPU**
|
||||||
|
* to indicate that the index of the current CPU core should be
|
||||||
|
* used.
|
||||||
|
*
|
||||||
|
* The value to write, of *size*, is passed through eBPF stack and
|
||||||
|
* pointed by *data*.
|
||||||
|
*
|
||||||
|
* *ctx* is a pointer to in-kernel struct xdp_buff.
|
||||||
|
*
|
||||||
|
* This helper is similar to **bpf_perf_eventoutput**\ () but
|
||||||
|
* restricted to raw_tracepoint bpf programs.
|
||||||
|
*
|
||||||
|
* Returns
|
||||||
|
* 0 on success, or a negative error in case of failure.
|
||||||
|
*/
|
||||||
|
static int (*bpf_xdp_output)(void *ctx, void *map, __u64 flags, void *data, __u64 size) = (void *) 121;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bpf_get_netns_cookie
|
||||||
|
*
|
||||||
|
* Retrieve the cookie (generated by the kernel) of the network
|
||||||
|
* namespace the input *ctx* is associated with. The network
|
||||||
|
* namespace cookie remains stable for its lifetime and provides
|
||||||
|
* a global identifier that can be assumed unique. If *ctx* is
|
||||||
|
* NULL, then the helper returns the cookie for the initial
|
||||||
|
* network namespace. The cookie itself is very similar to that
|
||||||
|
* of bpf_get_socket_cookie() helper, but for network namespaces
|
||||||
|
* instead of sockets.
|
||||||
|
*
|
||||||
|
* Returns
|
||||||
|
* A 8-byte long opaque number.
|
||||||
|
*/
|
||||||
|
static __u64 (*bpf_get_netns_cookie)(void *ctx) = (void *) 122;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bpf_get_current_ancestor_cgroup_id
|
||||||
|
*
|
||||||
|
* Return id of cgroup v2 that is ancestor of the cgroup associated
|
||||||
|
* with the current task at the *ancestor_level*. The root cgroup
|
||||||
|
* is at *ancestor_level* zero and each step down the hierarchy
|
||||||
|
* increments the level. If *ancestor_level* == level of cgroup
|
||||||
|
* associated with the current task, then return value will be the
|
||||||
|
* same as that of **bpf_get_current_cgroup_id**\ ().
|
||||||
|
*
|
||||||
|
* The helper is useful to implement policies based on cgroups
|
||||||
|
* that are upper in hierarchy than immediate cgroup associated
|
||||||
|
* with the current task.
|
||||||
|
*
|
||||||
|
* The format of returned id and helper limitations are same as in
|
||||||
|
* **bpf_get_current_cgroup_id**\ ().
|
||||||
|
*
|
||||||
|
* Returns
|
||||||
|
* The id is returned or 0 in case the id could not be retrieved.
|
||||||
|
*/
|
||||||
|
static __u64 (*bpf_get_current_ancestor_cgroup_id)(int ancestor_level) = (void *) 123;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bpf_sk_assign
|
||||||
|
*
|
||||||
|
* Assign the *sk* to the *skb*. When combined with appropriate
|
||||||
|
* routing configuration to receive the packet towards the socket,
|
||||||
|
* will cause *skb* to be delivered to the specified socket.
|
||||||
|
* Subsequent redirection of *skb* via **bpf_redirect**\ (),
|
||||||
|
* **bpf_clone_redirect**\ () or other methods outside of BPF may
|
||||||
|
* interfere with successful delivery to the socket.
|
||||||
|
*
|
||||||
|
* This operation is only valid from TC ingress path.
|
||||||
|
*
|
||||||
|
* The *flags* argument must be zero.
|
||||||
|
*
|
||||||
|
* Returns
|
||||||
|
* 0 on success, or a negative errno in case of failure.
|
||||||
|
*
|
||||||
|
* * **-EINVAL** Unsupported flags specified.
|
||||||
|
* * **-ENOENT** Socket is unavailable for assignment.
|
||||||
|
* * **-ENETUNREACH** Socket is unreachable (wrong netns).
|
||||||
|
* * **-EOPNOTSUPP** Unsupported operation, for example a
|
||||||
|
* call from outside of TC ingress.
|
||||||
|
* * **-ESOCKTNOSUPPORT** Socket type not supported (reuseport).
|
||||||
|
*/
|
||||||
|
static int (*bpf_sk_assign)(struct __sk_buff *skb, struct bpf_sock *sk, __u64 flags) = (void *) 124;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,8 @@
|
|||||||
|
|
||||||
#if defined(bpf_target_x86)
|
#if defined(bpf_target_x86)
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#if defined(__KERNEL__) || defined(__VMLINUX_H__)
|
||||||
|
|
||||||
#define PT_REGS_PARM1(x) ((x)->di)
|
#define PT_REGS_PARM1(x) ((x)->di)
|
||||||
#define PT_REGS_PARM2(x) ((x)->si)
|
#define PT_REGS_PARM2(x) ((x)->si)
|
||||||
#define PT_REGS_PARM3(x) ((x)->dx)
|
#define PT_REGS_PARM3(x) ((x)->dx)
|
||||||
@@ -60,7 +61,20 @@
|
|||||||
#define PT_REGS_RC(x) ((x)->ax)
|
#define PT_REGS_RC(x) ((x)->ax)
|
||||||
#define PT_REGS_SP(x) ((x)->sp)
|
#define PT_REGS_SP(x) ((x)->sp)
|
||||||
#define PT_REGS_IP(x) ((x)->ip)
|
#define PT_REGS_IP(x) ((x)->ip)
|
||||||
|
|
||||||
|
#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), di)
|
||||||
|
#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), si)
|
||||||
|
#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), dx)
|
||||||
|
#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), cx)
|
||||||
|
#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), r8)
|
||||||
|
#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), sp)
|
||||||
|
#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), bp)
|
||||||
|
#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), ax)
|
||||||
|
#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), sp)
|
||||||
|
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), ip)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#ifdef __i386__
|
#ifdef __i386__
|
||||||
/* i386 kernel is built with -mregparm=3 */
|
/* i386 kernel is built with -mregparm=3 */
|
||||||
#define PT_REGS_PARM1(x) ((x)->eax)
|
#define PT_REGS_PARM1(x) ((x)->eax)
|
||||||
@@ -73,7 +87,20 @@
|
|||||||
#define PT_REGS_RC(x) ((x)->eax)
|
#define PT_REGS_RC(x) ((x)->eax)
|
||||||
#define PT_REGS_SP(x) ((x)->esp)
|
#define PT_REGS_SP(x) ((x)->esp)
|
||||||
#define PT_REGS_IP(x) ((x)->eip)
|
#define PT_REGS_IP(x) ((x)->eip)
|
||||||
|
|
||||||
|
#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), eax)
|
||||||
|
#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), edx)
|
||||||
|
#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), ecx)
|
||||||
|
#define PT_REGS_PARM4_CORE(x) 0
|
||||||
|
#define PT_REGS_PARM5_CORE(x) 0
|
||||||
|
#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), esp)
|
||||||
|
#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), ebp)
|
||||||
|
#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), eax)
|
||||||
|
#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), esp)
|
||||||
|
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), eip)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define PT_REGS_PARM1(x) ((x)->rdi)
|
#define PT_REGS_PARM1(x) ((x)->rdi)
|
||||||
#define PT_REGS_PARM2(x) ((x)->rsi)
|
#define PT_REGS_PARM2(x) ((x)->rsi)
|
||||||
#define PT_REGS_PARM3(x) ((x)->rdx)
|
#define PT_REGS_PARM3(x) ((x)->rdx)
|
||||||
@@ -84,6 +111,18 @@
|
|||||||
#define PT_REGS_RC(x) ((x)->rax)
|
#define PT_REGS_RC(x) ((x)->rax)
|
||||||
#define PT_REGS_SP(x) ((x)->rsp)
|
#define PT_REGS_SP(x) ((x)->rsp)
|
||||||
#define PT_REGS_IP(x) ((x)->rip)
|
#define PT_REGS_IP(x) ((x)->rip)
|
||||||
|
|
||||||
|
#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), rdi)
|
||||||
|
#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), rsi)
|
||||||
|
#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), rdx)
|
||||||
|
#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), rcx)
|
||||||
|
#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), r8)
|
||||||
|
#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), rsp)
|
||||||
|
#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), rbp)
|
||||||
|
#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), rax)
|
||||||
|
#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), rsp)
|
||||||
|
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), rip)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -104,6 +143,17 @@ struct pt_regs;
|
|||||||
#define PT_REGS_SP(x) (((PT_REGS_S390 *)(x))->gprs[15])
|
#define PT_REGS_SP(x) (((PT_REGS_S390 *)(x))->gprs[15])
|
||||||
#define PT_REGS_IP(x) (((PT_REGS_S390 *)(x))->psw.addr)
|
#define PT_REGS_IP(x) (((PT_REGS_S390 *)(x))->psw.addr)
|
||||||
|
|
||||||
|
#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[2])
|
||||||
|
#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[3])
|
||||||
|
#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[4])
|
||||||
|
#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[5])
|
||||||
|
#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[6])
|
||||||
|
#define PT_REGS_RET_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), grps[14])
|
||||||
|
#define PT_REGS_FP_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[11])
|
||||||
|
#define PT_REGS_RC_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[2])
|
||||||
|
#define PT_REGS_SP_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[15])
|
||||||
|
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), pdw.addr)
|
||||||
|
|
||||||
#elif defined(bpf_target_arm)
|
#elif defined(bpf_target_arm)
|
||||||
|
|
||||||
#define PT_REGS_PARM1(x) ((x)->uregs[0])
|
#define PT_REGS_PARM1(x) ((x)->uregs[0])
|
||||||
@@ -117,6 +167,17 @@ struct pt_regs;
|
|||||||
#define PT_REGS_SP(x) ((x)->uregs[13])
|
#define PT_REGS_SP(x) ((x)->uregs[13])
|
||||||
#define PT_REGS_IP(x) ((x)->uregs[12])
|
#define PT_REGS_IP(x) ((x)->uregs[12])
|
||||||
|
|
||||||
|
#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), uregs[0])
|
||||||
|
#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), uregs[1])
|
||||||
|
#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), uregs[2])
|
||||||
|
#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), uregs[3])
|
||||||
|
#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), uregs[4])
|
||||||
|
#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), uregs[14])
|
||||||
|
#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), uregs[11])
|
||||||
|
#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), uregs[0])
|
||||||
|
#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), uregs[13])
|
||||||
|
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), uregs[12])
|
||||||
|
|
||||||
#elif defined(bpf_target_arm64)
|
#elif defined(bpf_target_arm64)
|
||||||
|
|
||||||
/* arm64 provides struct user_pt_regs instead of struct pt_regs to userspace */
|
/* arm64 provides struct user_pt_regs instead of struct pt_regs to userspace */
|
||||||
@@ -134,6 +195,17 @@ struct pt_regs;
|
|||||||
#define PT_REGS_SP(x) (((PT_REGS_ARM64 *)(x))->sp)
|
#define PT_REGS_SP(x) (((PT_REGS_ARM64 *)(x))->sp)
|
||||||
#define PT_REGS_IP(x) (((PT_REGS_ARM64 *)(x))->pc)
|
#define PT_REGS_IP(x) (((PT_REGS_ARM64 *)(x))->pc)
|
||||||
|
|
||||||
|
#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[0])
|
||||||
|
#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[1])
|
||||||
|
#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[2])
|
||||||
|
#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[3])
|
||||||
|
#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[4])
|
||||||
|
#define PT_REGS_RET_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[30])
|
||||||
|
#define PT_REGS_FP_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[29])
|
||||||
|
#define PT_REGS_RC_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[0])
|
||||||
|
#define PT_REGS_SP_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), sp)
|
||||||
|
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), pc)
|
||||||
|
|
||||||
#elif defined(bpf_target_mips)
|
#elif defined(bpf_target_mips)
|
||||||
|
|
||||||
#define PT_REGS_PARM1(x) ((x)->regs[4])
|
#define PT_REGS_PARM1(x) ((x)->regs[4])
|
||||||
@@ -147,6 +219,17 @@ struct pt_regs;
|
|||||||
#define PT_REGS_SP(x) ((x)->regs[29])
|
#define PT_REGS_SP(x) ((x)->regs[29])
|
||||||
#define PT_REGS_IP(x) ((x)->cp0_epc)
|
#define PT_REGS_IP(x) ((x)->cp0_epc)
|
||||||
|
|
||||||
|
#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), regs[4])
|
||||||
|
#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), regs[5])
|
||||||
|
#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), regs[6])
|
||||||
|
#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), regs[7])
|
||||||
|
#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), regs[8])
|
||||||
|
#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), regs[31])
|
||||||
|
#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), regs[30])
|
||||||
|
#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), regs[1])
|
||||||
|
#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), regs[29])
|
||||||
|
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), cp0_epc)
|
||||||
|
|
||||||
#elif defined(bpf_target_powerpc)
|
#elif defined(bpf_target_powerpc)
|
||||||
|
|
||||||
#define PT_REGS_PARM1(x) ((x)->gpr[3])
|
#define PT_REGS_PARM1(x) ((x)->gpr[3])
|
||||||
@@ -158,6 +241,15 @@ struct pt_regs;
|
|||||||
#define PT_REGS_SP(x) ((x)->sp)
|
#define PT_REGS_SP(x) ((x)->sp)
|
||||||
#define PT_REGS_IP(x) ((x)->nip)
|
#define PT_REGS_IP(x) ((x)->nip)
|
||||||
|
|
||||||
|
#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), gpr[3])
|
||||||
|
#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), gpr[4])
|
||||||
|
#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), gpr[5])
|
||||||
|
#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), gpr[6])
|
||||||
|
#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), gpr[7])
|
||||||
|
#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), gpr[3])
|
||||||
|
#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), sp)
|
||||||
|
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), nip)
|
||||||
|
|
||||||
#elif defined(bpf_target_sparc)
|
#elif defined(bpf_target_sparc)
|
||||||
|
|
||||||
#define PT_REGS_PARM1(x) ((x)->u_regs[UREG_I0])
|
#define PT_REGS_PARM1(x) ((x)->u_regs[UREG_I0])
|
||||||
@@ -169,11 +261,22 @@ struct pt_regs;
|
|||||||
#define PT_REGS_RC(x) ((x)->u_regs[UREG_I0])
|
#define PT_REGS_RC(x) ((x)->u_regs[UREG_I0])
|
||||||
#define PT_REGS_SP(x) ((x)->u_regs[UREG_FP])
|
#define PT_REGS_SP(x) ((x)->u_regs[UREG_FP])
|
||||||
|
|
||||||
|
#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I0])
|
||||||
|
#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I1])
|
||||||
|
#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I2])
|
||||||
|
#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I3])
|
||||||
|
#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I4])
|
||||||
|
#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I7])
|
||||||
|
#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I0])
|
||||||
|
#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), u_regs[UREG_FP])
|
||||||
|
|
||||||
/* Should this also be a bpf_target check for the sparc case? */
|
/* Should this also be a bpf_target check for the sparc case? */
|
||||||
#if defined(__arch64__)
|
#if defined(__arch64__)
|
||||||
#define PT_REGS_IP(x) ((x)->tpc)
|
#define PT_REGS_IP(x) ((x)->tpc)
|
||||||
|
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), tpc)
|
||||||
#else
|
#else
|
||||||
#define PT_REGS_IP(x) ((x)->pc)
|
#define PT_REGS_IP(x) ((x)->pc)
|
||||||
|
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), pc)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -192,4 +295,122 @@ struct pt_regs;
|
|||||||
(void *)(PT_REGS_FP(ctx) + sizeof(ip))); })
|
(void *)(PT_REGS_FP(ctx) + sizeof(ip))); })
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ___bpf_concat(a, b) a ## b
|
||||||
|
#define ___bpf_apply(fn, n) ___bpf_concat(fn, n)
|
||||||
|
#define ___bpf_nth(_, _1, _2, _3, _4, _5, _6, _7, _8, _9, _a, _b, _c, N, ...) N
|
||||||
|
#define ___bpf_narg(...) \
|
||||||
|
___bpf_nth(_, ##__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||||
|
#define ___bpf_empty(...) \
|
||||||
|
___bpf_nth(_, ##__VA_ARGS__, N, N, N, N, N, N, N, N, N, N, 0)
|
||||||
|
|
||||||
|
#define ___bpf_ctx_cast0() ctx
|
||||||
|
#define ___bpf_ctx_cast1(x) ___bpf_ctx_cast0(), (void *)ctx[0]
|
||||||
|
#define ___bpf_ctx_cast2(x, args...) ___bpf_ctx_cast1(args), (void *)ctx[1]
|
||||||
|
#define ___bpf_ctx_cast3(x, args...) ___bpf_ctx_cast2(args), (void *)ctx[2]
|
||||||
|
#define ___bpf_ctx_cast4(x, args...) ___bpf_ctx_cast3(args), (void *)ctx[3]
|
||||||
|
#define ___bpf_ctx_cast5(x, args...) ___bpf_ctx_cast4(args), (void *)ctx[4]
|
||||||
|
#define ___bpf_ctx_cast6(x, args...) ___bpf_ctx_cast5(args), (void *)ctx[5]
|
||||||
|
#define ___bpf_ctx_cast7(x, args...) ___bpf_ctx_cast6(args), (void *)ctx[6]
|
||||||
|
#define ___bpf_ctx_cast8(x, args...) ___bpf_ctx_cast7(args), (void *)ctx[7]
|
||||||
|
#define ___bpf_ctx_cast9(x, args...) ___bpf_ctx_cast8(args), (void *)ctx[8]
|
||||||
|
#define ___bpf_ctx_cast10(x, args...) ___bpf_ctx_cast9(args), (void *)ctx[9]
|
||||||
|
#define ___bpf_ctx_cast11(x, args...) ___bpf_ctx_cast10(args), (void *)ctx[10]
|
||||||
|
#define ___bpf_ctx_cast12(x, args...) ___bpf_ctx_cast11(args), (void *)ctx[11]
|
||||||
|
#define ___bpf_ctx_cast(args...) \
|
||||||
|
___bpf_apply(___bpf_ctx_cast, ___bpf_narg(args))(args)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BPF_PROG is a convenience wrapper for generic tp_btf/fentry/fexit and
|
||||||
|
* similar kinds of BPF programs, that accept input arguments as a single
|
||||||
|
* pointer to untyped u64 array, where each u64 can actually be a typed
|
||||||
|
* pointer or integer of different size. Instead of requring user to write
|
||||||
|
* manual casts and work with array elements by index, BPF_PROG macro
|
||||||
|
* allows user to declare a list of named and typed input arguments in the
|
||||||
|
* same syntax as for normal C function. All the casting is hidden and
|
||||||
|
* performed transparently, while user code can just assume working with
|
||||||
|
* function arguments of specified type and name.
|
||||||
|
*
|
||||||
|
* Original raw context argument is preserved as well as 'ctx' argument.
|
||||||
|
* This is useful when using BPF helpers that expect original context
|
||||||
|
* as one of the parameters (e.g., for bpf_perf_event_output()).
|
||||||
|
*/
|
||||||
|
#define BPF_PROG(name, args...) \
|
||||||
|
name(unsigned long long *ctx); \
|
||||||
|
static __attribute__((always_inline)) typeof(name(0)) \
|
||||||
|
____##name(unsigned long long *ctx, ##args); \
|
||||||
|
typeof(name(0)) name(unsigned long long *ctx) \
|
||||||
|
{ \
|
||||||
|
_Pragma("GCC diagnostic push") \
|
||||||
|
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
|
||||||
|
return ____##name(___bpf_ctx_cast(args)); \
|
||||||
|
_Pragma("GCC diagnostic pop") \
|
||||||
|
} \
|
||||||
|
static __attribute__((always_inline)) typeof(name(0)) \
|
||||||
|
____##name(unsigned long long *ctx, ##args)
|
||||||
|
|
||||||
|
struct pt_regs;
|
||||||
|
|
||||||
|
#define ___bpf_kprobe_args0() ctx
|
||||||
|
#define ___bpf_kprobe_args1(x) \
|
||||||
|
___bpf_kprobe_args0(), (void *)PT_REGS_PARM1(ctx)
|
||||||
|
#define ___bpf_kprobe_args2(x, args...) \
|
||||||
|
___bpf_kprobe_args1(args), (void *)PT_REGS_PARM2(ctx)
|
||||||
|
#define ___bpf_kprobe_args3(x, args...) \
|
||||||
|
___bpf_kprobe_args2(args), (void *)PT_REGS_PARM3(ctx)
|
||||||
|
#define ___bpf_kprobe_args4(x, args...) \
|
||||||
|
___bpf_kprobe_args3(args), (void *)PT_REGS_PARM4(ctx)
|
||||||
|
#define ___bpf_kprobe_args5(x, args...) \
|
||||||
|
___bpf_kprobe_args4(args), (void *)PT_REGS_PARM5(ctx)
|
||||||
|
#define ___bpf_kprobe_args(args...) \
|
||||||
|
___bpf_apply(___bpf_kprobe_args, ___bpf_narg(args))(args)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BPF_KPROBE serves the same purpose for kprobes as BPF_PROG for
|
||||||
|
* tp_btf/fentry/fexit BPF programs. It hides the underlying platform-specific
|
||||||
|
* low-level way of getting kprobe input arguments from struct pt_regs, and
|
||||||
|
* provides a familiar typed and named function arguments syntax and
|
||||||
|
* semantics of accessing kprobe input paremeters.
|
||||||
|
*
|
||||||
|
* Original struct pt_regs* context is preserved as 'ctx' argument. This might
|
||||||
|
* be necessary when using BPF helpers like bpf_perf_event_output().
|
||||||
|
*/
|
||||||
|
#define BPF_KPROBE(name, args...) \
|
||||||
|
name(struct pt_regs *ctx); \
|
||||||
|
static __attribute__((always_inline)) typeof(name(0)) \
|
||||||
|
____##name(struct pt_regs *ctx, ##args); \
|
||||||
|
typeof(name(0)) name(struct pt_regs *ctx) \
|
||||||
|
{ \
|
||||||
|
_Pragma("GCC diagnostic push") \
|
||||||
|
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
|
||||||
|
return ____##name(___bpf_kprobe_args(args)); \
|
||||||
|
_Pragma("GCC diagnostic pop") \
|
||||||
|
} \
|
||||||
|
static __attribute__((always_inline)) typeof(name(0)) \
|
||||||
|
____##name(struct pt_regs *ctx, ##args)
|
||||||
|
|
||||||
|
#define ___bpf_kretprobe_args0() ctx
|
||||||
|
#define ___bpf_kretprobe_args1(x) \
|
||||||
|
___bpf_kretprobe_args0(), (void *)PT_REGS_RC(ctx)
|
||||||
|
#define ___bpf_kretprobe_args(args...) \
|
||||||
|
___bpf_apply(___bpf_kretprobe_args, ___bpf_narg(args))(args)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BPF_KRETPROBE is similar to BPF_KPROBE, except, it only provides optional
|
||||||
|
* return value (in addition to `struct pt_regs *ctx`), but no input
|
||||||
|
* arguments, because they will be clobbered by the time probed function
|
||||||
|
* returns.
|
||||||
|
*/
|
||||||
|
#define BPF_KRETPROBE(name, args...) \
|
||||||
|
name(struct pt_regs *ctx); \
|
||||||
|
static __attribute__((always_inline)) typeof(name(0)) \
|
||||||
|
____##name(struct pt_regs *ctx, ##args); \
|
||||||
|
typeof(name(0)) name(struct pt_regs *ctx) \
|
||||||
|
{ \
|
||||||
|
_Pragma("GCC diagnostic push") \
|
||||||
|
_Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
|
||||||
|
return ____##name(___bpf_kretprobe_args(args)); \
|
||||||
|
_Pragma("GCC diagnostic pop") \
|
||||||
|
} \
|
||||||
|
static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
20
src/btf.c
20
src/btf.c
@@ -657,22 +657,32 @@ int btf__finalize_data(struct bpf_object *obj, struct btf *btf)
|
|||||||
|
|
||||||
int btf__load(struct btf *btf)
|
int btf__load(struct btf *btf)
|
||||||
{
|
{
|
||||||
__u32 log_buf_size = BPF_LOG_BUF_SIZE;
|
__u32 log_buf_size = 0;
|
||||||
char *log_buf = NULL;
|
char *log_buf = NULL;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (btf->fd >= 0)
|
if (btf->fd >= 0)
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
|
|
||||||
log_buf = malloc(log_buf_size);
|
retry_load:
|
||||||
if (!log_buf)
|
if (log_buf_size) {
|
||||||
return -ENOMEM;
|
log_buf = malloc(log_buf_size);
|
||||||
|
if (!log_buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
*log_buf = 0;
|
*log_buf = 0;
|
||||||
|
}
|
||||||
|
|
||||||
btf->fd = bpf_load_btf(btf->data, btf->data_size,
|
btf->fd = bpf_load_btf(btf->data, btf->data_size,
|
||||||
log_buf, log_buf_size, false);
|
log_buf, log_buf_size, false);
|
||||||
if (btf->fd < 0) {
|
if (btf->fd < 0) {
|
||||||
|
if (!log_buf || errno == ENOSPC) {
|
||||||
|
log_buf_size = max((__u32)BPF_LOG_BUF_SIZE,
|
||||||
|
log_buf_size << 1);
|
||||||
|
free(log_buf);
|
||||||
|
goto retry_load;
|
||||||
|
}
|
||||||
|
|
||||||
err = -errno;
|
err = -errno;
|
||||||
pr_warn("Error loading BTF: %s(%d)\n", strerror(errno), errno);
|
pr_warn("Error loading BTF: %s(%d)\n", strerror(errno), errno);
|
||||||
if (*log_buf)
|
if (*log_buf)
|
||||||
|
|||||||
@@ -916,13 +916,13 @@ static void btf_dump_emit_enum_def(struct btf_dump *d, __u32 id,
|
|||||||
/* enumerators share namespace with typedef idents */
|
/* enumerators share namespace with typedef idents */
|
||||||
dup_cnt = btf_dump_name_dups(d, d->ident_names, name);
|
dup_cnt = btf_dump_name_dups(d, d->ident_names, name);
|
||||||
if (dup_cnt > 1) {
|
if (dup_cnt > 1) {
|
||||||
btf_dump_printf(d, "\n%s%s___%zu = %d,",
|
btf_dump_printf(d, "\n%s%s___%zu = %u,",
|
||||||
pfx(lvl + 1), name, dup_cnt,
|
pfx(lvl + 1), name, dup_cnt,
|
||||||
(__s32)v->val);
|
(__u32)v->val);
|
||||||
} else {
|
} else {
|
||||||
btf_dump_printf(d, "\n%s%s = %d,",
|
btf_dump_printf(d, "\n%s%s = %u,",
|
||||||
pfx(lvl + 1), name,
|
pfx(lvl + 1), name,
|
||||||
(__s32)v->val);
|
(__u32)v->val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
btf_dump_printf(d, "\n%s}", pfx(lvl));
|
btf_dump_printf(d, "\n%s}", pfx(lvl));
|
||||||
@@ -1030,7 +1030,7 @@ int btf_dump__emit_type_decl(struct btf_dump *d, __u32 id,
|
|||||||
if (!OPTS_VALID(opts, btf_dump_emit_type_decl_opts))
|
if (!OPTS_VALID(opts, btf_dump_emit_type_decl_opts))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
fname = OPTS_GET(opts, field_name, NULL);
|
fname = OPTS_GET(opts, field_name, "");
|
||||||
lvl = OPTS_GET(opts, indent_level, 0);
|
lvl = OPTS_GET(opts, indent_level, 0);
|
||||||
btf_dump_emit_type_decl(d, id, fname, lvl);
|
btf_dump_emit_type_decl(d, id, fname, lvl);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
446
src/libbpf.c
446
src/libbpf.c
@@ -24,6 +24,7 @@
|
|||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <asm/unistd.h>
|
#include <asm/unistd.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
@@ -177,6 +178,8 @@ struct bpf_capabilities {
|
|||||||
__u32 array_mmap:1;
|
__u32 array_mmap:1;
|
||||||
/* BTF_FUNC_GLOBAL is supported */
|
/* BTF_FUNC_GLOBAL is supported */
|
||||||
__u32 btf_func_global:1;
|
__u32 btf_func_global:1;
|
||||||
|
/* kernel support for expected_attach_type in BPF_PROG_LOAD */
|
||||||
|
__u32 exp_attach_type:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum reloc_type {
|
enum reloc_type {
|
||||||
@@ -193,6 +196,22 @@ struct reloc_desc {
|
|||||||
int sym_off;
|
int sym_off;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct bpf_sec_def;
|
||||||
|
|
||||||
|
typedef struct bpf_link *(*attach_fn_t)(const struct bpf_sec_def *sec,
|
||||||
|
struct bpf_program *prog);
|
||||||
|
|
||||||
|
struct bpf_sec_def {
|
||||||
|
const char *sec;
|
||||||
|
size_t len;
|
||||||
|
enum bpf_prog_type prog_type;
|
||||||
|
enum bpf_attach_type expected_attach_type;
|
||||||
|
bool is_exp_attach_type_optional;
|
||||||
|
bool is_attachable;
|
||||||
|
bool is_attach_btf;
|
||||||
|
attach_fn_t attach_fn;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bpf_prog should be a better name but it has been used in
|
* bpf_prog should be a better name but it has been used in
|
||||||
* linux/filter.h.
|
* linux/filter.h.
|
||||||
@@ -203,6 +222,7 @@ struct bpf_program {
|
|||||||
char *name;
|
char *name;
|
||||||
int prog_ifindex;
|
int prog_ifindex;
|
||||||
char *section_name;
|
char *section_name;
|
||||||
|
const struct bpf_sec_def *sec_def;
|
||||||
/* section_name with / replaced by _; makes recursive pinning
|
/* section_name with / replaced by _; makes recursive pinning
|
||||||
* in bpf_object__pin_programs easier
|
* in bpf_object__pin_programs easier
|
||||||
*/
|
*/
|
||||||
@@ -1283,7 +1303,7 @@ static size_t bpf_map_mmap_sz(const struct bpf_map *map)
|
|||||||
static char *internal_map_name(struct bpf_object *obj,
|
static char *internal_map_name(struct bpf_object *obj,
|
||||||
enum libbpf_map_type type)
|
enum libbpf_map_type type)
|
||||||
{
|
{
|
||||||
char map_name[BPF_OBJ_NAME_LEN];
|
char map_name[BPF_OBJ_NAME_LEN], *p;
|
||||||
const char *sfx = libbpf_type_to_btf_name[type];
|
const char *sfx = libbpf_type_to_btf_name[type];
|
||||||
int sfx_len = max((size_t)7, strlen(sfx));
|
int sfx_len = max((size_t)7, strlen(sfx));
|
||||||
int pfx_len = min((size_t)BPF_OBJ_NAME_LEN - sfx_len - 1,
|
int pfx_len = min((size_t)BPF_OBJ_NAME_LEN - sfx_len - 1,
|
||||||
@@ -1292,6 +1312,11 @@ static char *internal_map_name(struct bpf_object *obj,
|
|||||||
snprintf(map_name, sizeof(map_name), "%.*s%.*s", pfx_len, obj->name,
|
snprintf(map_name, sizeof(map_name), "%.*s%.*s", pfx_len, obj->name,
|
||||||
sfx_len, libbpf_type_to_btf_name[type]);
|
sfx_len, libbpf_type_to_btf_name[type]);
|
||||||
|
|
||||||
|
/* sanitise map name to characters allowed by kernel */
|
||||||
|
for (p = map_name; *p && p < map_name + sizeof(map_name); p++)
|
||||||
|
if (!isalnum(*p) && *p != '_' && *p != '.')
|
||||||
|
*p = '_';
|
||||||
|
|
||||||
return strdup(map_name);
|
return strdup(map_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1839,7 +1864,6 @@ resolve_func_ptr(const struct btf *btf, __u32 id, __u32 *res_id)
|
|||||||
* type definition, while using only sizeof(void *) space in ELF data section.
|
* type definition, while using only sizeof(void *) space in ELF data section.
|
||||||
*/
|
*/
|
||||||
static bool get_map_field_int(const char *map_name, const struct btf *btf,
|
static bool get_map_field_int(const char *map_name, const struct btf *btf,
|
||||||
const struct btf_type *def,
|
|
||||||
const struct btf_member *m, __u32 *res)
|
const struct btf_member *m, __u32 *res)
|
||||||
{
|
{
|
||||||
const struct btf_type *t = skip_mods_and_typedefs(btf, m->type, NULL);
|
const struct btf_type *t = skip_mods_and_typedefs(btf, m->type, NULL);
|
||||||
@@ -1966,19 +1990,19 @@ static int bpf_object__init_user_btf_map(struct bpf_object *obj,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (strcmp(name, "type") == 0) {
|
if (strcmp(name, "type") == 0) {
|
||||||
if (!get_map_field_int(map_name, obj->btf, def, m,
|
if (!get_map_field_int(map_name, obj->btf, m,
|
||||||
&map->def.type))
|
&map->def.type))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
pr_debug("map '%s': found type = %u.\n",
|
pr_debug("map '%s': found type = %u.\n",
|
||||||
map_name, map->def.type);
|
map_name, map->def.type);
|
||||||
} else if (strcmp(name, "max_entries") == 0) {
|
} else if (strcmp(name, "max_entries") == 0) {
|
||||||
if (!get_map_field_int(map_name, obj->btf, def, m,
|
if (!get_map_field_int(map_name, obj->btf, m,
|
||||||
&map->def.max_entries))
|
&map->def.max_entries))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
pr_debug("map '%s': found max_entries = %u.\n",
|
pr_debug("map '%s': found max_entries = %u.\n",
|
||||||
map_name, map->def.max_entries);
|
map_name, map->def.max_entries);
|
||||||
} else if (strcmp(name, "map_flags") == 0) {
|
} else if (strcmp(name, "map_flags") == 0) {
|
||||||
if (!get_map_field_int(map_name, obj->btf, def, m,
|
if (!get_map_field_int(map_name, obj->btf, m,
|
||||||
&map->def.map_flags))
|
&map->def.map_flags))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
pr_debug("map '%s': found map_flags = %u.\n",
|
pr_debug("map '%s': found map_flags = %u.\n",
|
||||||
@@ -1986,8 +2010,7 @@ static int bpf_object__init_user_btf_map(struct bpf_object *obj,
|
|||||||
} else if (strcmp(name, "key_size") == 0) {
|
} else if (strcmp(name, "key_size") == 0) {
|
||||||
__u32 sz;
|
__u32 sz;
|
||||||
|
|
||||||
if (!get_map_field_int(map_name, obj->btf, def, m,
|
if (!get_map_field_int(map_name, obj->btf, m, &sz))
|
||||||
&sz))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
pr_debug("map '%s': found key_size = %u.\n",
|
pr_debug("map '%s': found key_size = %u.\n",
|
||||||
map_name, sz);
|
map_name, sz);
|
||||||
@@ -2029,8 +2052,7 @@ static int bpf_object__init_user_btf_map(struct bpf_object *obj,
|
|||||||
} else if (strcmp(name, "value_size") == 0) {
|
} else if (strcmp(name, "value_size") == 0) {
|
||||||
__u32 sz;
|
__u32 sz;
|
||||||
|
|
||||||
if (!get_map_field_int(map_name, obj->btf, def, m,
|
if (!get_map_field_int(map_name, obj->btf, m, &sz))
|
||||||
&sz))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
pr_debug("map '%s': found value_size = %u.\n",
|
pr_debug("map '%s': found value_size = %u.\n",
|
||||||
map_name, sz);
|
map_name, sz);
|
||||||
@@ -2073,8 +2095,7 @@ static int bpf_object__init_user_btf_map(struct bpf_object *obj,
|
|||||||
__u32 val;
|
__u32 val;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!get_map_field_int(map_name, obj->btf, def, m,
|
if (!get_map_field_int(map_name, obj->btf, m, &val))
|
||||||
&val))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
pr_debug("map '%s': found pinning = %u.\n",
|
pr_debug("map '%s': found pinning = %u.\n",
|
||||||
map_name, val);
|
map_name, val);
|
||||||
@@ -2278,11 +2299,16 @@ static void bpf_object__sanitize_btf_ext(struct bpf_object *obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool bpf_object__is_btf_mandatory(const struct bpf_object *obj)
|
static bool libbpf_needs_btf(const struct bpf_object *obj)
|
||||||
{
|
{
|
||||||
return obj->efile.btf_maps_shndx >= 0 ||
|
return obj->efile.btf_maps_shndx >= 0 ||
|
||||||
obj->efile.st_ops_shndx >= 0 ||
|
obj->efile.st_ops_shndx >= 0 ||
|
||||||
obj->nr_extern > 0;
|
obj->nr_extern > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool kernel_needs_btf(const struct bpf_object *obj)
|
||||||
|
{
|
||||||
|
return obj->efile.st_ops_shndx >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bpf_object__init_btf(struct bpf_object *obj,
|
static int bpf_object__init_btf(struct bpf_object *obj,
|
||||||
@@ -2318,7 +2344,7 @@ static int bpf_object__init_btf(struct bpf_object *obj,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
if (err && bpf_object__is_btf_mandatory(obj)) {
|
if (err && libbpf_needs_btf(obj)) {
|
||||||
pr_warn("BTF is required, but is missing or corrupted.\n");
|
pr_warn("BTF is required, but is missing or corrupted.\n");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -2342,7 +2368,7 @@ static int bpf_object__finalize_btf(struct bpf_object *obj)
|
|||||||
btf_ext__free(obj->btf_ext);
|
btf_ext__free(obj->btf_ext);
|
||||||
obj->btf_ext = NULL;
|
obj->btf_ext = NULL;
|
||||||
|
|
||||||
if (bpf_object__is_btf_mandatory(obj)) {
|
if (libbpf_needs_btf(obj)) {
|
||||||
pr_warn("BTF is required, but is missing or corrupted.\n");
|
pr_warn("BTF is required, but is missing or corrupted.\n");
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
@@ -2351,7 +2377,8 @@ static int bpf_object__finalize_btf(struct bpf_object *obj)
|
|||||||
|
|
||||||
static inline bool libbpf_prog_needs_vmlinux_btf(struct bpf_program *prog)
|
static inline bool libbpf_prog_needs_vmlinux_btf(struct bpf_program *prog)
|
||||||
{
|
{
|
||||||
if (prog->type == BPF_PROG_TYPE_STRUCT_OPS)
|
if (prog->type == BPF_PROG_TYPE_STRUCT_OPS ||
|
||||||
|
prog->type == BPF_PROG_TYPE_LSM)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* BPF_PROG_TYPE_TRACING programs which do not attach to other programs
|
/* BPF_PROG_TYPE_TRACING programs which do not attach to other programs
|
||||||
@@ -2406,7 +2433,7 @@ static int bpf_object__sanitize_and_load_btf(struct bpf_object *obj)
|
|||||||
obj->btf_ext = NULL;
|
obj->btf_ext = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bpf_object__is_btf_mandatory(obj))
|
if (kernel_needs_btf(obj))
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -3307,6 +3334,37 @@ static int bpf_object__probe_array_mmap(struct bpf_object *obj)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bpf_object__probe_exp_attach_type(struct bpf_object *obj)
|
||||||
|
{
|
||||||
|
struct bpf_load_program_attr attr;
|
||||||
|
struct bpf_insn insns[] = {
|
||||||
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
};
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
memset(&attr, 0, sizeof(attr));
|
||||||
|
/* use any valid combination of program type and (optional)
|
||||||
|
* non-zero expected attach type (i.e., not a BPF_CGROUP_INET_INGRESS)
|
||||||
|
* to see if kernel supports expected_attach_type field for
|
||||||
|
* BPF_PROG_LOAD command
|
||||||
|
*/
|
||||||
|
attr.prog_type = BPF_PROG_TYPE_CGROUP_SOCK;
|
||||||
|
attr.expected_attach_type = BPF_CGROUP_INET_SOCK_CREATE;
|
||||||
|
attr.insns = insns;
|
||||||
|
attr.insns_cnt = ARRAY_SIZE(insns);
|
||||||
|
attr.license = "GPL";
|
||||||
|
|
||||||
|
fd = bpf_load_program_xattr(&attr, NULL, 0);
|
||||||
|
if (fd >= 0) {
|
||||||
|
obj->caps.exp_attach_type = 1;
|
||||||
|
close(fd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bpf_object__probe_caps(struct bpf_object *obj)
|
bpf_object__probe_caps(struct bpf_object *obj)
|
||||||
{
|
{
|
||||||
@@ -3317,6 +3375,7 @@ bpf_object__probe_caps(struct bpf_object *obj)
|
|||||||
bpf_object__probe_btf_func_global,
|
bpf_object__probe_btf_func_global,
|
||||||
bpf_object__probe_btf_datasec,
|
bpf_object__probe_btf_datasec,
|
||||||
bpf_object__probe_array_mmap,
|
bpf_object__probe_array_mmap,
|
||||||
|
bpf_object__probe_exp_attach_type,
|
||||||
};
|
};
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
@@ -3862,6 +3921,10 @@ static struct ids_vec *bpf_core_find_cands(const struct btf *local_btf,
|
|||||||
if (str_is_empty(targ_name))
|
if (str_is_empty(targ_name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
t = skip_mods_and_typedefs(targ_btf, i, NULL);
|
||||||
|
if (!btf_is_composite(t) && !btf_is_array(t))
|
||||||
|
continue;
|
||||||
|
|
||||||
targ_essent_len = bpf_core_essential_name_len(targ_name);
|
targ_essent_len = bpf_core_essential_name_len(targ_name);
|
||||||
if (targ_essent_len != local_essent_len)
|
if (targ_essent_len != local_essent_len)
|
||||||
continue;
|
continue;
|
||||||
@@ -4840,8 +4903,8 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
|
|||||||
{
|
{
|
||||||
struct bpf_load_program_attr load_attr;
|
struct bpf_load_program_attr load_attr;
|
||||||
char *cp, errmsg[STRERR_BUFSIZE];
|
char *cp, errmsg[STRERR_BUFSIZE];
|
||||||
int log_buf_size = BPF_LOG_BUF_SIZE;
|
size_t log_buf_size = 0;
|
||||||
char *log_buf;
|
char *log_buf = NULL;
|
||||||
int btf_fd, ret;
|
int btf_fd, ret;
|
||||||
|
|
||||||
if (!insns || !insns_cnt)
|
if (!insns || !insns_cnt)
|
||||||
@@ -4849,13 +4912,19 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
|
|||||||
|
|
||||||
memset(&load_attr, 0, sizeof(struct bpf_load_program_attr));
|
memset(&load_attr, 0, sizeof(struct bpf_load_program_attr));
|
||||||
load_attr.prog_type = prog->type;
|
load_attr.prog_type = prog->type;
|
||||||
load_attr.expected_attach_type = prog->expected_attach_type;
|
/* old kernels might not support specifying expected_attach_type */
|
||||||
|
if (!prog->caps->exp_attach_type && prog->sec_def &&
|
||||||
|
prog->sec_def->is_exp_attach_type_optional)
|
||||||
|
load_attr.expected_attach_type = 0;
|
||||||
|
else
|
||||||
|
load_attr.expected_attach_type = prog->expected_attach_type;
|
||||||
if (prog->caps->name)
|
if (prog->caps->name)
|
||||||
load_attr.name = prog->name;
|
load_attr.name = prog->name;
|
||||||
load_attr.insns = insns;
|
load_attr.insns = insns;
|
||||||
load_attr.insns_cnt = insns_cnt;
|
load_attr.insns_cnt = insns_cnt;
|
||||||
load_attr.license = license;
|
load_attr.license = license;
|
||||||
if (prog->type == BPF_PROG_TYPE_STRUCT_OPS) {
|
if (prog->type == BPF_PROG_TYPE_STRUCT_OPS ||
|
||||||
|
prog->type == BPF_PROG_TYPE_LSM) {
|
||||||
load_attr.attach_btf_id = prog->attach_btf_id;
|
load_attr.attach_btf_id = prog->attach_btf_id;
|
||||||
} else if (prog->type == BPF_PROG_TYPE_TRACING ||
|
} else if (prog->type == BPF_PROG_TYPE_TRACING ||
|
||||||
prog->type == BPF_PROG_TYPE_EXT) {
|
prog->type == BPF_PROG_TYPE_EXT) {
|
||||||
@@ -4881,22 +4950,28 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
|
|||||||
load_attr.prog_flags = prog->prog_flags;
|
load_attr.prog_flags = prog->prog_flags;
|
||||||
|
|
||||||
retry_load:
|
retry_load:
|
||||||
log_buf = malloc(log_buf_size);
|
if (log_buf_size) {
|
||||||
if (!log_buf)
|
log_buf = malloc(log_buf_size);
|
||||||
pr_warn("Alloc log buffer for bpf loader error, continue without log\n");
|
if (!log_buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
*log_buf = 0;
|
||||||
|
}
|
||||||
|
|
||||||
ret = bpf_load_program_xattr(&load_attr, log_buf, log_buf_size);
|
ret = bpf_load_program_xattr(&load_attr, log_buf, log_buf_size);
|
||||||
|
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
if (load_attr.log_level)
|
if (log_buf && load_attr.log_level)
|
||||||
pr_debug("verifier log:\n%s", log_buf);
|
pr_debug("verifier log:\n%s", log_buf);
|
||||||
*pfd = ret;
|
*pfd = ret;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errno == ENOSPC) {
|
if (!log_buf || errno == ENOSPC) {
|
||||||
log_buf_size <<= 1;
|
log_buf_size = max((size_t)BPF_LOG_BUF_SIZE,
|
||||||
|
log_buf_size << 1);
|
||||||
|
|
||||||
free(log_buf);
|
free(log_buf);
|
||||||
goto retry_load;
|
goto retry_load;
|
||||||
}
|
}
|
||||||
@@ -4939,8 +5014,9 @@ int bpf_program__load(struct bpf_program *prog, char *license, __u32 kern_ver)
|
|||||||
{
|
{
|
||||||
int err = 0, fd, i, btf_id;
|
int err = 0, fd, i, btf_id;
|
||||||
|
|
||||||
if (prog->type == BPF_PROG_TYPE_TRACING ||
|
if ((prog->type == BPF_PROG_TYPE_TRACING ||
|
||||||
prog->type == BPF_PROG_TYPE_EXT) {
|
prog->type == BPF_PROG_TYPE_LSM ||
|
||||||
|
prog->type == BPF_PROG_TYPE_EXT) && !prog->attach_btf_id) {
|
||||||
btf_id = libbpf_find_attach_btf_id(prog);
|
btf_id = libbpf_find_attach_btf_id(prog);
|
||||||
if (btf_id <= 0)
|
if (btf_id <= 0)
|
||||||
return btf_id;
|
return btf_id;
|
||||||
@@ -5042,6 +5118,8 @@ bpf_object__load_progs(struct bpf_object *obj, int log_level)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct bpf_sec_def *find_sec_def(const char *sec_name);
|
||||||
|
|
||||||
static struct bpf_object *
|
static struct bpf_object *
|
||||||
__bpf_object__open(const char *path, const void *obj_buf, size_t obj_buf_sz,
|
__bpf_object__open(const char *path, const void *obj_buf, size_t obj_buf_sz,
|
||||||
const struct bpf_object_open_opts *opts)
|
const struct bpf_object_open_opts *opts)
|
||||||
@@ -5097,24 +5175,17 @@ __bpf_object__open(const char *path, const void *obj_buf, size_t obj_buf_sz,
|
|||||||
bpf_object__elf_finish(obj);
|
bpf_object__elf_finish(obj);
|
||||||
|
|
||||||
bpf_object__for_each_program(prog, obj) {
|
bpf_object__for_each_program(prog, obj) {
|
||||||
enum bpf_prog_type prog_type;
|
prog->sec_def = find_sec_def(prog->section_name);
|
||||||
enum bpf_attach_type attach_type;
|
if (!prog->sec_def)
|
||||||
|
|
||||||
if (prog->type != BPF_PROG_TYPE_UNSPEC)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
err = libbpf_prog_type_by_name(prog->section_name, &prog_type,
|
|
||||||
&attach_type);
|
|
||||||
if (err == -ESRCH)
|
|
||||||
/* couldn't guess, but user might manually specify */
|
/* couldn't guess, but user might manually specify */
|
||||||
continue;
|
continue;
|
||||||
if (err)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
bpf_program__set_type(prog, prog_type);
|
bpf_program__set_type(prog, prog->sec_def->prog_type);
|
||||||
bpf_program__set_expected_attach_type(prog, attach_type);
|
bpf_program__set_expected_attach_type(prog,
|
||||||
if (prog_type == BPF_PROG_TYPE_TRACING ||
|
prog->sec_def->expected_attach_type);
|
||||||
prog_type == BPF_PROG_TYPE_EXT)
|
|
||||||
|
if (prog->sec_def->prog_type == BPF_PROG_TYPE_TRACING ||
|
||||||
|
prog->sec_def->prog_type == BPF_PROG_TYPE_EXT)
|
||||||
prog->attach_prog_fd = OPTS_GET(opts, attach_prog_fd, 0);
|
prog->attach_prog_fd = OPTS_GET(opts, attach_prog_fd, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6179,6 +6250,7 @@ bool bpf_program__is_##NAME(const struct bpf_program *prog) \
|
|||||||
} \
|
} \
|
||||||
|
|
||||||
BPF_PROG_TYPE_FNS(socket_filter, BPF_PROG_TYPE_SOCKET_FILTER);
|
BPF_PROG_TYPE_FNS(socket_filter, BPF_PROG_TYPE_SOCKET_FILTER);
|
||||||
|
BPF_PROG_TYPE_FNS(lsm, BPF_PROG_TYPE_LSM);
|
||||||
BPF_PROG_TYPE_FNS(kprobe, BPF_PROG_TYPE_KPROBE);
|
BPF_PROG_TYPE_FNS(kprobe, BPF_PROG_TYPE_KPROBE);
|
||||||
BPF_PROG_TYPE_FNS(sched_cls, BPF_PROG_TYPE_SCHED_CLS);
|
BPF_PROG_TYPE_FNS(sched_cls, BPF_PROG_TYPE_SCHED_CLS);
|
||||||
BPF_PROG_TYPE_FNS(sched_act, BPF_PROG_TYPE_SCHED_ACT);
|
BPF_PROG_TYPE_FNS(sched_act, BPF_PROG_TYPE_SCHED_ACT);
|
||||||
@@ -6202,23 +6274,32 @@ void bpf_program__set_expected_attach_type(struct bpf_program *prog,
|
|||||||
prog->expected_attach_type = type;
|
prog->expected_attach_type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BPF_PROG_SEC_IMPL(string, ptype, eatype, is_attachable, btf, atype) \
|
#define BPF_PROG_SEC_IMPL(string, ptype, eatype, eatype_optional, \
|
||||||
{ string, sizeof(string) - 1, ptype, eatype, is_attachable, btf, atype }
|
attachable, attach_btf) \
|
||||||
|
{ \
|
||||||
|
.sec = string, \
|
||||||
|
.len = sizeof(string) - 1, \
|
||||||
|
.prog_type = ptype, \
|
||||||
|
.expected_attach_type = eatype, \
|
||||||
|
.is_exp_attach_type_optional = eatype_optional, \
|
||||||
|
.is_attachable = attachable, \
|
||||||
|
.is_attach_btf = attach_btf, \
|
||||||
|
}
|
||||||
|
|
||||||
/* Programs that can NOT be attached. */
|
/* Programs that can NOT be attached. */
|
||||||
#define BPF_PROG_SEC(string, ptype) BPF_PROG_SEC_IMPL(string, ptype, 0, 0, 0, 0)
|
#define BPF_PROG_SEC(string, ptype) BPF_PROG_SEC_IMPL(string, ptype, 0, 0, 0, 0)
|
||||||
|
|
||||||
/* Programs that can be attached. */
|
/* Programs that can be attached. */
|
||||||
#define BPF_APROG_SEC(string, ptype, atype) \
|
#define BPF_APROG_SEC(string, ptype, atype) \
|
||||||
BPF_PROG_SEC_IMPL(string, ptype, 0, 1, 0, atype)
|
BPF_PROG_SEC_IMPL(string, ptype, atype, true, 1, 0)
|
||||||
|
|
||||||
/* Programs that must specify expected attach type at load time. */
|
/* Programs that must specify expected attach type at load time. */
|
||||||
#define BPF_EAPROG_SEC(string, ptype, eatype) \
|
#define BPF_EAPROG_SEC(string, ptype, eatype) \
|
||||||
BPF_PROG_SEC_IMPL(string, ptype, eatype, 1, 0, eatype)
|
BPF_PROG_SEC_IMPL(string, ptype, eatype, false, 1, 0)
|
||||||
|
|
||||||
/* Programs that use BTF to identify attach point */
|
/* Programs that use BTF to identify attach point */
|
||||||
#define BPF_PROG_BTF(string, ptype, eatype) \
|
#define BPF_PROG_BTF(string, ptype, eatype) \
|
||||||
BPF_PROG_SEC_IMPL(string, ptype, eatype, 0, 1, 0)
|
BPF_PROG_SEC_IMPL(string, ptype, eatype, false, 0, 1)
|
||||||
|
|
||||||
/* Programs that can be attached but attach type can't be identified by section
|
/* Programs that can be attached but attach type can't be identified by section
|
||||||
* name. Kept for backward compatibility.
|
* name. Kept for backward compatibility.
|
||||||
@@ -6232,11 +6313,6 @@ void bpf_program__set_expected_attach_type(struct bpf_program *prog,
|
|||||||
__VA_ARGS__ \
|
__VA_ARGS__ \
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bpf_sec_def;
|
|
||||||
|
|
||||||
typedef struct bpf_link *(*attach_fn_t)(const struct bpf_sec_def *sec,
|
|
||||||
struct bpf_program *prog);
|
|
||||||
|
|
||||||
static struct bpf_link *attach_kprobe(const struct bpf_sec_def *sec,
|
static struct bpf_link *attach_kprobe(const struct bpf_sec_def *sec,
|
||||||
struct bpf_program *prog);
|
struct bpf_program *prog);
|
||||||
static struct bpf_link *attach_tp(const struct bpf_sec_def *sec,
|
static struct bpf_link *attach_tp(const struct bpf_sec_def *sec,
|
||||||
@@ -6245,17 +6321,8 @@ static struct bpf_link *attach_raw_tp(const struct bpf_sec_def *sec,
|
|||||||
struct bpf_program *prog);
|
struct bpf_program *prog);
|
||||||
static struct bpf_link *attach_trace(const struct bpf_sec_def *sec,
|
static struct bpf_link *attach_trace(const struct bpf_sec_def *sec,
|
||||||
struct bpf_program *prog);
|
struct bpf_program *prog);
|
||||||
|
static struct bpf_link *attach_lsm(const struct bpf_sec_def *sec,
|
||||||
struct bpf_sec_def {
|
struct bpf_program *prog);
|
||||||
const char *sec;
|
|
||||||
size_t len;
|
|
||||||
enum bpf_prog_type prog_type;
|
|
||||||
enum bpf_attach_type expected_attach_type;
|
|
||||||
bool is_attachable;
|
|
||||||
bool is_attach_btf;
|
|
||||||
enum bpf_attach_type attach_type;
|
|
||||||
attach_fn_t attach_fn;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct bpf_sec_def section_defs[] = {
|
static const struct bpf_sec_def section_defs[] = {
|
||||||
BPF_PROG_SEC("socket", BPF_PROG_TYPE_SOCKET_FILTER),
|
BPF_PROG_SEC("socket", BPF_PROG_TYPE_SOCKET_FILTER),
|
||||||
@@ -6284,6 +6351,10 @@ static const struct bpf_sec_def section_defs[] = {
|
|||||||
.expected_attach_type = BPF_TRACE_FENTRY,
|
.expected_attach_type = BPF_TRACE_FENTRY,
|
||||||
.is_attach_btf = true,
|
.is_attach_btf = true,
|
||||||
.attach_fn = attach_trace),
|
.attach_fn = attach_trace),
|
||||||
|
SEC_DEF("fmod_ret/", TRACING,
|
||||||
|
.expected_attach_type = BPF_MODIFY_RETURN,
|
||||||
|
.is_attach_btf = true,
|
||||||
|
.attach_fn = attach_trace),
|
||||||
SEC_DEF("fexit/", TRACING,
|
SEC_DEF("fexit/", TRACING,
|
||||||
.expected_attach_type = BPF_TRACE_FEXIT,
|
.expected_attach_type = BPF_TRACE_FEXIT,
|
||||||
.is_attach_btf = true,
|
.is_attach_btf = true,
|
||||||
@@ -6291,6 +6362,10 @@ static const struct bpf_sec_def section_defs[] = {
|
|||||||
SEC_DEF("freplace/", EXT,
|
SEC_DEF("freplace/", EXT,
|
||||||
.is_attach_btf = true,
|
.is_attach_btf = true,
|
||||||
.attach_fn = attach_trace),
|
.attach_fn = attach_trace),
|
||||||
|
SEC_DEF("lsm/", LSM,
|
||||||
|
.is_attach_btf = true,
|
||||||
|
.expected_attach_type = BPF_LSM_MAC,
|
||||||
|
.attach_fn = attach_lsm),
|
||||||
BPF_PROG_SEC("xdp", BPF_PROG_TYPE_XDP),
|
BPF_PROG_SEC("xdp", BPF_PROG_TYPE_XDP),
|
||||||
BPF_PROG_SEC("perf_event", BPF_PROG_TYPE_PERF_EVENT),
|
BPF_PROG_SEC("perf_event", BPF_PROG_TYPE_PERF_EVENT),
|
||||||
BPF_PROG_SEC("lwt_in", BPF_PROG_TYPE_LWT_IN),
|
BPF_PROG_SEC("lwt_in", BPF_PROG_TYPE_LWT_IN),
|
||||||
@@ -6553,6 +6628,7 @@ invalid_prog:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define BTF_TRACE_PREFIX "btf_trace_"
|
#define BTF_TRACE_PREFIX "btf_trace_"
|
||||||
|
#define BTF_LSM_PREFIX "bpf_lsm_"
|
||||||
#define BTF_MAX_NAME_SIZE 128
|
#define BTF_MAX_NAME_SIZE 128
|
||||||
|
|
||||||
static int find_btf_by_prefix_kind(const struct btf *btf, const char *prefix,
|
static int find_btf_by_prefix_kind(const struct btf *btf, const char *prefix,
|
||||||
@@ -6580,9 +6656,15 @@ static inline int __find_vmlinux_btf_id(struct btf *btf, const char *name,
|
|||||||
if (attach_type == BPF_TRACE_RAW_TP)
|
if (attach_type == BPF_TRACE_RAW_TP)
|
||||||
err = find_btf_by_prefix_kind(btf, BTF_TRACE_PREFIX, name,
|
err = find_btf_by_prefix_kind(btf, BTF_TRACE_PREFIX, name,
|
||||||
BTF_KIND_TYPEDEF);
|
BTF_KIND_TYPEDEF);
|
||||||
|
else if (attach_type == BPF_LSM_MAC)
|
||||||
|
err = find_btf_by_prefix_kind(btf, BTF_LSM_PREFIX, name,
|
||||||
|
BTF_KIND_FUNC);
|
||||||
else
|
else
|
||||||
err = btf__find_by_name_kind(btf, name, BTF_KIND_FUNC);
|
err = btf__find_by_name_kind(btf, name, BTF_KIND_FUNC);
|
||||||
|
|
||||||
|
if (err <= 0)
|
||||||
|
pr_warn("%s is not found in vmlinux BTF\n", name);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6655,8 +6737,6 @@ static int libbpf_find_attach_btf_id(struct bpf_program *prog)
|
|||||||
err = __find_vmlinux_btf_id(prog->obj->btf_vmlinux,
|
err = __find_vmlinux_btf_id(prog->obj->btf_vmlinux,
|
||||||
name + section_defs[i].len,
|
name + section_defs[i].len,
|
||||||
attach_type);
|
attach_type);
|
||||||
if (err <= 0)
|
|
||||||
pr_warn("%s is not found in vmlinux BTF\n", name);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
pr_warn("failed to identify btf_id based on ELF section name '%s'\n", name);
|
pr_warn("failed to identify btf_id based on ELF section name '%s'\n", name);
|
||||||
@@ -6677,7 +6757,7 @@ int libbpf_attach_type_by_name(const char *name,
|
|||||||
continue;
|
continue;
|
||||||
if (!section_defs[i].is_attachable)
|
if (!section_defs[i].is_attachable)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
*attach_type = section_defs[i].attach_type;
|
*attach_type = section_defs[i].expected_attach_type;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
pr_debug("failed to guess attach type based on ELF section name '%s'\n", name);
|
pr_debug("failed to guess attach type based on ELF section name '%s'\n", name);
|
||||||
@@ -6736,6 +6816,17 @@ void *bpf_map__priv(const struct bpf_map *map)
|
|||||||
return map ? map->priv : ERR_PTR(-EINVAL);
|
return map ? map->priv : ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bpf_map__set_initial_value(struct bpf_map *map,
|
||||||
|
const void *data, size_t size)
|
||||||
|
{
|
||||||
|
if (!map->mmaped || map->libbpf_type == LIBBPF_MAP_KCONFIG ||
|
||||||
|
size != map->def.value_size || map->fd >= 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
memcpy(map->mmaped, data, size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool bpf_map__is_offload_neutral(const struct bpf_map *map)
|
bool bpf_map__is_offload_neutral(const struct bpf_map *map)
|
||||||
{
|
{
|
||||||
return map->def.type == BPF_MAP_TYPE_PERF_EVENT_ARRAY;
|
return map->def.type == BPF_MAP_TYPE_PERF_EVENT_ARRAY;
|
||||||
@@ -6926,9 +7017,17 @@ int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
|
|||||||
struct bpf_link {
|
struct bpf_link {
|
||||||
int (*detach)(struct bpf_link *link);
|
int (*detach)(struct bpf_link *link);
|
||||||
int (*destroy)(struct bpf_link *link);
|
int (*destroy)(struct bpf_link *link);
|
||||||
|
char *pin_path; /* NULL, if not pinned */
|
||||||
|
int fd; /* hook FD, -1 if not applicable */
|
||||||
bool disconnected;
|
bool disconnected;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Replace link's underlying BPF program with the new one */
|
||||||
|
int bpf_link__update_program(struct bpf_link *link, struct bpf_program *prog)
|
||||||
|
{
|
||||||
|
return bpf_link_update(bpf_link__fd(link), bpf_program__fd(prog), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/* Release "ownership" of underlying BPF resource (typically, BPF program
|
/* Release "ownership" of underlying BPF resource (typically, BPF program
|
||||||
* attached to some BPF hook, e.g., tracepoint, kprobe, etc). Disconnected
|
* attached to some BPF hook, e.g., tracepoint, kprobe, etc). Disconnected
|
||||||
* link, when destructed through bpf_link__destroy() call won't attempt to
|
* link, when destructed through bpf_link__destroy() call won't attempt to
|
||||||
@@ -6955,26 +7054,109 @@ int bpf_link__destroy(struct bpf_link *link)
|
|||||||
err = link->detach(link);
|
err = link->detach(link);
|
||||||
if (link->destroy)
|
if (link->destroy)
|
||||||
link->destroy(link);
|
link->destroy(link);
|
||||||
|
if (link->pin_path)
|
||||||
|
free(link->pin_path);
|
||||||
free(link);
|
free(link);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bpf_link_fd {
|
int bpf_link__fd(const struct bpf_link *link)
|
||||||
struct bpf_link link; /* has to be at the top of struct */
|
{
|
||||||
int fd; /* hook FD */
|
return link->fd;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
const char *bpf_link__pin_path(const struct bpf_link *link)
|
||||||
|
{
|
||||||
|
return link->pin_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bpf_link__detach_fd(struct bpf_link *link)
|
||||||
|
{
|
||||||
|
return close(link->fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bpf_link *bpf_link__open(const char *path)
|
||||||
|
{
|
||||||
|
struct bpf_link *link;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = bpf_obj_get(path);
|
||||||
|
if (fd < 0) {
|
||||||
|
fd = -errno;
|
||||||
|
pr_warn("failed to open link at %s: %d\n", path, fd);
|
||||||
|
return ERR_PTR(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
link = calloc(1, sizeof(*link));
|
||||||
|
if (!link) {
|
||||||
|
close(fd);
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
}
|
||||||
|
link->detach = &bpf_link__detach_fd;
|
||||||
|
link->fd = fd;
|
||||||
|
|
||||||
|
link->pin_path = strdup(path);
|
||||||
|
if (!link->pin_path) {
|
||||||
|
bpf_link__destroy(link);
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bpf_link__pin(struct bpf_link *link, const char *path)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (link->pin_path)
|
||||||
|
return -EBUSY;
|
||||||
|
err = make_parent_dir(path);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
err = check_path(path);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
link->pin_path = strdup(path);
|
||||||
|
if (!link->pin_path)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (bpf_obj_pin(link->fd, link->pin_path)) {
|
||||||
|
err = -errno;
|
||||||
|
zfree(&link->pin_path);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_debug("link fd=%d: pinned at %s\n", link->fd, link->pin_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bpf_link__unpin(struct bpf_link *link)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!link->pin_path)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
err = unlink(link->pin_path);
|
||||||
|
if (err != 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
pr_debug("link fd=%d: unpinned from %s\n", link->fd, link->pin_path);
|
||||||
|
zfree(&link->pin_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int bpf_link__detach_perf_event(struct bpf_link *link)
|
static int bpf_link__detach_perf_event(struct bpf_link *link)
|
||||||
{
|
{
|
||||||
struct bpf_link_fd *l = (void *)link;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = ioctl(l->fd, PERF_EVENT_IOC_DISABLE, 0);
|
err = ioctl(link->fd, PERF_EVENT_IOC_DISABLE, 0);
|
||||||
if (err)
|
if (err)
|
||||||
err = -errno;
|
err = -errno;
|
||||||
|
|
||||||
close(l->fd);
|
close(link->fd);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6982,7 +7164,7 @@ struct bpf_link *bpf_program__attach_perf_event(struct bpf_program *prog,
|
|||||||
int pfd)
|
int pfd)
|
||||||
{
|
{
|
||||||
char errmsg[STRERR_BUFSIZE];
|
char errmsg[STRERR_BUFSIZE];
|
||||||
struct bpf_link_fd *link;
|
struct bpf_link *link;
|
||||||
int prog_fd, err;
|
int prog_fd, err;
|
||||||
|
|
||||||
if (pfd < 0) {
|
if (pfd < 0) {
|
||||||
@@ -7000,7 +7182,7 @@ struct bpf_link *bpf_program__attach_perf_event(struct bpf_program *prog,
|
|||||||
link = calloc(1, sizeof(*link));
|
link = calloc(1, sizeof(*link));
|
||||||
if (!link)
|
if (!link)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
link->link.detach = &bpf_link__detach_perf_event;
|
link->detach = &bpf_link__detach_perf_event;
|
||||||
link->fd = pfd;
|
link->fd = pfd;
|
||||||
|
|
||||||
if (ioctl(pfd, PERF_EVENT_IOC_SET_BPF, prog_fd) < 0) {
|
if (ioctl(pfd, PERF_EVENT_IOC_SET_BPF, prog_fd) < 0) {
|
||||||
@@ -7019,7 +7201,7 @@ struct bpf_link *bpf_program__attach_perf_event(struct bpf_program *prog,
|
|||||||
libbpf_strerror_r(err, errmsg, sizeof(errmsg)));
|
libbpf_strerror_r(err, errmsg, sizeof(errmsg)));
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
return (struct bpf_link *)link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -7307,18 +7489,11 @@ out:
|
|||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bpf_link__detach_fd(struct bpf_link *link)
|
|
||||||
{
|
|
||||||
struct bpf_link_fd *l = (void *)link;
|
|
||||||
|
|
||||||
return close(l->fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct bpf_link *bpf_program__attach_raw_tracepoint(struct bpf_program *prog,
|
struct bpf_link *bpf_program__attach_raw_tracepoint(struct bpf_program *prog,
|
||||||
const char *tp_name)
|
const char *tp_name)
|
||||||
{
|
{
|
||||||
char errmsg[STRERR_BUFSIZE];
|
char errmsg[STRERR_BUFSIZE];
|
||||||
struct bpf_link_fd *link;
|
struct bpf_link *link;
|
||||||
int prog_fd, pfd;
|
int prog_fd, pfd;
|
||||||
|
|
||||||
prog_fd = bpf_program__fd(prog);
|
prog_fd = bpf_program__fd(prog);
|
||||||
@@ -7331,7 +7506,7 @@ struct bpf_link *bpf_program__attach_raw_tracepoint(struct bpf_program *prog,
|
|||||||
link = calloc(1, sizeof(*link));
|
link = calloc(1, sizeof(*link));
|
||||||
if (!link)
|
if (!link)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
link->link.detach = &bpf_link__detach_fd;
|
link->detach = &bpf_link__detach_fd;
|
||||||
|
|
||||||
pfd = bpf_raw_tracepoint_open(tp_name, prog_fd);
|
pfd = bpf_raw_tracepoint_open(tp_name, prog_fd);
|
||||||
if (pfd < 0) {
|
if (pfd < 0) {
|
||||||
@@ -7343,7 +7518,7 @@ struct bpf_link *bpf_program__attach_raw_tracepoint(struct bpf_program *prog,
|
|||||||
return ERR_PTR(pfd);
|
return ERR_PTR(pfd);
|
||||||
}
|
}
|
||||||
link->fd = pfd;
|
link->fd = pfd;
|
||||||
return (struct bpf_link *)link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct bpf_link *attach_raw_tp(const struct bpf_sec_def *sec,
|
static struct bpf_link *attach_raw_tp(const struct bpf_sec_def *sec,
|
||||||
@@ -7354,10 +7529,11 @@ static struct bpf_link *attach_raw_tp(const struct bpf_sec_def *sec,
|
|||||||
return bpf_program__attach_raw_tracepoint(prog, tp_name);
|
return bpf_program__attach_raw_tracepoint(prog, tp_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bpf_link *bpf_program__attach_trace(struct bpf_program *prog)
|
/* Common logic for all BPF program types that attach to a btf_id */
|
||||||
|
static struct bpf_link *bpf_program__attach_btf_id(struct bpf_program *prog)
|
||||||
{
|
{
|
||||||
char errmsg[STRERR_BUFSIZE];
|
char errmsg[STRERR_BUFSIZE];
|
||||||
struct bpf_link_fd *link;
|
struct bpf_link *link;
|
||||||
int prog_fd, pfd;
|
int prog_fd, pfd;
|
||||||
|
|
||||||
prog_fd = bpf_program__fd(prog);
|
prog_fd = bpf_program__fd(prog);
|
||||||
@@ -7370,13 +7546,13 @@ struct bpf_link *bpf_program__attach_trace(struct bpf_program *prog)
|
|||||||
link = calloc(1, sizeof(*link));
|
link = calloc(1, sizeof(*link));
|
||||||
if (!link)
|
if (!link)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
link->link.detach = &bpf_link__detach_fd;
|
link->detach = &bpf_link__detach_fd;
|
||||||
|
|
||||||
pfd = bpf_raw_tracepoint_open(NULL, prog_fd);
|
pfd = bpf_raw_tracepoint_open(NULL, prog_fd);
|
||||||
if (pfd < 0) {
|
if (pfd < 0) {
|
||||||
pfd = -errno;
|
pfd = -errno;
|
||||||
free(link);
|
free(link);
|
||||||
pr_warn("program '%s': failed to attach to trace: %s\n",
|
pr_warn("program '%s': failed to attach: %s\n",
|
||||||
bpf_program__title(prog, false),
|
bpf_program__title(prog, false),
|
||||||
libbpf_strerror_r(pfd, errmsg, sizeof(errmsg)));
|
libbpf_strerror_r(pfd, errmsg, sizeof(errmsg)));
|
||||||
return ERR_PTR(pfd);
|
return ERR_PTR(pfd);
|
||||||
@@ -7385,12 +7561,62 @@ struct bpf_link *bpf_program__attach_trace(struct bpf_program *prog)
|
|||||||
return (struct bpf_link *)link;
|
return (struct bpf_link *)link;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct bpf_link *bpf_program__attach_trace(struct bpf_program *prog)
|
||||||
|
{
|
||||||
|
return bpf_program__attach_btf_id(prog);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bpf_link *bpf_program__attach_lsm(struct bpf_program *prog)
|
||||||
|
{
|
||||||
|
return bpf_program__attach_btf_id(prog);
|
||||||
|
}
|
||||||
|
|
||||||
static struct bpf_link *attach_trace(const struct bpf_sec_def *sec,
|
static struct bpf_link *attach_trace(const struct bpf_sec_def *sec,
|
||||||
struct bpf_program *prog)
|
struct bpf_program *prog)
|
||||||
{
|
{
|
||||||
return bpf_program__attach_trace(prog);
|
return bpf_program__attach_trace(prog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct bpf_link *attach_lsm(const struct bpf_sec_def *sec,
|
||||||
|
struct bpf_program *prog)
|
||||||
|
{
|
||||||
|
return bpf_program__attach_lsm(prog);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bpf_link *
|
||||||
|
bpf_program__attach_cgroup(struct bpf_program *prog, int cgroup_fd)
|
||||||
|
{
|
||||||
|
enum bpf_attach_type attach_type;
|
||||||
|
char errmsg[STRERR_BUFSIZE];
|
||||||
|
struct bpf_link *link;
|
||||||
|
int prog_fd, link_fd;
|
||||||
|
|
||||||
|
prog_fd = bpf_program__fd(prog);
|
||||||
|
if (prog_fd < 0) {
|
||||||
|
pr_warn("program '%s': can't attach before loaded\n",
|
||||||
|
bpf_program__title(prog, false));
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
link = calloc(1, sizeof(*link));
|
||||||
|
if (!link)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
link->detach = &bpf_link__detach_fd;
|
||||||
|
|
||||||
|
attach_type = bpf_program__get_expected_attach_type(prog);
|
||||||
|
link_fd = bpf_link_create(prog_fd, cgroup_fd, attach_type, NULL);
|
||||||
|
if (link_fd < 0) {
|
||||||
|
link_fd = -errno;
|
||||||
|
free(link);
|
||||||
|
pr_warn("program '%s': failed to attach to cgroup: %s\n",
|
||||||
|
bpf_program__title(prog, false),
|
||||||
|
libbpf_strerror_r(link_fd, errmsg, sizeof(errmsg)));
|
||||||
|
return ERR_PTR(link_fd);
|
||||||
|
}
|
||||||
|
link->fd = link_fd;
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
|
||||||
struct bpf_link *bpf_program__attach(struct bpf_program *prog)
|
struct bpf_link *bpf_program__attach(struct bpf_program *prog)
|
||||||
{
|
{
|
||||||
const struct bpf_sec_def *sec_def;
|
const struct bpf_sec_def *sec_def;
|
||||||
@@ -7404,10 +7630,9 @@ struct bpf_link *bpf_program__attach(struct bpf_program *prog)
|
|||||||
|
|
||||||
static int bpf_link__detach_struct_ops(struct bpf_link *link)
|
static int bpf_link__detach_struct_ops(struct bpf_link *link)
|
||||||
{
|
{
|
||||||
struct bpf_link_fd *l = (void *)link;
|
|
||||||
__u32 zero = 0;
|
__u32 zero = 0;
|
||||||
|
|
||||||
if (bpf_map_delete_elem(l->fd, &zero))
|
if (bpf_map_delete_elem(link->fd, &zero))
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -7416,7 +7641,7 @@ static int bpf_link__detach_struct_ops(struct bpf_link *link)
|
|||||||
struct bpf_link *bpf_map__attach_struct_ops(struct bpf_map *map)
|
struct bpf_link *bpf_map__attach_struct_ops(struct bpf_map *map)
|
||||||
{
|
{
|
||||||
struct bpf_struct_ops *st_ops;
|
struct bpf_struct_ops *st_ops;
|
||||||
struct bpf_link_fd *link;
|
struct bpf_link *link;
|
||||||
__u32 i, zero = 0;
|
__u32 i, zero = 0;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@@ -7448,10 +7673,10 @@ struct bpf_link *bpf_map__attach_struct_ops(struct bpf_map *map)
|
|||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
link->link.detach = bpf_link__detach_struct_ops;
|
link->detach = bpf_link__detach_struct_ops;
|
||||||
link->fd = map->fd;
|
link->fd = map->fd;
|
||||||
|
|
||||||
return (struct bpf_link *)link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum bpf_perf_event_ret
|
enum bpf_perf_event_ret
|
||||||
@@ -8132,6 +8357,31 @@ void bpf_program__bpil_offs_to_addr(struct bpf_prog_info_linear *info_linear)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bpf_program__set_attach_target(struct bpf_program *prog,
|
||||||
|
int attach_prog_fd,
|
||||||
|
const char *attach_func_name)
|
||||||
|
{
|
||||||
|
int btf_id;
|
||||||
|
|
||||||
|
if (!prog || attach_prog_fd < 0 || !attach_func_name)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (attach_prog_fd)
|
||||||
|
btf_id = libbpf_find_prog_btf_id(attach_func_name,
|
||||||
|
attach_prog_fd);
|
||||||
|
else
|
||||||
|
btf_id = __find_vmlinux_btf_id(prog->obj->btf_vmlinux,
|
||||||
|
attach_func_name,
|
||||||
|
prog->expected_attach_type);
|
||||||
|
|
||||||
|
if (btf_id < 0)
|
||||||
|
return btf_id;
|
||||||
|
|
||||||
|
prog->attach_btf_id = btf_id;
|
||||||
|
prog->attach_prog_fd = attach_prog_fd;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int parse_cpu_mask_str(const char *s, bool **mask, int *mask_sz)
|
int parse_cpu_mask_str(const char *s, bool **mask, int *mask_sz)
|
||||||
{
|
{
|
||||||
int err = 0, n, len, start, end = -1;
|
int err = 0, n, len, start, end = -1;
|
||||||
|
|||||||
31
src/libbpf.h
31
src/libbpf.h
@@ -219,6 +219,13 @@ LIBBPF_API void bpf_program__unload(struct bpf_program *prog);
|
|||||||
|
|
||||||
struct bpf_link;
|
struct bpf_link;
|
||||||
|
|
||||||
|
LIBBPF_API struct bpf_link *bpf_link__open(const char *path);
|
||||||
|
LIBBPF_API int bpf_link__fd(const struct bpf_link *link);
|
||||||
|
LIBBPF_API const char *bpf_link__pin_path(const struct bpf_link *link);
|
||||||
|
LIBBPF_API int bpf_link__pin(struct bpf_link *link, const char *path);
|
||||||
|
LIBBPF_API int bpf_link__unpin(struct bpf_link *link);
|
||||||
|
LIBBPF_API int bpf_link__update_program(struct bpf_link *link,
|
||||||
|
struct bpf_program *prog);
|
||||||
LIBBPF_API void bpf_link__disconnect(struct bpf_link *link);
|
LIBBPF_API 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);
|
||||||
|
|
||||||
@@ -240,11 +247,17 @@ bpf_program__attach_tracepoint(struct bpf_program *prog,
|
|||||||
LIBBPF_API struct bpf_link *
|
LIBBPF_API struct bpf_link *
|
||||||
bpf_program__attach_raw_tracepoint(struct bpf_program *prog,
|
bpf_program__attach_raw_tracepoint(struct bpf_program *prog,
|
||||||
const char *tp_name);
|
const char *tp_name);
|
||||||
|
|
||||||
LIBBPF_API struct bpf_link *
|
LIBBPF_API struct bpf_link *
|
||||||
bpf_program__attach_trace(struct bpf_program *prog);
|
bpf_program__attach_trace(struct bpf_program *prog);
|
||||||
|
LIBBPF_API struct bpf_link *
|
||||||
|
bpf_program__attach_lsm(struct bpf_program *prog);
|
||||||
|
LIBBPF_API struct bpf_link *
|
||||||
|
bpf_program__attach_cgroup(struct bpf_program *prog, int cgroup_fd);
|
||||||
|
|
||||||
struct bpf_map;
|
struct bpf_map;
|
||||||
|
|
||||||
LIBBPF_API struct bpf_link *bpf_map__attach_struct_ops(struct bpf_map *map);
|
LIBBPF_API struct bpf_link *bpf_map__attach_struct_ops(struct bpf_map *map);
|
||||||
|
|
||||||
struct bpf_insn;
|
struct bpf_insn;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -316,6 +329,7 @@ LIBBPF_API int bpf_program__set_socket_filter(struct bpf_program *prog);
|
|||||||
LIBBPF_API int bpf_program__set_tracepoint(struct bpf_program *prog);
|
LIBBPF_API int bpf_program__set_tracepoint(struct bpf_program *prog);
|
||||||
LIBBPF_API int bpf_program__set_raw_tracepoint(struct bpf_program *prog);
|
LIBBPF_API int bpf_program__set_raw_tracepoint(struct bpf_program *prog);
|
||||||
LIBBPF_API int bpf_program__set_kprobe(struct bpf_program *prog);
|
LIBBPF_API int bpf_program__set_kprobe(struct bpf_program *prog);
|
||||||
|
LIBBPF_API int bpf_program__set_lsm(struct bpf_program *prog);
|
||||||
LIBBPF_API int bpf_program__set_sched_cls(struct bpf_program *prog);
|
LIBBPF_API int bpf_program__set_sched_cls(struct bpf_program *prog);
|
||||||
LIBBPF_API int bpf_program__set_sched_act(struct bpf_program *prog);
|
LIBBPF_API int bpf_program__set_sched_act(struct bpf_program *prog);
|
||||||
LIBBPF_API int bpf_program__set_xdp(struct bpf_program *prog);
|
LIBBPF_API int bpf_program__set_xdp(struct bpf_program *prog);
|
||||||
@@ -334,10 +348,15 @@ LIBBPF_API void
|
|||||||
bpf_program__set_expected_attach_type(struct bpf_program *prog,
|
bpf_program__set_expected_attach_type(struct bpf_program *prog,
|
||||||
enum bpf_attach_type type);
|
enum bpf_attach_type type);
|
||||||
|
|
||||||
|
LIBBPF_API int
|
||||||
|
bpf_program__set_attach_target(struct bpf_program *prog, int attach_prog_fd,
|
||||||
|
const char *attach_func_name);
|
||||||
|
|
||||||
LIBBPF_API bool bpf_program__is_socket_filter(const struct bpf_program *prog);
|
LIBBPF_API bool bpf_program__is_socket_filter(const struct bpf_program *prog);
|
||||||
LIBBPF_API bool bpf_program__is_tracepoint(const struct bpf_program *prog);
|
LIBBPF_API bool bpf_program__is_tracepoint(const struct bpf_program *prog);
|
||||||
LIBBPF_API bool bpf_program__is_raw_tracepoint(const struct bpf_program *prog);
|
LIBBPF_API bool bpf_program__is_raw_tracepoint(const struct bpf_program *prog);
|
||||||
LIBBPF_API bool bpf_program__is_kprobe(const struct bpf_program *prog);
|
LIBBPF_API bool bpf_program__is_kprobe(const struct bpf_program *prog);
|
||||||
|
LIBBPF_API bool bpf_program__is_lsm(const struct bpf_program *prog);
|
||||||
LIBBPF_API bool bpf_program__is_sched_cls(const struct bpf_program *prog);
|
LIBBPF_API bool bpf_program__is_sched_cls(const struct bpf_program *prog);
|
||||||
LIBBPF_API bool bpf_program__is_sched_act(const struct bpf_program *prog);
|
LIBBPF_API bool bpf_program__is_sched_act(const struct bpf_program *prog);
|
||||||
LIBBPF_API bool bpf_program__is_xdp(const struct bpf_program *prog);
|
LIBBPF_API bool bpf_program__is_xdp(const struct bpf_program *prog);
|
||||||
@@ -398,6 +417,8 @@ typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);
|
|||||||
LIBBPF_API int bpf_map__set_priv(struct bpf_map *map, void *priv,
|
LIBBPF_API int bpf_map__set_priv(struct bpf_map *map, void *priv,
|
||||||
bpf_map_clear_priv_t clear_priv);
|
bpf_map_clear_priv_t clear_priv);
|
||||||
LIBBPF_API void *bpf_map__priv(const struct bpf_map *map);
|
LIBBPF_API void *bpf_map__priv(const struct bpf_map *map);
|
||||||
|
LIBBPF_API int bpf_map__set_initial_value(struct bpf_map *map,
|
||||||
|
const void *data, size_t size);
|
||||||
LIBBPF_API int bpf_map__reuse_fd(struct bpf_map *map, int fd);
|
LIBBPF_API int bpf_map__reuse_fd(struct bpf_map *map, int fd);
|
||||||
LIBBPF_API int bpf_map__resize(struct bpf_map *map, __u32 max_entries);
|
LIBBPF_API int bpf_map__resize(struct bpf_map *map, __u32 max_entries);
|
||||||
LIBBPF_API bool bpf_map__is_offload_neutral(const struct bpf_map *map);
|
LIBBPF_API bool bpf_map__is_offload_neutral(const struct bpf_map *map);
|
||||||
@@ -435,7 +456,15 @@ struct xdp_link_info {
|
|||||||
__u8 attach_mode;
|
__u8 attach_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct bpf_xdp_set_link_opts {
|
||||||
|
size_t sz;
|
||||||
|
int old_fd;
|
||||||
|
};
|
||||||
|
#define bpf_xdp_set_link_opts__last_field old_fd
|
||||||
|
|
||||||
LIBBPF_API int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags);
|
LIBBPF_API int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags);
|
||||||
|
LIBBPF_API int bpf_set_link_xdp_fd_opts(int ifindex, int fd, __u32 flags,
|
||||||
|
const struct bpf_xdp_set_link_opts *opts);
|
||||||
LIBBPF_API int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags);
|
LIBBPF_API int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags);
|
||||||
LIBBPF_API int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info,
|
LIBBPF_API int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info,
|
||||||
size_t info_size, __u32 flags);
|
size_t info_size, __u32 flags);
|
||||||
|
|||||||
@@ -235,3 +235,22 @@ LIBBPF_0.0.7 {
|
|||||||
btf__align_of;
|
btf__align_of;
|
||||||
libbpf_find_kernel_btf;
|
libbpf_find_kernel_btf;
|
||||||
} LIBBPF_0.0.6;
|
} LIBBPF_0.0.6;
|
||||||
|
|
||||||
|
LIBBPF_0.0.8 {
|
||||||
|
global:
|
||||||
|
bpf_link__fd;
|
||||||
|
bpf_link__open;
|
||||||
|
bpf_link__pin;
|
||||||
|
bpf_link__pin_path;
|
||||||
|
bpf_link__unpin;
|
||||||
|
bpf_link__update_program;
|
||||||
|
bpf_link_create;
|
||||||
|
bpf_link_update;
|
||||||
|
bpf_map__set_initial_value;
|
||||||
|
bpf_program__attach_cgroup;
|
||||||
|
bpf_program__attach_lsm;
|
||||||
|
bpf_program__is_lsm;
|
||||||
|
bpf_program__set_attach_target;
|
||||||
|
bpf_program__set_lsm;
|
||||||
|
bpf_set_link_xdp_fd_opts;
|
||||||
|
} LIBBPF_0.0.7;
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ probe_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns,
|
|||||||
case BPF_PROG_TYPE_TRACING:
|
case BPF_PROG_TYPE_TRACING:
|
||||||
case BPF_PROG_TYPE_STRUCT_OPS:
|
case BPF_PROG_TYPE_STRUCT_OPS:
|
||||||
case BPF_PROG_TYPE_EXT:
|
case BPF_PROG_TYPE_EXT:
|
||||||
|
case BPF_PROG_TYPE_LSM:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,7 +132,8 @@ done:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
|
static int __bpf_set_link_xdp_fd_replace(int ifindex, int fd, int old_fd,
|
||||||
|
__u32 flags)
|
||||||
{
|
{
|
||||||
int sock, seq = 0, ret;
|
int sock, seq = 0, ret;
|
||||||
struct nlattr *nla, *nla_xdp;
|
struct nlattr *nla, *nla_xdp;
|
||||||
@@ -141,7 +142,7 @@ int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
|
|||||||
struct ifinfomsg ifinfo;
|
struct ifinfomsg ifinfo;
|
||||||
char attrbuf[64];
|
char attrbuf[64];
|
||||||
} req;
|
} req;
|
||||||
__u32 nl_pid;
|
__u32 nl_pid = 0;
|
||||||
|
|
||||||
sock = libbpf_netlink_open(&nl_pid);
|
sock = libbpf_netlink_open(&nl_pid);
|
||||||
if (sock < 0)
|
if (sock < 0)
|
||||||
@@ -178,6 +179,14 @@ int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
|
|||||||
nla->nla_len += nla_xdp->nla_len;
|
nla->nla_len += nla_xdp->nla_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & XDP_FLAGS_REPLACE) {
|
||||||
|
nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
|
||||||
|
nla_xdp->nla_type = IFLA_XDP_EXPECTED_FD;
|
||||||
|
nla_xdp->nla_len = NLA_HDRLEN + sizeof(old_fd);
|
||||||
|
memcpy((char *)nla_xdp + NLA_HDRLEN, &old_fd, sizeof(old_fd));
|
||||||
|
nla->nla_len += nla_xdp->nla_len;
|
||||||
|
}
|
||||||
|
|
||||||
req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);
|
req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);
|
||||||
|
|
||||||
if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
|
if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
|
||||||
@@ -191,6 +200,29 @@ cleanup:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bpf_set_link_xdp_fd_opts(int ifindex, int fd, __u32 flags,
|
||||||
|
const struct bpf_xdp_set_link_opts *opts)
|
||||||
|
{
|
||||||
|
int old_fd = -1;
|
||||||
|
|
||||||
|
if (!OPTS_VALID(opts, bpf_xdp_set_link_opts))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (OPTS_HAS(opts, old_fd)) {
|
||||||
|
old_fd = OPTS_GET(opts, old_fd, -1);
|
||||||
|
flags |= XDP_FLAGS_REPLACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return __bpf_set_link_xdp_fd_replace(ifindex, fd,
|
||||||
|
old_fd,
|
||||||
|
flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
|
||||||
|
{
|
||||||
|
return __bpf_set_link_xdp_fd_replace(ifindex, fd, 0, flags);
|
||||||
|
}
|
||||||
|
|
||||||
static int __dump_link_nlmsg(struct nlmsghdr *nlh,
|
static int __dump_link_nlmsg(struct nlmsghdr *nlh,
|
||||||
libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie)
|
libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie)
|
||||||
{
|
{
|
||||||
@@ -256,7 +288,7 @@ int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info,
|
|||||||
{
|
{
|
||||||
struct xdp_id_md xdp_id = {};
|
struct xdp_id_md xdp_id = {};
|
||||||
int sock, ret;
|
int sock, ret;
|
||||||
__u32 nl_pid;
|
__u32 nl_pid = 0;
|
||||||
__u32 mask;
|
__u32 mask;
|
||||||
|
|
||||||
if (flags & ~XDP_FLAGS_MASK || !info_size)
|
if (flags & ~XDP_FLAGS_MASK || !info_size)
|
||||||
@@ -289,7 +321,7 @@ int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info,
|
|||||||
|
|
||||||
static __u32 get_xdp_id(struct xdp_link_info *info, __u32 flags)
|
static __u32 get_xdp_id(struct xdp_link_info *info, __u32 flags)
|
||||||
{
|
{
|
||||||
if (info->attach_mode != XDP_ATTACHED_MULTI)
|
if (info->attach_mode != XDP_ATTACHED_MULTI && !flags)
|
||||||
return info->prog_id;
|
return info->prog_id;
|
||||||
if (flags & XDP_FLAGS_DRV_MODE)
|
if (flags & XDP_FLAGS_DRV_MODE)
|
||||||
return info->drv_prog_id;
|
return info->drv_prog_id;
|
||||||
|
|||||||
16
src/xsk.c
16
src/xsk.c
@@ -280,7 +280,11 @@ int xsk_umem__create_v0_0_4(struct xsk_umem **umem_ptr, void *umem_area,
|
|||||||
fill->consumer = map + off.fr.consumer;
|
fill->consumer = map + off.fr.consumer;
|
||||||
fill->flags = map + off.fr.flags;
|
fill->flags = map + off.fr.flags;
|
||||||
fill->ring = map + off.fr.desc;
|
fill->ring = map + off.fr.desc;
|
||||||
fill->cached_cons = umem->config.fill_size;
|
fill->cached_prod = *fill->producer;
|
||||||
|
/* cached_cons is "size" bigger than the real consumer pointer
|
||||||
|
* See xsk_prod_nb_free
|
||||||
|
*/
|
||||||
|
fill->cached_cons = *fill->consumer + umem->config.fill_size;
|
||||||
|
|
||||||
map = mmap(NULL, off.cr.desc + umem->config.comp_size * sizeof(__u64),
|
map = mmap(NULL, off.cr.desc + umem->config.comp_size * sizeof(__u64),
|
||||||
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, umem->fd,
|
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, umem->fd,
|
||||||
@@ -297,6 +301,8 @@ int xsk_umem__create_v0_0_4(struct xsk_umem **umem_ptr, void *umem_area,
|
|||||||
comp->consumer = map + off.cr.consumer;
|
comp->consumer = map + off.cr.consumer;
|
||||||
comp->flags = map + off.cr.flags;
|
comp->flags = map + off.cr.flags;
|
||||||
comp->ring = map + off.cr.desc;
|
comp->ring = map + off.cr.desc;
|
||||||
|
comp->cached_prod = *comp->producer;
|
||||||
|
comp->cached_cons = *comp->consumer;
|
||||||
|
|
||||||
*umem_ptr = umem;
|
*umem_ptr = umem;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -672,6 +678,8 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
|
|||||||
rx->consumer = rx_map + off.rx.consumer;
|
rx->consumer = rx_map + off.rx.consumer;
|
||||||
rx->flags = rx_map + off.rx.flags;
|
rx->flags = rx_map + off.rx.flags;
|
||||||
rx->ring = rx_map + off.rx.desc;
|
rx->ring = rx_map + off.rx.desc;
|
||||||
|
rx->cached_prod = *rx->producer;
|
||||||
|
rx->cached_cons = *rx->consumer;
|
||||||
}
|
}
|
||||||
xsk->rx = rx;
|
xsk->rx = rx;
|
||||||
|
|
||||||
@@ -691,7 +699,11 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
|
|||||||
tx->consumer = tx_map + off.tx.consumer;
|
tx->consumer = tx_map + off.tx.consumer;
|
||||||
tx->flags = tx_map + off.tx.flags;
|
tx->flags = tx_map + off.tx.flags;
|
||||||
tx->ring = tx_map + off.tx.desc;
|
tx->ring = tx_map + off.tx.desc;
|
||||||
tx->cached_cons = xsk->config.tx_size;
|
tx->cached_prod = *tx->producer;
|
||||||
|
/* cached_cons is r->size bigger than the real consumer pointer
|
||||||
|
* See xsk_prod_nb_free
|
||||||
|
*/
|
||||||
|
tx->cached_cons = *tx->consumer + xsk->config.tx_size;
|
||||||
}
|
}
|
||||||
xsk->tx = tx;
|
xsk->tx = tx;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
PHASES=(${@:-SETUP RUN RUN_ASAN CLEANUP})
|
PHASES=(${@:-SETUP RUN RUN_ASAN CLEANUP})
|
||||||
DEBIAN_RELEASE="${DEBIAN_RELEASE:-testing}"
|
DEBIAN_RELEASE="${DEBIAN_RELEASE:-testing}"
|
||||||
CONT_NAME="${CONT_NAME:-debian-$DEBIAN_RELEASE-$RANDOM}"
|
CONT_NAME="${CONT_NAME:-libbpf-debian-$DEBIAN_RELEASE}"
|
||||||
ENV_VARS="${ENV_VARS:-}"
|
ENV_VARS="${ENV_VARS:-}"
|
||||||
DOCKER_RUN="${DOCKER_RUN:-docker run}"
|
DOCKER_RUN="${DOCKER_RUN:-docker run}"
|
||||||
REPO_ROOT="${REPO_ROOT:-$PWD}"
|
REPO_ROOT="${REPO_ROOT:-$PWD}"
|
||||||
@@ -30,6 +30,10 @@ for phase in "${PHASES[@]}"; do
|
|||||||
SETUP)
|
SETUP)
|
||||||
info "Setup phase"
|
info "Setup phase"
|
||||||
info "Using Debian $DEBIAN_RELEASE"
|
info "Using Debian $DEBIAN_RELEASE"
|
||||||
|
|
||||||
|
sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
|
||||||
|
docker --version
|
||||||
|
|
||||||
docker pull debian:$DEBIAN_RELEASE
|
docker pull debian:$DEBIAN_RELEASE
|
||||||
info "Starting container $CONT_NAME"
|
info "Starting container $CONT_NAME"
|
||||||
$DOCKER_RUN -v $REPO_ROOT:/build:rw \
|
$DOCKER_RUN -v $REPO_ROOT:/build:rw \
|
||||||
@@ -57,7 +61,7 @@ for phase in "${PHASES[@]}"; do
|
|||||||
docker_exec mkdir build install
|
docker_exec mkdir build install
|
||||||
docker_exec ${CC:-cc} --version
|
docker_exec ${CC:-cc} --version
|
||||||
info "build"
|
info "build"
|
||||||
docker_exec make CFLAGS="${CFLAGS}" -C ./src -B OBJDIR=../build
|
docker_exec make -j$((4*$(nproc))) CFLAGS="${CFLAGS}" -C ./src -B OBJDIR=../build
|
||||||
info "ldd build/libbpf.so:"
|
info "ldd build/libbpf.so:"
|
||||||
docker_exec ldd build/libbpf.so
|
docker_exec ldd build/libbpf.so
|
||||||
if ! docker_exec ldd build/libbpf.so | grep -q libelf; then
|
if ! docker_exec ldd build/libbpf.so | grep -q libelf; then
|
||||||
@@ -65,7 +69,7 @@ for phase in "${PHASES[@]}"; do
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
info "install"
|
info "install"
|
||||||
docker_exec make -C src OBJDIR=../build DESTDIR=../install install
|
docker_exec make -j$((4*$(nproc))) -C src OBJDIR=../build DESTDIR=../install install
|
||||||
docker_exec rm -rf build install
|
docker_exec rm -rf build install
|
||||||
;;
|
;;
|
||||||
CLEANUP)
|
CLEANUP)
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ cd $REPO_ROOT
|
|||||||
CFLAGS="-g -O2 -Werror -Wall -fsanitize=address,undefined"
|
CFLAGS="-g -O2 -Werror -Wall -fsanitize=address,undefined"
|
||||||
mkdir build install
|
mkdir build install
|
||||||
cc --version
|
cc --version
|
||||||
make CFLAGS="${CFLAGS}" -C ./src -B OBJDIR=../build
|
make -j$((4*$(nproc))) CFLAGS="${CFLAGS}" -C ./src -B OBJDIR=../build
|
||||||
ldd build/libbpf.so
|
ldd build/libbpf.so
|
||||||
if ! ldd build/libbpf.so | grep -q libelf; then
|
if ! ldd build/libbpf.so | grep -q libelf; then
|
||||||
echo "FAIL: No reference to libelf.so in libbpf.so!"
|
echo "FAIL: No reference to libelf.so in libbpf.so!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
make -C src OBJDIR=../build DESTDIR=../install install
|
make -j$((4*$(nproc))) -C src OBJDIR=../build DESTDIR=../install install
|
||||||
rm -rf build install
|
rm -rf build install
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
#!/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
|
|
||||||
25
travis-ci/vmtest/build_pahole.sh
Executable file
25
travis-ci/vmtest/build_pahole.sh
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
CWD=$(pwd)
|
||||||
|
REPO_PATH=$1
|
||||||
|
PAHOLE_ORIGIN=https://git.kernel.org/pub/scm/devel/pahole/pahole.git
|
||||||
|
|
||||||
|
mkdir -p ${REPO_PATH}
|
||||||
|
cd ${REPO_PATH}
|
||||||
|
git init
|
||||||
|
git remote add origin ${PAHOLE_ORIGIN}
|
||||||
|
git fetch origin
|
||||||
|
git checkout master
|
||||||
|
|
||||||
|
mkdir -p build
|
||||||
|
cd build
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -D__LIB=lib ..
|
||||||
|
make -j$((4*$(nproc))) all
|
||||||
|
sudo make install
|
||||||
|
|
||||||
|
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH:-}:/usr/local/lib
|
||||||
|
ldd $(which pahole)
|
||||||
|
pahole --version
|
||||||
|
|
||||||
@@ -1,11 +1,16 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
LLVM_VER=11
|
||||||
LIBBPF_PATH="${REPO_ROOT}"
|
LIBBPF_PATH="${REPO_ROOT}"
|
||||||
REPO_PATH="travis-ci/vmtest/bpf-next"
|
REPO_PATH="travis-ci/vmtest/bpf-next"
|
||||||
|
|
||||||
|
# temporary work-around for failing tests
|
||||||
|
rm "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c"
|
||||||
|
|
||||||
make \
|
make \
|
||||||
CLANG=clang-10 \
|
CLANG=clang-${LLVM_VER} \
|
||||||
LLC=llc-10 \
|
LLC=llc-${LLVM_VER} \
|
||||||
LLVM_STRIP=llvm-strip-10 \
|
LLVM_STRIP=llvm-strip-${LLVM_VER} \
|
||||||
VMLINUX_BTF="${VMLINUX_BTF}" \
|
VMLINUX_BTF="${VMLINUX_BTF}" \
|
||||||
-C "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" \
|
-C "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" \
|
||||||
-j $((4*$(nproc)))
|
-j $((4*$(nproc)))
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ if [ ! -d "${REPO_PATH}" ]; then
|
|||||||
cd ${REPO_PATH}
|
cd ${REPO_PATH}
|
||||||
git init
|
git init
|
||||||
git remote add bpf-next ${BPF_NEXT_ORIGIN}
|
git remote add bpf-next ${BPF_NEXT_ORIGIN}
|
||||||
git fetch --depth ${GIT_FETCH_DEPTH} bpf-next
|
for depth in 32 64 128; do
|
||||||
git reset --hard ${LINUX_SHA}
|
git fetch --depth ${depth} bpf-next
|
||||||
else
|
git reset --hard ${LINUX_SHA} && break
|
||||||
cd ${REPO_PATH}
|
done
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
INDEX https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/INDEX
|
INDEX https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/INDEX
|
||||||
libbpf-vmtest-rootfs-2020.01.10.tar.zst https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/libbpf-vmtest-rootfs-2020.01.10.tar.zst
|
libbpf-vmtest-rootfs-2020.03.11.tar.zst https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/libbpf-vmtest-rootfs-2020.03.11.tar.zst
|
||||||
vmlinux-5.5.0-rc6.zst https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinux-5.5.0-rc6.zst
|
vmlinux-5.5.0-rc6.zst https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinux-5.5.0-rc6.zst
|
||||||
vmlinux-5.5.0.zst https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinux-5.5.0.zst
|
vmlinux-5.5.0.zst https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinux-5.5.0.zst
|
||||||
vmlinuz-5.5.0-rc6 https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinuz-5.5.0-rc6
|
vmlinuz-5.5.0-rc6 https://libbpf-vmtest.s3-us-west-1.amazonaws.com/x86_64/vmlinuz-5.5.0-rc6
|
||||||
|
|||||||
@@ -1,21 +1,27 @@
|
|||||||
mmap
|
# PERMANENTLY DISABLED
|
||||||
dctcp
|
bpf_tcp_ca # STRUCT_OPS is missing
|
||||||
cubic
|
cgroup_attach_multi # BPF_F_REPLACE_PROG missing
|
||||||
bpf_tcp_ca
|
cgroup_link # LINK_CREATE is missing
|
||||||
bpf_verif_scale
|
fentry_fexit # bpf_prog_test_tracing missing
|
||||||
cgroup_attach
|
fentry_test # bpf_prog_test_tracing missing
|
||||||
pinning
|
fexit_bpf2bpf # freplace is missing
|
||||||
send_signal_tracepoint_thread
|
fexit_test # bpf_prog_test_tracing missing
|
||||||
test_syncookie
|
get_stack_raw_tp # exercising BPF verifier bug causing infinite loop
|
||||||
select_reuseport
|
link_pinning # bpf_link is missing
|
||||||
send_signal
|
mmap # 5.5 kernel is too permissive with re-mmaping
|
||||||
sockopt_inherit
|
modify_return # fmod_ret is missing
|
||||||
strobemeta_nounroll2
|
ns_current_pid_tgid # bpf_get_ns_current_pid_tgid() helper is missing
|
||||||
stacktrace_build_id
|
perf_branches # bpf_read_branch_records() helper is missing
|
||||||
tp_attach_query
|
select_reuseport # UDP support is missing
|
||||||
tcp_rtt
|
sk_assign # bpf_sk_assign helper missing
|
||||||
task_fd_query_tp
|
sockmap_listen # no listen socket supportin SOCKMAP
|
||||||
stacktrace_map
|
skb_ctx # ctx_{size, }_{in, out} in BPF_PROG_TEST_RUN is missing
|
||||||
test_global_funcs
|
test_global_funcs # kernel doesn't support BTF linkage=global on FUNCs
|
||||||
skb_ctx
|
test_lsm # no BPF_LSM support
|
||||||
fexit_bpf2bpf
|
vmlinux # hrtimer_nanosleep() signature changed incompatibly
|
||||||
|
xdp_attach # IFLA_XDP_EXPECTED_FD support is missing
|
||||||
|
xdp_bpf2bpf # freplace is missing
|
||||||
|
|
||||||
|
|
||||||
|
# TEMPORARILY DISABLED
|
||||||
|
send_signal # flaky
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,23 +1,4 @@
|
|||||||
mmap
|
# TEMPORARILY DISABLED
|
||||||
dctcp
|
send_signal # flaky
|
||||||
cubic
|
test_lsm # semi-working
|
||||||
bpf_tcp_ca
|
sk_assign # needs better setup in Travis CI
|
||||||
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
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
148
travis-ci/vmtest/mkrootfs.sh
Executable file
148
travis-ci/vmtest/mkrootfs.sh
Executable file
@@ -0,0 +1,148 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# This script is based on drgn script for generating Arch Linux bootstrap
|
||||||
|
# images.
|
||||||
|
# https://github.com/osandov/drgn/blob/master/scripts/vmtest/mkrootfs.sh
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
usage () {
|
||||||
|
USAGE_STRING="usage: $0 [NAME]
|
||||||
|
$0 -h
|
||||||
|
|
||||||
|
Build an Arch Linux root filesystem image for testing libbpf in a virtual
|
||||||
|
machine.
|
||||||
|
|
||||||
|
The image is generated as a zstd-compressed tarball.
|
||||||
|
|
||||||
|
This must be run as root, as most of the installation is done in a chroot.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
NAME name of generated image file (default:
|
||||||
|
libbpf-vmtest-rootfs-\$DATE.tar.zst)
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h display this help message and exit"
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
out)
|
||||||
|
echo "$USAGE_STRING"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
err)
|
||||||
|
echo "$USAGE_STRING" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
while getopts "h" OPT; do
|
||||||
|
case "$OPT" in
|
||||||
|
h)
|
||||||
|
usage out
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage err
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
if [[ $OPTIND -eq $# ]]; then
|
||||||
|
NAME="${!OPTIND}"
|
||||||
|
elif [[ $OPTIND -gt $# ]]; then
|
||||||
|
NAME="libbpf-vmtest-rootfs-$(date +%Y.%m.%d).tar.zst"
|
||||||
|
else
|
||||||
|
usage err
|
||||||
|
fi
|
||||||
|
|
||||||
|
pacman_conf=
|
||||||
|
root=
|
||||||
|
trap 'rm -rf "$pacman_conf" "$root"' EXIT
|
||||||
|
pacman_conf="$(mktemp -p "$PWD")"
|
||||||
|
cat > "$pacman_conf" << "EOF"
|
||||||
|
[options]
|
||||||
|
Architecture = x86_64
|
||||||
|
CheckSpace
|
||||||
|
SigLevel = Required DatabaseOptional
|
||||||
|
[core]
|
||||||
|
Include = /etc/pacman.d/mirrorlist
|
||||||
|
[extra]
|
||||||
|
Include = /etc/pacman.d/mirrorlist
|
||||||
|
[community]
|
||||||
|
Include = /etc/pacman.d/mirrorlist
|
||||||
|
EOF
|
||||||
|
root="$(mktemp -d -p "$PWD")"
|
||||||
|
|
||||||
|
packages=(
|
||||||
|
busybox
|
||||||
|
# libbpf dependencies.
|
||||||
|
libelf
|
||||||
|
zlib
|
||||||
|
# selftests test_progs dependencies.
|
||||||
|
binutils
|
||||||
|
elfutils
|
||||||
|
glibc
|
||||||
|
# selftests test_verifier dependencies.
|
||||||
|
libcap
|
||||||
|
)
|
||||||
|
|
||||||
|
pacstrap -C "$pacman_conf" -cGM "$root" "${packages[@]}"
|
||||||
|
|
||||||
|
# Remove unnecessary files from the chroot.
|
||||||
|
|
||||||
|
# We don't need the pacman databases anymore.
|
||||||
|
rm -rf "$root/var/lib/pacman/sync/"
|
||||||
|
# We don't need D, Fortran, or Go.
|
||||||
|
rm -f "$root/usr/lib/libgdruntime."* \
|
||||||
|
"$root/usr/lib/libgphobos."* \
|
||||||
|
"$root/usr/lib/libgfortran."* \
|
||||||
|
"$root/usr/lib/libgo."*
|
||||||
|
# We don't need any documentation.
|
||||||
|
rm -rf "$root/usr/share/{doc,help,man,texinfo}"
|
||||||
|
|
||||||
|
chroot "${root}" /bin/busybox --install
|
||||||
|
|
||||||
|
cat > "$root/etc/fstab" << "EOF"
|
||||||
|
dev /dev devtmpfs rw,nosuid 0 0
|
||||||
|
proc /proc proc rw,nosuid,nodev,noexec 0 0
|
||||||
|
sys /sys sysfs rw,nosuid,nodev,noexec 0 0
|
||||||
|
debugfs /sys/kernel/debug debugfs mode=755,realtime 0 0
|
||||||
|
bpffs /sys/fs/bpf bpf realtime 0 0
|
||||||
|
EOF
|
||||||
|
chmod 644 "$root/etc/fstab"
|
||||||
|
|
||||||
|
cat > "$root/etc/inittab" << "EOF"
|
||||||
|
::sysinit:/etc/init.d/rcS
|
||||||
|
::ctrlaltdel:/sbin/reboot
|
||||||
|
::shutdown:/sbin/swapoff -a
|
||||||
|
::shutdown:/bin/umount -a -r
|
||||||
|
::restart:/sbin/init
|
||||||
|
EOF
|
||||||
|
chmod 644 "$root/etc/inittab"
|
||||||
|
|
||||||
|
mkdir -m 755 "$root/etc/init.d" "$root/etc/rcS.d"
|
||||||
|
cat > "$root/etc/rcS.d/S10-mount" << "EOF"
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
/bin/mount -a
|
||||||
|
EOF
|
||||||
|
chmod 755 "$root/etc/rcS.d/S10-mount"
|
||||||
|
|
||||||
|
cat > "$root/etc/rcS.d/S40-network" << "EOF"
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
ip link set lo up
|
||||||
|
EOF
|
||||||
|
chmod 755 "$root/etc/rcS.d/S40-network"
|
||||||
|
|
||||||
|
cat > "$root/etc/init.d/rcS" << "EOF"
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
for path in /etc/rcS.d/S*; do
|
||||||
|
[ -x "$path" ] && "$path"
|
||||||
|
done
|
||||||
|
EOF
|
||||||
|
chmod 755 "$root/etc/init.d/rcS"
|
||||||
|
|
||||||
|
chmod 755 "$root"
|
||||||
|
tar -C "$root" -c . | zstd -T0 -19 -o "$NAME"
|
||||||
|
chmod 644 "$NAME"
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
set -eux
|
set -eux
|
||||||
GIT_FETCH_DEPTH="${GIT_FETCH_DEPTH}" ${VMTEST_ROOT}/checkout_latest_kernel.sh $1
|
|
||||||
|
|
||||||
# Fix runqslower build
|
REPO_PATH=$1
|
||||||
# TODO(hex@): remove after the patch is merged from bpf to bpf-next tree
|
|
||||||
cd $1
|
${VMTEST_ROOT}/checkout_latest_kernel.sh ${REPO_PATH}
|
||||||
wget https://lore.kernel.org/bpf/908498f794661c44dca54da9e09dc0c382df6fcb.1580425879.git.hex@fb.com/t.mbox.gz
|
cd ${REPO_PATH}
|
||||||
gunzip t.mbox.gz
|
|
||||||
git apply t.mbox
|
if [[ "${KERNEL}" = 'LATEST' ]]; then
|
||||||
|
cp ${VMTEST_ROOT}/configs/latest.config .config
|
||||||
|
make -j $((4*$(nproc))) olddefconfig all
|
||||||
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,39 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
set -eux
|
set -euxo pipefail
|
||||||
|
|
||||||
|
test_progs() {
|
||||||
|
echo TEST_PROGS
|
||||||
|
./test_progs ${BLACKLIST:+-b$BLACKLIST} ${WHITELIST:+-t$WHITELIST}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_maps() {
|
||||||
|
echo TEST_MAPS
|
||||||
|
# Allow failing on older kernels.
|
||||||
|
./test_maps
|
||||||
|
}
|
||||||
|
|
||||||
|
test_verifier() {
|
||||||
|
echo TEST_VERIFIER
|
||||||
|
./test_verifier
|
||||||
|
}
|
||||||
|
|
||||||
configs_path='libbpf/travis-ci/vmtest/configs'
|
configs_path='libbpf/travis-ci/vmtest/configs'
|
||||||
blacklist_path="$configs_path/blacklist/BLACKLIST-${KERNEL}"
|
blacklist_path="$configs_path/blacklist/BLACKLIST-${KERNEL}"
|
||||||
if [[ -s "${blacklist_path}" ]]; then
|
if [[ -s "${blacklist_path}" ]]; then
|
||||||
BLACKLIST=$(cat "${blacklist_path}" | tr '\n' ',')
|
BLACKLIST=$(cat "${blacklist_path}" | cut -d'#' -f1 | tr -s '[:space:]' ',')
|
||||||
fi
|
fi
|
||||||
|
|
||||||
whitelist_path="$configs_path/whitelist/WHITELIST-${KERNEL}"
|
whitelist_path="$configs_path/whitelist/WHITELIST-${KERNEL}"
|
||||||
if [[ -s "${whitelist_path}" ]]; then
|
if [[ -s "${whitelist_path}" ]]; then
|
||||||
WHITELIST=$(cat "${whitelist_path}" | tr '\n' ',')
|
WHITELIST=$(cat "${whitelist_path}" | cut -d'#' -f1 | tr -s '[:space:]' ',')
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd libbpf/selftests/bpf
|
cd libbpf/selftests/bpf
|
||||||
|
|
||||||
echo TEST_PROGS
|
test_progs
|
||||||
./test_progs ${BLACKLIST:+-b$BLACKLIST} ${WHITELIST:+-t$WHITELIST}
|
|
||||||
|
if [[ "${KERNEL}" == 'latest' ]]; then
|
||||||
|
test_maps
|
||||||
|
test_verifier
|
||||||
|
fi
|
||||||
|
|||||||
30
travis-ci/vmtest/run_vmtest.sh
Executable file
30
travis-ci/vmtest/run_vmtest.sh
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
VMTEST_SETUPCMD="PROJECT_NAME=${PROJECT_NAME} ./${PROJECT_NAME}/travis-ci/vmtest/run_selftests.sh"
|
||||||
|
|
||||||
|
echo "KERNEL: $KERNEL"
|
||||||
|
|
||||||
|
# Build latest pahole
|
||||||
|
${VMTEST_ROOT}/build_pahole.sh travis-ci/vmtest/pahole
|
||||||
|
|
||||||
|
# Install required packages
|
||||||
|
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||||
|
echo "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main" | sudo tee -a /etc/apt/sources.list
|
||||||
|
sudo apt-get -qq update
|
||||||
|
sudo apt-get -qq -y install clang lld llvm
|
||||||
|
|
||||||
|
# Build selftests (and latest kernel, if necessary)
|
||||||
|
KERNEL="${KERNEL}" ${VMTEST_ROOT}/prepare_selftests.sh travis-ci/vmtest/bpf-next
|
||||||
|
|
||||||
|
# Escape whitespace characters.
|
||||||
|
setup_cmd=$(sed 's/\([[:space:]]\)/\\\1/g' <<< "${VMTEST_SETUPCMD}")
|
||||||
|
|
||||||
|
sudo adduser "${USER}" kvm
|
||||||
|
|
||||||
|
if [[ "${KERNEL}" = 'LATEST' ]]; then
|
||||||
|
sudo -E sudo -E -u "${USER}" "${VMTEST_ROOT}/run.sh" -b travis-ci/vmtest/bpf-next -o -d ~ -s "${setup_cmd}" ~/root.img;
|
||||||
|
else
|
||||||
|
sudo -E sudo -E -u "${USER}" "${VMTEST_ROOT}/run.sh" -k "${KERNEL}*" -o -d ~ -s "${setup_cmd}" ~/root.img;
|
||||||
|
fi
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#!/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