Merge branch 'aya-rs:main' into interface

pull/478/head
Ayrton Sparling 2 years ago committed by GitHub
commit c7a997b48e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -7,4 +7,7 @@ build-bpfeb = "build -Zbuild-std=core --target=bpfeb-unknown-none"
linker = "arm-linux-gnueabi-gcc"
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
linker = "arm-linux-gnueabihf-gcc"
[target.aarch64-unknown-linux-musl]
linker = "aarch64-linux-musl-gcc"

@ -14,7 +14,7 @@ env:
CARGO_TERM_COLOR: always
jobs:
build:
build-test:
strategy:
matrix:
arch:
@ -43,38 +43,3 @@ jobs:
RUST_BACKTRACE: full
run: |
cross test --verbose --target ${{matrix.arch}}
test:
runs-on: ubuntu-20.04
needs: build
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v2
with:
repository: libbpf/libbpf
path: libbpf
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly
components: rustfmt, clippy, rust-src
target: x86_64-unknown-linux-musl
override: true
- uses: Swatinem/rust-cache@v1
- name: Install Pre-requisites
run: |
sudo apt-get update
sudo apt-get -qy install linux-tools-common qemu-system-x86 cloud-image-utils openssh-client libelf-dev gcc-multilib
cargo install bpf-linker
- name: Lint integration tests
run: |
cargo xtask build-integration-test-ebpf --libbpf-dir ./libbpf
cargo clippy -p integration-test -- --deny warnings
- name: Run integration tests
run: |
(cd test && ./run.sh ../libbpf)

@ -0,0 +1,43 @@
name: integration-tests
on:
push:
branches:
- main
pull_request:
branches:
- main
env:
CARGO_TERM_COLOR: always
jobs:
test:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v2
with:
repository: libbpf/libbpf
path: libbpf
- name: Install Pre-requisites
run: |
brew install qemu gnu-getopt coreutils cdrtools
- name: Cache tmp files
uses: actions/cache@v3
with:
path: |
.tmp/*.qcow2
.tmp/test_rsa
.tmp/test_rsa.pub
# FIXME: we should invalidate the cache on new bpf-linker releases.
# For now we must manually delete the cache when we release a new
# bpf-linker version.
key: tmp-files-${{ hashFiles('test/run.sh') }}
- name: Run integration tests
run: test/run.sh ./libbpf

@ -1,12 +1,12 @@
[workspace]
members = [
"aya", "aya-tool", "aya-log", "aya-log-common", "aya-log-parser", "test/integration-test", "test/integration-test-macros", "xtask",
"aya", "aya-obj", "aya-tool", "aya-log", "aya-log-common", "aya-log-parser", "test/integration-test", "test/integration-test-macros", "xtask",
# macros
"aya-bpf-macros", "aya-log-ebpf-macros",
# ebpf crates
"bpf/aya-bpf", "bpf/aya-bpf-bindings", "bpf/aya-log-ebpf", "test/integration-ebpf"
]
default-members = ["aya", "aya-tool", "aya-log", "aya-bpf-macros", "aya-log-ebpf-macros"]
default-members = ["aya", "aya-obj", "aya-tool", "aya-log", "aya-bpf-macros", "aya-log-ebpf-macros"]
[profile.dev]
panic = "abort"

@ -119,12 +119,13 @@ impl Probe {
pub fn expand(&self) -> Result<TokenStream> {
let section_name = format!("{}/{}", self.kind, self.name);
let fn_vis = &self.item.vis;
let fn_name = &self.item.sig.ident;
let item = &self.item;
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 {
#fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 {
let _ = #fn_name(::aya_bpf::programs::ProbeContext::new(ctx));
return 0;
@ -152,12 +153,13 @@ impl SockOps {
} else {
"sockops".to_owned()
};
let fn_vis = &self.item.vis;
let fn_name = &self.item.sig.ident;
let item = &self.item;
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_sock_ops) -> u32 {
#fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_sock_ops) -> u32 {
return #fn_name(::aya_bpf::programs::SockOpsContext::new(ctx));
#item
@ -180,12 +182,13 @@ impl SkMsg {
pub fn expand(&self) -> Result<TokenStream> {
let section_name = format!("sk_msg/{}", self.name);
let fn_vis = &self.item.vis;
let fn_name = &self.item.sig.ident;
let item = &self.item;
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::aya_bpf::bindings::sk_msg_md) -> u32 {
#fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::sk_msg_md) -> u32 {
return #fn_name(::aya_bpf::programs::SkMsgContext::new(ctx));
#item
@ -212,12 +215,13 @@ impl Xdp {
} else {
"xdp".to_owned()
};
let fn_vis = &self.item.vis;
let fn_name = &self.item.sig.ident;
let item = &self.item;
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::aya_bpf::bindings::xdp_md) -> u32 {
#fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::xdp_md) -> u32 {
return #fn_name(::aya_bpf::programs::XdpContext::new(ctx));
#item
@ -244,12 +248,13 @@ impl SchedClassifier {
} else {
"classifier".to_owned()
};
let fn_vis = &self.item.vis;
let fn_name = &self.item.sig.ident;
let item = &self.item;
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::aya_bpf::bindings::__sk_buff) -> i32 {
#fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::__sk_buff) -> i32 {
return #fn_name(::aya_bpf::programs::TcContext::new(ctx));
#item
@ -276,12 +281,13 @@ impl CgroupSysctl {
} else {
("cgroup/sysctl").to_owned()
};
let fn_vis = &self.item.vis;
let fn_name = &self.item.sig.ident;
let item = &self.item;
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_sysctl) -> i32 {
#fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_sysctl) -> i32 {
return #fn_name(::aya_bpf::programs::SysctlContext::new(ctx));
#item
@ -313,12 +319,13 @@ impl CgroupSockopt {
} else {
format!("cgroup/{}", self.attach_type)
};
let fn_vis = &self.item.vis;
let fn_name = &self.item.sig.ident;
let item = &self.item;
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_sockopt) -> i32 {
#fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_sockopt) -> i32 {
return #fn_name(::aya_bpf::programs::SockoptContext::new(ctx));
#item
@ -358,12 +365,13 @@ impl CgroupSkb {
} else {
("cgroup/skb").to_owned()
};
let fn_vis = &self.item.vis;
let fn_name = &self.item.sig.ident;
let item = &self.item;
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::aya_bpf::bindings::__sk_buff) -> i32 {
#fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::__sk_buff) -> i32 {
return #fn_name(::aya_bpf::programs::SkBuffContext::new(ctx));
#item
@ -396,12 +404,13 @@ impl CgroupSockAddr {
} else {
format!("cgroup/{}", self.attach_type)
};
let fn_vis = &self.item.vis;
let fn_name = &self.item.sig.ident;
let item = &self.item;
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_sock_addr) -> i32 {
#fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_sock_addr) -> i32 {
return #fn_name(::aya_bpf::programs::SockAddrContext::new(ctx));
#item
@ -441,12 +450,13 @@ impl CgroupSock {
} else {
"cgroup/sock".to_string()
};
let fn_vis = &self.item.vis;
let fn_name = &self.item.sig.ident;
let item = &self.item;
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_sock) -> i32 {
#fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_sock) -> i32 {
return #fn_name(::aya_bpf::programs::SockContext::new(ctx));
#item
@ -512,12 +522,13 @@ impl TracePoint {
pub fn expand(&self) -> Result<TokenStream> {
let section_name = format!("tp/{}", self.name);
let fn_vis = &self.item.vis;
let fn_name = &self.item.sig.ident;
let item = &self.item;
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 {
#fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 {
let _ = #fn_name(::aya_bpf::programs::TracePointContext::new(ctx));
return 0;
@ -541,12 +552,13 @@ impl PerfEvent {
pub fn expand(&self) -> Result<TokenStream> {
let section_name = format!("perf_event/{}", self.name);
let fn_vis = &self.item.vis;
let fn_name = &self.item.sig.ident;
let item = &self.item;
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 {
#fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 {
let _ = #fn_name(::aya_bpf::programs::PerfEventContext::new(ctx));
return 0;
@ -570,12 +582,13 @@ impl RawTracePoint {
pub fn expand(&self) -> Result<TokenStream> {
let section_name = format!("raw_tp/{}", self.name);
let fn_vis = &self.item.vis;
let fn_name = &self.item.sig.ident;
let item = &self.item;
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 {
#fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 {
let _ = #fn_name(::aya_bpf::programs::RawTracePointContext::new(ctx));
return 0;
@ -599,6 +612,7 @@ impl Lsm {
pub fn expand(&self) -> Result<TokenStream> {
let section_name = format!("lsm/{}", self.name);
let fn_vis = &self.item.vis;
let fn_name = &self.item.sig.ident;
let item = &self.item;
// LSM probes need to return an integer corresponding to the correct
@ -607,7 +621,7 @@ impl Lsm {
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 {
#fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 {
return #fn_name(::aya_bpf::programs::LsmContext::new(ctx));
#item
@ -630,12 +644,13 @@ impl BtfTracePoint {
pub fn expand(&self) -> Result<TokenStream> {
let section_name = format!("tp_btf/{}", self.name);
let fn_vis = &self.item.vis;
let fn_name = &self.item.sig.ident;
let item = &self.item;
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 {
#fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 {
let _ = #fn_name(::aya_bpf::programs::BtfTracePointContext::new(ctx));
return 0;
@ -683,12 +698,13 @@ impl SkSkb {
} else {
format!("sk_skb/{kind}")
};
let fn_vis = &self.item.vis;
let fn_name = &self.item.sig.ident;
let item = &self.item;
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::aya_bpf::bindings::__sk_buff) -> u32 {
#fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::__sk_buff) -> u32 {
return #fn_name(::aya_bpf::programs::SkBuffContext::new(ctx));
#item
@ -716,12 +732,13 @@ impl SocketFilter {
} else {
"socket".to_owned()
};
let fn_vis = &self.item.vis;
let fn_name = &self.item.sig.ident;
let item = &self.item;
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::aya_bpf::bindings::__sk_buff) -> i64 {
#fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::__sk_buff) -> i64 {
return #fn_name(::aya_bpf::programs::SkBuffContext::new(ctx));
#item
@ -744,12 +761,13 @@ impl FEntry {
pub fn expand(&self) -> Result<TokenStream> {
let section_name = format!("fentry/{}", self.name);
let fn_vis = &self.item.vis;
let fn_name = &self.item.sig.ident;
let item = &self.item;
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 {
#fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 {
let _ = #fn_name(::aya_bpf::programs::FEntryContext::new(ctx));
return 0;
@ -773,12 +791,13 @@ impl FExit {
pub fn expand(&self) -> Result<TokenStream> {
let section_name = format!("fexit/{}", self.name);
let fn_vis = &self.item.vis;
let fn_name = &self.item.sig.ident;
let item = &self.item;
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 {
#fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 {
let _ = #fn_name(::aya_bpf::programs::FExitContext::new(ctx));
return 0;
@ -806,12 +825,13 @@ impl SkLookup {
} else {
"sk_lookup".to_owned()
};
let fn_vis = &self.item.vis;
let fn_name = &self.item.sig.ident;
let item = &self.item;
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_sk_lookup) -> u32 {
#fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_sk_lookup) -> u32 {
return #fn_name(::aya_bpf::programs::SkLookupContext::new(ctx));
#item
@ -838,12 +858,13 @@ impl CgroupDevice {
} else {
("cgroup/dev").to_owned()
};
let fn_vis = &self.item.vis;
let fn_name = &self.item.sig.ident;
let item = &self.item;
Ok(quote! {
#[no_mangle]
#[link_section = #section_name]
fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_cgroup_dev_ctx) -> i32 {
#fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_cgroup_dev_ctx) -> i32 {
return #fn_name(::aya_bpf::programs::DeviceContext::new(ctx));
#item
@ -941,4 +962,49 @@ mod tests {
.to_string()
.contains("[link_section = \"cgroup/dev\"]"));
}
#[test]
fn priv_function() {
let prog = CgroupSkb::from_syn(
parse_quote!(attach = "egress"),
parse_quote!(
fn foo(ctx: SkBuffContext) -> i32 {
0
}
),
)
.unwrap();
let stream = prog.expand().unwrap();
assert!(stream.to_string().contains("] fn foo ("));
}
#[test]
fn pub_function() {
let prog = CgroupSkb::from_syn(
parse_quote!(attach = "egress"),
parse_quote!(
pub fn foo(ctx: SkBuffContext) -> i32 {
0
}
),
)
.unwrap();
let stream = prog.expand().unwrap();
assert!(stream.to_string().contains("] pub fn foo ("));
}
#[test]
fn pub_crate_function() {
let prog = CgroupSkb::from_syn(
parse_quote!(attach = "egress"),
parse_quote!(
pub(crate) fn foo(ctx: SkBuffContext) -> i32 {
0
}
),
)
.unwrap();
let stream = prog.expand().unwrap();
assert!(stream.to_string().contains("] pub (crate) fn foo ("));
}
}

@ -16,7 +16,7 @@ aya-log-common = { path = "../aya-log-common", version = "0.1.13", features=["us
thiserror = "1"
log = "0.4"
bytes = "1.1"
tokio = { version = "1.2.0" }
tokio = { version = "1.24" }
[dev-dependencies]
env_logger = "0.10"

@ -0,0 +1,27 @@
[package]
name = "aya-obj"
version = "0.1.0"
description = "An eBPF object file parsing library with BTF and relocation support."
keywords = ["ebpf", "bpf", "btf", "elf", "object"]
license = "MIT OR Apache-2.0"
authors = ["The Aya Contributors"]
repository = "https://github.com/aya-rs/aya"
readme = "README.md"
documentation = "https://docs.rs/aya-obj"
edition = "2021"
[dependencies]
bytes = "1"
log = "0.4"
object = { version = "0.30", default-features = false, features = ["read_core", "elf"] }
hashbrown = { version = "0.13", optional = true }
thiserror-std = { package = "thiserror", version = "1" }
thiserror-core = { version = "1", default-features = false, features = [], optional = true }
[dev-dependencies]
matches = "0.1.8"
rbpf = "0.1.0"
[features]
default = []
no_std = ["hashbrown", "thiserror-core"]

@ -0,0 +1,55 @@
# aya-obj
## Status
This crate includes code that started as internal API used by
the [aya] crate. It has been split out so that it can be used by
other projects that deal with eBPF object files. Unless you're writing
low level eBPF plumbing tools, you should not need to use this crate
but see the [aya] crate instead.
The API as it is today has a few rough edges and is generally not as
polished nor stable as the main [aya] crate API. As always,
improvements welcome!
[aya]: https://github.com/aya-rs/aya
## Overview
eBPF programs written with [libbpf] or [aya-bpf] are usually compiled
into an ELF object file, using various sections to store information
about the eBPF programs.
`aya-obj` is a library for parsing such eBPF object files, with BTF and
relocation support.
[libbpf]: https://github.com/libbpf/libbpf
[aya-bpf]: https://github.com/aya-rs/aya
## Example
This example loads a simple eBPF program and runs it with [rbpf].
```rust
use aya_obj::{generated::bpf_insn, Object};
// Parse the object file
let bytes = std::fs::read("program.o").unwrap();
let mut object = Object::parse(&bytes).unwrap();
// Relocate the programs
object.relocate_calls().unwrap();
object.relocate_maps(std::iter::empty()).unwrap();
// Run with rbpf
let instructions = &object.programs["prog_name"].function.instructions;
let data = unsafe {
core::slice::from_raw_parts(
instructions.as_ptr() as *const u8,
instructions.len() * core::mem::size_of::<bpf_insn>(),
)
};
let vm = rbpf::EbpfVmNoData::new(Some(data)).unwrap();
let _return = vm.execute_program().unwrap();
```
[rbpf]: https://github.com/qmonnet/rbpf

@ -1,29 +1,29 @@
use std::{
use core::{ffi::CStr, mem, ptr};
use alloc::{
borrow::Cow,
collections::HashMap,
convert::TryInto,
ffi::{CStr, CString},
fs, io, mem,
path::{Path, PathBuf},
ptr,
ffi::CString,
format,
string::{String, ToString},
vec,
vec::Vec,
};
use bytes::BufMut;
use log::debug;
use object::Endianness;
use thiserror::Error;
use crate::{
generated::{btf_ext_header, btf_header},
obj::btf::{
btf::{
info::{FuncSecInfo, LineSecInfo},
relocation::Relocation,
Array, BtfEnum, BtfKind, BtfMember, BtfType, Const, Enum, FuncInfo, FuncLinkage, Int,
IntEncoding, LineInfo, Struct, Typedef, VarLinkage,
},
util::bytes_of,
Features,
generated::{btf_ext_header, btf_header},
thiserror::{self, Error},
util::{bytes_of, HashMap},
Object,
};
pub(crate) const MAX_RESOLVE_DEPTH: u8 = 32;
@ -32,14 +32,15 @@ pub(crate) const MAX_SPEC_LEN: usize = 64;
/// The error type returned when `BTF` operations fail.
#[derive(Error, Debug)]
pub enum BtfError {
#[cfg(not(feature = "no_std"))]
/// Error parsing file
#[error("error parsing {path}")]
FileError {
/// file path
path: PathBuf,
path: std::path::PathBuf,
/// source of the error
#[source]
error: io::Error,
error: std::io::Error,
},
/// Error parsing BTF header
@ -125,12 +126,13 @@ pub enum BtfError {
type_id: u32,
},
#[cfg(not(feature = "no_std"))]
/// Loading the btf failed
#[error("the BPF_BTF_LOAD syscall failed. Verifier output: {verifier_log}")]
LoadError {
/// The [`io::Error`] returned by the `BPF_BTF_LOAD` syscall.
/// The [`std::io::Error`] returned by the `BPF_BTF_LOAD` syscall.
#[source]
io_error: io::Error,
io_error: std::io::Error,
/// The error log produced by the kernel verifier.
verifier_log: String,
},
@ -158,14 +160,26 @@ pub enum BtfError {
InvalidSymbolName,
}
/// Available BTF features
#[derive(Default, Debug)]
#[allow(missing_docs)]
pub struct BtfFeatures {
pub btf_func: bool,
pub btf_func_global: bool,
pub btf_datasec: bool,
pub btf_float: bool,
pub btf_decl_tag: bool,
pub btf_type_tag: bool,
}
/// Bpf Type Format metadata.
///
/// BTF is a kind of debug metadata that allows eBPF programs compiled against one kernel version
/// to be loaded into different kernel versions.
///
/// Aya automatically loads BTF metadata if you use [`Bpf::load_file`](crate::Bpf::load_file). You
/// Aya automatically loads BTF metadata if you use `Bpf::load_file`. You
/// only need to explicitly use this type if you want to load BTF from a non-standard
/// location or if you are using [`Bpf::load`](crate::Bpf::load).
/// location or if you are using `Bpf::load`.
#[derive(Clone, Debug)]
pub struct Btf {
header: btf_header,
@ -175,7 +189,8 @@ pub struct Btf {
}
impl Btf {
pub(crate) fn new() -> Btf {
/// Creates a new empty instance with its header initialized
pub fn new() -> Btf {
Btf {
header: btf_header {
magic: 0xeb9f,
@ -197,7 +212,8 @@ impl Btf {
self.types.types.iter()
}
pub(crate) fn add_string(&mut self, name: String) -> u32 {
/// Adds a string to BTF metadata, returning an offset
pub fn add_string(&mut self, name: String) -> u32 {
let str = CString::new(name).unwrap();
let name_offset = self.strings.len();
self.strings.extend(str.as_c_str().to_bytes_with_nul());
@ -205,7 +221,8 @@ impl Btf {
name_offset as u32
}
pub(crate) fn add_type(&mut self, btf_type: BtfType) -> u32 {
/// Adds a type to BTF metadata, returning a type id
pub fn add_type(&mut self, btf_type: BtfType) -> u32 {
let size = btf_type.type_info_size() as u32;
let type_id = self.types.len();
self.types.push(btf_type);
@ -215,12 +232,18 @@ impl Btf {
}
/// Loads BTF metadata from `/sys/kernel/btf/vmlinux`.
#[cfg(not(feature = "no_std"))]
pub fn from_sys_fs() -> Result<Btf, BtfError> {
Btf::parse_file("/sys/kernel/btf/vmlinux", Endianness::default())
}
/// Loads BTF metadata from the given `path`.
pub fn parse_file<P: AsRef<Path>>(path: P, endianness: Endianness) -> Result<Btf, BtfError> {
#[cfg(not(feature = "no_std"))]
pub fn parse_file<P: AsRef<std::path::Path>>(
path: P,
endianness: Endianness,
) -> Result<Btf, BtfError> {
use std::{borrow::ToOwned, fs};
let path = path.as_ref();
Btf::parse(
&fs::read(path).map_err(|error| BtfError::FileError {
@ -231,7 +254,8 @@ impl Btf {
)
}
pub(crate) fn parse(data: &[u8], endianness: Endianness) -> Result<Btf, BtfError> {
/// Parses BTF from binary data of the given endianness
pub fn parse(data: &[u8], endianness: Endianness) -> Result<Btf, BtfError> {
if data.len() < mem::size_of::<btf_header>() {
return Err(BtfError::InvalidHeader);
}
@ -324,7 +348,8 @@ impl Btf {
self.string_at(ty.name_offset()).ok().map(String::from)
}
pub(crate) fn id_by_type_name_kind(&self, name: &str, kind: BtfKind) -> Result<u32, BtfError> {
/// Returns a type id matching the type name and [BtfKind]
pub fn id_by_type_name_kind(&self, name: &str, kind: BtfKind) -> Result<u32, BtfError> {
for (type_id, ty) in self.types().enumerate() {
if ty.kind() != kind {
continue;
@ -370,7 +395,8 @@ impl Btf {
})
}
pub(crate) fn to_bytes(&self) -> Vec<u8> {
/// Encodes the metadata as BTF format
pub fn to_bytes(&self) -> Vec<u8> {
// Safety: btf_header is POD
let mut buf = unsafe { bytes_of::<btf_header>(&self.header).to_vec() };
// Skip the first type since it's always BtfType::Unknown for type_by_id to work
@ -383,7 +409,7 @@ impl Btf {
&mut self,
section_sizes: &HashMap<String, u64>,
symbol_offsets: &HashMap<String, u64>,
features: &Features,
features: &BtfFeatures,
) -> Result<(), BtfError> {
let mut types = mem::take(&mut self.types);
for i in 0..types.types.len() {
@ -503,7 +529,7 @@ impl Btf {
.iter()
.map(|p| BtfEnum {
name_offset: p.name_offset,
value: p.btf_type as i32,
value: p.btf_type,
})
.collect();
let enum_type = BtfType::Enum(Enum::new(ty.name_offset, members));
@ -560,11 +586,34 @@ impl Default for Btf {
}
}
impl Object {
/// Fixes up and sanitizes BTF data.
///
/// Mostly, it removes unsupported types and works around LLVM behaviours.
pub fn fixup_and_sanitize_btf(
&mut self,
features: &BtfFeatures,
) -> Result<Option<&Btf>, BtfError> {
if let Some(ref mut obj_btf) = self.btf {
// fixup btf
obj_btf.fixup_and_sanitize(
&self.section_sizes,
&self.symbol_offset_by_name,
features,
)?;
Ok(Some(obj_btf))
} else {
Ok(None)
}
}
}
unsafe fn read_btf_header(data: &[u8]) -> btf_header {
// safety: btf_header is POD so read_unaligned is safe
ptr::read_unaligned(data.as_ptr() as *const btf_header)
}
/// Data in the `.BTF.ext` section
#[derive(Debug, Clone)]
pub struct BtfExt {
data: Vec<u8>,
@ -863,7 +912,7 @@ pub(crate) struct SecInfo<'a> {
#[cfg(test)]
mod tests {
use crate::obj::btf::{
use crate::btf::{
BtfParam, DataSec, DataSecEntry, DeclTag, Float, Func, FuncProto, Ptr, TypeTag, Var,
};
@ -996,7 +1045,7 @@ mod tests {
let name_offset = btf.add_string("&mut int".to_string());
let ptr_type_id = btf.add_type(BtfType::Ptr(Ptr::new(name_offset, int_type_id)));
let features = Features {
let features = BtfFeatures {
..Default::default()
};
@ -1034,7 +1083,7 @@ mod tests {
VarLinkage::Static,
)));
let features = Features {
let features = BtfFeatures {
btf_datasec: false,
..Default::default()
};
@ -1078,7 +1127,7 @@ mod tests {
let datasec_type_id =
btf.add_type(BtfType::DataSec(DataSec::new(name_offset, variables, 0)));
let features = Features {
let features = BtfFeatures {
btf_datasec: false,
..Default::default()
};
@ -1125,7 +1174,7 @@ mod tests {
let datasec_type_id =
btf.add_type(BtfType::DataSec(DataSec::new(name_offset, variables, 0)));
let features = Features {
let features = BtfFeatures {
btf_datasec: true,
..Default::default()
};
@ -1186,7 +1235,7 @@ mod tests {
FuncLinkage::Static,
)));
let features = Features {
let features = BtfFeatures {
btf_func: false,
..Default::default()
};
@ -1197,9 +1246,9 @@ mod tests {
assert!(fixed.name_offset == 0);
assert!(fixed.variants.len() == 2);
assert!(btf.string_at(fixed.variants[0].name_offset).unwrap() == "a");
assert!(fixed.variants[0].value == int_type_id as i32);
assert!(fixed.variants[0].value == int_type_id);
assert!(btf.string_at(fixed.variants[1].name_offset).unwrap() == "b");
assert!(fixed.variants[1].value == int_type_id as i32);
assert!(fixed.variants[1].value == int_type_id);
} else {
panic!("not an emum")
}
@ -1235,7 +1284,7 @@ mod tests {
let func_proto = BtfType::FuncProto(FuncProto::new(params, int_type_id));
let func_proto_type_id = btf.add_type(func_proto);
let features = Features {
let features = BtfFeatures {
btf_func: true,
..Default::default()
};
@ -1284,7 +1333,7 @@ mod tests {
FuncLinkage::Global,
)));
let features = Features {
let features = BtfFeatures {
btf_func: true,
btf_func_global: false,
..Default::default()
@ -1309,7 +1358,7 @@ mod tests {
let name_offset = btf.add_string("float".to_string());
let float_type_id = btf.add_type(BtfType::Float(Float::new(name_offset, 16)));
let features = Features {
let features = BtfFeatures {
btf_float: false,
..Default::default()
};
@ -1349,7 +1398,7 @@ mod tests {
let decl_tag_type_id =
btf.add_type(BtfType::DeclTag(DeclTag::new(name_offset, var_type_id, -1)));
let features = Features {
let features = BtfFeatures {
btf_decl_tag: false,
..Default::default()
};
@ -1377,7 +1426,7 @@ mod tests {
let type_tag_type = btf.add_type(BtfType::TypeTag(TypeTag::new(name_offset, int_type_id)));
btf.add_type(BtfType::Ptr(Ptr::new(0, type_tag_type)));
let features = Features {
let features = BtfFeatures {
btf_type_tag: false,
..Default::default()
};
@ -1395,6 +1444,7 @@ mod tests {
}
#[test]
#[cfg(not(feature = "no_std"))]
#[cfg_attr(miri, ignore)]
fn test_read_btf_from_sys_fs() {
let btf = Btf::parse_file("/sys/kernel/btf/vmlinux", Endianness::default()).unwrap();

@ -1,12 +1,11 @@
use std::collections::HashMap;
use alloc::{string::String, vec, vec::Vec};
use bytes::BufMut;
use object::Endianness;
use crate::{
generated::{bpf_func_info, bpf_line_info},
obj::relocation::INS_SIZE,
util::bytes_of,
relocation::INS_SIZE,
util::{bytes_of, HashMap},
};
/* The func_info subsection layout:
@ -19,10 +18,18 @@ use crate::{
* a list of bpf_func_info records for section #2
* ......
*/
/// A collection of [bpf_func_info] collected from the `btf_ext_info_sec` struct
/// inside the [FuncInfo] subsection.
///
/// See [BPF Type Format (BTF) — The Linux Kernel documentation](https://docs.kernel.org/bpf/btf.html)
/// for more information.
#[derive(Debug, Clone, Default)]
pub(crate) struct FuncSecInfo {
pub _sec_name_offset: u32,
pub struct FuncSecInfo {
pub(crate) _sec_name_offset: u32,
/// The number of info entries
pub num_info: u32,
/// Info entries
pub func_info: Vec<bpf_func_info>,
}
@ -64,7 +71,8 @@ impl FuncSecInfo {
}
}
pub(crate) fn func_info_bytes(&self) -> Vec<u8> {
/// Encodes the [bpf_func_info] entries.
pub fn func_info_bytes(&self) -> Vec<u8> {
let mut buf = vec![];
for l in &self.func_info {
// Safety: bpf_func_info is POD
@ -73,13 +81,20 @@ impl FuncSecInfo {
buf
}
pub(crate) fn len(&self) -> usize {
/// Returns the number of [bpf_func_info] entries.
pub fn len(&self) -> usize {
self.func_info.len()
}
}
/// A collection of [FuncSecInfo] collected from the `func_info` subsection
/// in the `.BTF.ext` section.
///
/// See [BPF Type Format (BTF) — The Linux Kernel documentation](https://docs.kernel.org/bpf/btf.html)
/// for more information.
#[derive(Debug, Clone)]
pub(crate) struct FuncInfo {
pub struct FuncInfo {
/// The [FuncSecInfo] subsections for some sections, referenced by section names
pub data: HashMap<String, FuncSecInfo>,
}
@ -98,12 +113,19 @@ impl FuncInfo {
}
}
/// A collection of [bpf_line_info] collected from the `btf_ext_info_sec` struct
/// inside the `line_info` subsection.
///
/// See [BPF Type Format (BTF) — The Linux Kernel documentation](https://docs.kernel.org/bpf/btf.html)
/// for more information.
#[derive(Debug, Clone, Default)]
pub(crate) struct LineSecInfo {
pub struct LineSecInfo {
// each line info section has a header
pub _sec_name_offset: u32,
pub(crate) _sec_name_offset: u32,
/// The number of entries
pub num_info: u32,
// followed by one or more bpf_line_info structs
/// The [bpf_line_info] entries
pub line_info: Vec<bpf_line_info>,
}
@ -154,7 +176,8 @@ impl LineSecInfo {
}
}
pub(crate) fn line_info_bytes(&self) -> Vec<u8> {
/// Encodes the entries.
pub fn line_info_bytes(&self) -> Vec<u8> {
let mut buf = vec![];
for l in &self.line_info {
// Safety: bpf_func_info is POD
@ -163,7 +186,8 @@ impl LineSecInfo {
buf
}
pub(crate) fn len(&self) -> usize {
/// Returns the number of entries.
pub fn len(&self) -> usize {
self.line_info.len()
}
}

@ -0,0 +1,12 @@
//! BTF loading, parsing and relocation.
#[allow(clippy::module_inception)]
mod btf;
mod info;
mod relocation;
mod types;
pub use btf::*;
pub use info::*;
pub use relocation::BtfRelocationError;
pub use types::*;

@ -1,76 +1,137 @@
use std::{collections::HashMap, io, mem, ptr, str::FromStr};
use thiserror::Error;
use core::{mem, ptr, str::FromStr};
use alloc::{
borrow::ToOwned,
format,
string::{String, ToString},
vec,
vec::Vec,
};
use crate::{
btf::{
fields_are_compatible, types_are_compatible, Array, Btf, BtfError, BtfMember, BtfType,
IntEncoding, Struct, Union, MAX_SPEC_LEN,
},
generated::{
bpf_core_relo, bpf_core_relo_kind::*, bpf_insn, BPF_ALU, BPF_ALU64, BPF_B, BPF_DW, BPF_H,
BPF_K, BPF_LD, BPF_LDX, BPF_ST, BPF_STX, BPF_W, BTF_INT_SIGNED,
},
obj::{
btf::{
fields_are_compatible, types_are_compatible, Array, BtfMember, BtfType, IntEncoding,
Struct, Union, MAX_SPEC_LEN,
},
Btf, BtfError, Object, Program, ProgramSection,
},
BpfError,
thiserror::{self, Error},
util::HashMap,
Object, Program, ProgramSection,
};
/// The error type returned by [`Object::relocate_btf`].
#[derive(Error, Debug)]
#[error("error relocating `{section}`")]
pub struct BtfRelocationError {
/// The function name
pub section: String,
#[source]
/// The original error
error: RelocationError,
}
/// Relocation failures
#[derive(Error, Debug)]
pub enum RelocationError {
enum RelocationError {
#[cfg(not(feature = "no_std"))]
/// I/O error
#[error(transparent)]
IOError(#[from] io::Error),
IOError(#[from] std::io::Error),
/// Program not found
#[error("program not found")]
ProgramNotFound,
/// Invalid relocation access string
#[error("invalid relocation access string {access_str}")]
InvalidAccessString { access_str: String },
InvalidAccessString {
/// The access string
access_str: String,
},
/// Invalid instruction index referenced by relocation
#[error("invalid instruction index #{index} referenced by relocation #{relocation_number}, the program contains {num_instructions} instructions")]
InvalidInstructionIndex {
/// The invalid instruction index
index: usize,
/// Number of instructions in the program
num_instructions: usize,
/// The relocation number
relocation_number: usize,
},
/// Multiple candidate target types found with different memory layouts
#[error("error relocating {type_name}, multiple candidate target types found with different memory layouts: {candidates:?}")]
ConflictingCandidates {
/// The type name
type_name: String,
/// The candidates
candidates: Vec<String>,
},
/// Maximum nesting level reached evaluating candidate type
#[error("maximum nesting level reached evaluating candidate type `{}`", err_type_name(.type_name))]
MaximumNestingLevelReached { type_name: Option<String> },
MaximumNestingLevelReached {
/// The type name
type_name: Option<String>,
},
/// Invalid access string
#[error("invalid access string `{spec}` for type `{}`: {error}", err_type_name(.type_name))]
InvalidAccessIndex {
/// The type name
type_name: Option<String>,
/// The access string
spec: String,
/// The index
index: usize,
/// The max index
max_index: usize,
/// The error message
error: String,
},
/// Relocation not valid for type
#[error(
"relocation #{relocation_number} of kind `{relocation_kind}` not valid for type `{type_kind}`: {error}"
)]
InvalidRelocationKindForType {
/// The relocation number
relocation_number: usize,
/// The relocation kind
relocation_kind: String,
/// The type kind
type_kind: String,
/// The error message
error: String,
},
/// Invalid instruction referenced by relocation
#[error(
"instruction #{index} referenced by relocation #{relocation_number} is invalid: {error}"
)]
InvalidInstruction {
/// The relocation number
relocation_number: usize,
/// The instruction index
index: usize,
/// The error message
error: String,
},
#[error("applying relocation `{kind:?}` missing target BTF info for type `{type_id}` at instruction #{ins_index}")]
MissingTargetDefinition {
kind: RelocationKind,
type_id: u32,
ins_index: usize,
},
/// BTF error
#[error("invalid BTF")]
BtfError(#[from] BtfError),
}
fn err_type_name(name: &Option<String>) -> String {
@ -119,7 +180,7 @@ impl TryFrom<u32> for RelocationKind {
}
#[derive(Debug, Copy, Clone)]
pub struct Relocation {
pub(crate) struct Relocation {
kind: RelocationKind,
ins_offset: usize,
type_id: u32,
@ -147,7 +208,8 @@ impl Relocation {
}
impl Object {
pub fn relocate_btf(&mut self, target_btf: &Btf) -> Result<(), BpfError> {
/// Relocates programs inside this object file with loaded BTF info.
pub fn relocate_btf(&mut self, target_btf: &Btf) -> Result<(), BtfRelocationError> {
let (local_btf, btf_ext) = match (&self.btf, &self.btf_ext) {
(Some(btf), Some(btf_ext)) => (btf, btf_ext),
_ => return Ok(()),
@ -155,7 +217,13 @@ impl Object {
let mut candidates_cache = HashMap::<u32, Vec<Candidate>>::new();
for (sec_name_off, relos) in btf_ext.relocations() {
let section_name = local_btf.string_at(*sec_name_off)?;
let section_name =
local_btf
.string_at(*sec_name_off)
.map_err(|e| BtfRelocationError {
section: format!("section@{sec_name_off}"),
error: RelocationError::BtfError(e),
})?;
let program_section = match ProgramSection::from_str(&section_name) {
Ok(program) => program,
@ -166,18 +234,17 @@ impl Object {
let program = self
.programs
.get_mut(section_name)
.ok_or(BpfError::RelocationError {
function: section_name.to_owned(),
error: Box::new(RelocationError::ProgramNotFound),
.ok_or(BtfRelocationError {
section: section_name.to_owned(),
error: RelocationError::ProgramNotFound,
})?;
match relocate_btf_program(program, relos, local_btf, target_btf, &mut candidates_cache)
{
Ok(_) => {}
Err(ErrorWrapper::BtfError(e)) => return Err(e.into()),
Err(ErrorWrapper::RelocationError(error)) => {
return Err(BpfError::RelocationError {
function: section_name.to_owned(),
error: Box::new(error),
Err(error) => {
return Err(BtfRelocationError {
section: section_name.to_owned(),
error,
})
}
}
@ -193,17 +260,16 @@ fn relocate_btf_program<'target>(
local_btf: &Btf,
target_btf: &'target Btf,
candidates_cache: &mut HashMap<u32, Vec<Candidate<'target>>>,
) -> Result<(), ErrorWrapper> {
) -> Result<(), RelocationError> {
for rel in relos {
let instructions = &mut program.function.instructions;
let ins_index = rel.ins_offset / std::mem::size_of::<bpf_insn>();
let ins_index = rel.ins_offset / mem::size_of::<bpf_insn>();
if ins_index >= instructions.len() {
return Err(RelocationError::InvalidInstructionIndex {
index: ins_index,
num_instructions: instructions.len(),
relocation_number: rel.number,
}
.into());
});
}
let local_ty = local_btf.type_by_id(rel.type_id)?;
@ -259,14 +325,13 @@ fn relocate_btf_program<'target>(
return Err(RelocationError::ConflictingCandidates {
type_name: local_name.to_string(),
candidates: conflicts,
}
.into());
});
}
target_comp_rel
} else {
// there are no candidate matches and therefore no target_spec. This might mean
// that matching failed, or that the relocation can be applied looking at local
// types only
// types only (eg with EnumVariantExists, FieldExists etc)
ComputedRelocation::new(rel, &local_spec, None)?
};
@ -310,7 +375,7 @@ fn find_candidates<'target>(
fn match_candidate<'target>(
local_spec: &AccessSpec,
candidate: &'target Candidate,
) -> Result<Option<AccessSpec<'target>>, ErrorWrapper> {
) -> Result<Option<AccessSpec<'target>>, RelocationError> {
let mut target_spec = AccessSpec {
btf: candidate.btf,
root_type_id: candidate.type_id,
@ -341,19 +406,35 @@ fn match_candidate<'target>(
let target_ty = candidate.btf.type_by_id(target_id)?;
// the first accessor is guaranteed to have a name by construction
let local_variant_name = local_spec.accessors[0].name.as_ref().unwrap();
let match_enum =
|name_offset, index, target_spec: &mut AccessSpec| -> Result<_, BtfError> {
let target_variant_name = candidate.btf.string_at(name_offset)?;
if flavorless_name(local_variant_name) == flavorless_name(&target_variant_name)
{
target_spec.parts.push(index);
target_spec.accessors.push(Accessor {
index,
type_id: target_id,
name: None,
});
Ok(Some(()))
} else {
Ok(None)
}
};
match target_ty {
BtfType::Enum(en) => {
for (index, member) in en.variants.iter().enumerate() {
let target_variant_name = candidate.btf.string_at(member.name_offset)?;
if flavorless_name(local_variant_name)
== flavorless_name(&target_variant_name)
if let Ok(Some(_)) = match_enum(member.name_offset, index, &mut target_spec)
{
return Ok(Some(target_spec));
}
}
}
BtfType::Enum64(en) => {
for (index, member) in en.variants.iter().enumerate() {
if let Ok(Some(_)) = match_enum(member.name_offset, index, &mut target_spec)
{
target_spec.parts.push(index);
target_spec.accessors.push(Accessor {
index,
type_id: target_id,
name: None,
});
return Ok(Some(target_spec));
}
}
@ -412,8 +493,7 @@ fn match_candidate<'target>(
if target_spec.parts.len() == MAX_SPEC_LEN {
return Err(RelocationError::MaximumNestingLevelReached {
type_name: Some(candidate.name.clone()),
}
.into());
});
}
target_spec.parts.push(accessor.index);
@ -439,7 +519,7 @@ fn match_member<'target>(
target_btf: &'target Btf,
target_id: u32,
target_spec: &mut AccessSpec<'target>,
) -> Result<Option<u32>, ErrorWrapper> {
) -> Result<Option<u32>, RelocationError> {
let local_ty = local_btf.type_by_id(local_accessor.type_id)?;
let local_member = match local_ty {
// this won't panic, bounds are checked when local_spec is built in AccessSpec::new
@ -463,8 +543,7 @@ fn match_member<'target>(
let root_ty = target_spec.btf.type_by_id(target_spec.root_type_id)?;
return Err(RelocationError::MaximumNestingLevelReached {
type_name: target_spec.btf.err_type_name(root_ty),
}
.into());
});
}
// this will not panic as we've already established these are fields types
@ -525,7 +604,7 @@ impl<'a> AccessSpec<'a> {
root_type_id: u32,
spec: &str,
relocation: Relocation,
) -> Result<AccessSpec<'a>, ErrorWrapper> {
) -> Result<AccessSpec<'a>, RelocationError> {
let parts = spec
.split(':')
.map(|s| s.parse::<usize>())
@ -545,8 +624,7 @@ impl<'a> AccessSpec<'a> {
if parts != [0] {
return Err(RelocationError::InvalidAccessString {
access_str: spec.to_string(),
}
.into());
});
}
AccessSpec {
btf,
@ -558,31 +636,39 @@ impl<'a> AccessSpec<'a> {
}
}
RelocationKind::EnumVariantExists | RelocationKind::EnumVariantValue => match ty {
BtfType::Enum(en) => {
BtfType::Enum(_) | BtfType::Enum64(_) => {
if parts.len() != 1 {
return Err(RelocationError::InvalidAccessString {
access_str: spec.to_string(),
}
.into());
});
}
let index = parts[0];
if index >= en.variants.len() {
let (n_variants, name_offset) = match ty {
BtfType::Enum(en) => (
en.variants.len(),
en.variants.get(index).map(|v| v.name_offset),
),
BtfType::Enum64(en) => (
en.variants.len(),
en.variants.get(index).map(|v| v.name_offset),
),
_ => unreachable!(),
};
if name_offset.is_none() {
return Err(RelocationError::InvalidAccessIndex {
type_name: btf.err_type_name(ty),
spec: spec.to_string(),
index,
max_index: en.variants.len(),
max_index: n_variants,
error: "tried to access nonexistant enum variant".to_string(),
}
.into());
});
}
let accessors = vec![Accessor {
type_id,
index,
name: Some(
btf.string_at(en.variants.get(index).unwrap().name_offset)?
.to_string(),
),
name: Some(btf.string_at(name_offset.unwrap())?.to_string()),
}];
AccessSpec {
@ -600,8 +686,7 @@ impl<'a> AccessSpec<'a> {
relocation_kind: format!("{:?}", relocation.kind),
type_kind: format!("{:?}", ty.kind()),
error: "enum relocation on non-enum type".to_string(),
}
.into())
})
}
},
@ -631,8 +716,7 @@ impl<'a> AccessSpec<'a> {
index,
max_index: members.len(),
error: "out of bounds struct or union access".to_string(),
}
.into());
});
}
let member = &members[index];
@ -668,8 +752,7 @@ impl<'a> AccessSpec<'a> {
index,
max_index: array.len as usize,
error: "array index out of bounds".to_string(),
}
.into());
});
}
accessors.push(Accessor {
type_id,
@ -686,8 +769,7 @@ impl<'a> AccessSpec<'a> {
type_kind: format!("{:?}", ty.kind()),
error: "field relocation on a type that doesn't have fields"
.to_string(),
}
.into());
});
}
};
}
@ -730,7 +812,7 @@ struct ComputedRelocation {
#[derive(Debug)]
struct ComputedRelocationValue {
value: u32,
value: u64,
size: u32,
type_id: Option<u32>,
}
@ -740,7 +822,7 @@ impl ComputedRelocation {
rel: &Relocation,
local_spec: &AccessSpec,
target_spec: Option<&AccessSpec>,
) -> Result<ComputedRelocation, ErrorWrapper> {
) -> Result<ComputedRelocation, RelocationError> {
use RelocationKind::*;
let ret = match rel.kind {
FieldByteOffset | FieldByteSize | FieldExists | FieldSigned | FieldLShift64
@ -767,10 +849,10 @@ impl ComputedRelocation {
rel: &Relocation,
local_btf: &Btf,
target_btf: &Btf,
) -> Result<(), ErrorWrapper> {
) -> Result<(), RelocationError> {
let instructions = &mut program.function.instructions;
let num_instructions = instructions.len();
let ins_index = rel.ins_offset / std::mem::size_of::<bpf_insn>();
let ins_index = rel.ins_offset / mem::size_of::<bpf_insn>();
let mut ins =
instructions
.get_mut(ins_index)
@ -792,20 +874,18 @@ impl ComputedRelocation {
relocation_number: rel.number,
index: ins_index,
error: format!("invalid src_reg={src_reg:x} expected {BPF_K:x}"),
}
.into());
});
}
ins.imm = target_value as i32;
}
BPF_LDX | BPF_ST | BPF_STX => {
if target_value > std::i16::MAX as u32 {
if target_value > i16::MAX as u64 {
return Err(RelocationError::InvalidInstruction {
relocation_number: rel.number,
index: ins_index,
error: format!("value `{target_value}` overflows 16 bits offset field"),
}
.into());
});
}
ins.off = target_value as i16;
@ -830,8 +910,7 @@ impl ComputedRelocation {
err_type_name(&target_btf.err_type_name(target_ty)),
self.target.size,
),
}
.into())
})
}
}
@ -845,8 +924,7 @@ impl ComputedRelocation {
relocation_number: rel.number,
index: ins_index,
error: format!("invalid target size {size}"),
}
.into())
})
}
} as u8;
ins.code = ins.code & 0xE0 | size | ins.code & 0x07;
@ -862,15 +940,14 @@ impl ComputedRelocation {
},
)?;
next_ins.imm = 0;
next_ins.imm = (target_value >> 32) as i32;
}
class => {
return Err(RelocationError::InvalidInstruction {
relocation_number: rel.number,
index: ins_index,
error: format!("invalid instruction class {class:x}"),
}
.into())
})
}
};
@ -880,20 +957,36 @@ impl ComputedRelocation {
fn compute_enum_relocation(
rel: &Relocation,
spec: Option<&AccessSpec>,
) -> Result<ComputedRelocationValue, ErrorWrapper> {
) -> Result<ComputedRelocationValue, RelocationError> {
use RelocationKind::*;
let value = match rel.kind {
EnumVariantExists => spec.is_some() as u32,
EnumVariantValue => {
let spec = spec.unwrap();
let value = match (rel.kind, spec) {
(EnumVariantExists, spec) => spec.is_some() as u64,
(EnumVariantValue, Some(spec)) => {
let accessor = &spec.accessors[0];
match spec.btf.type_by_id(accessor.type_id)? {
BtfType::Enum(en) => en.variants[accessor.index].value as u32,
_ => panic!("should not be reached"),
BtfType::Enum(en) => {
let value = en.variants[accessor.index].value;
if en.is_signed() {
value as i32 as u64
} else {
value as u64
}
}
BtfType::Enum64(en) => {
let variant = &en.variants[accessor.index];
(variant.value_high as u64) << 32 | variant.value_low as u64
}
// candidate selection ensures that rel_kind == local_kind == target_kind
_ => unreachable!(),
}
}
// this function is only called for enum relocations
_ => panic!("should not be reached"),
_ => {
return Err(RelocationError::MissingTargetDefinition {
kind: rel.kind,
type_id: rel.type_id,
ins_index: rel.ins_offset / mem::size_of::<bpf_insn>(),
})?;
}
};
Ok(ComputedRelocationValue {
@ -906,31 +999,41 @@ impl ComputedRelocation {
fn compute_field_relocation(
rel: &Relocation,
spec: Option<&AccessSpec>,
) -> Result<ComputedRelocationValue, ErrorWrapper> {
) -> Result<ComputedRelocationValue, RelocationError> {
use RelocationKind::*;
if let FieldExists = rel.kind {
// this is the bpf_preserve_field_info(member_access, FIELD_EXISTENCE) case. If we
// managed to build a spec, it means the field exists.
return Ok(ComputedRelocationValue {
value: spec.is_some() as u32,
value: spec.is_some() as u64,
size: 0,
type_id: None,
});
}
let spec = spec.unwrap();
let spec = match spec {
Some(spec) => spec,
None => {
return Err(RelocationError::MissingTargetDefinition {
kind: rel.kind,
type_id: rel.type_id,
ins_index: rel.ins_offset / mem::size_of::<bpf_insn>(),
})?;
}
};
let accessor = spec.accessors.last().unwrap();
if accessor.name.is_none() {
// the last accessor is unnamed, meaning that this is an array access
return match rel.kind {
FieldByteOffset => Ok(ComputedRelocationValue {
value: (spec.bit_offset / 8) as u32,
value: (spec.bit_offset / 8) as u64,
size: spec.btf.type_size(accessor.type_id)? as u32,
type_id: Some(accessor.type_id),
}),
FieldByteSize => Ok(ComputedRelocationValue {
value: spec.btf.type_size(accessor.type_id)? as u32,
value: spec.btf.type_size(accessor.type_id)? as u64,
size: 0,
type_id: Some(accessor.type_id),
}),
@ -941,8 +1044,7 @@ impl ComputedRelocation {
relocation_kind: format!("{rel_kind:?}"),
type_kind: format!("{:?}", ty.kind()),
error: "invalid relocation kind for array type".to_string(),
}
.into());
});
}
};
}
@ -957,8 +1059,7 @@ impl ComputedRelocation {
relocation_kind: format!("{:?}", rel.kind),
type_kind: format!("{:?}", ty.kind()),
error: "field relocation on a type that doesn't have fields".to_string(),
}
.into());
});
}
};
@ -997,30 +1098,31 @@ impl ComputedRelocation {
#[allow(clippy::wildcard_in_or_patterns)]
match rel.kind {
FieldByteOffset => {
value.value = byte_off;
value.value = byte_off as u64;
if !is_bitfield {
value.size = byte_size;
value.type_id = Some(member_type_id);
}
}
FieldByteSize => {
value.value = byte_size;
value.value = byte_size as u64;
}
FieldSigned => match member_ty {
BtfType::Enum(_) => value.value = 1,
BtfType::Int(i) => value.value = i.encoding() as u32 & IntEncoding::Signed as u32,
BtfType::Enum(en) => value.value = en.is_signed() as u64,
BtfType::Enum64(en) => value.value = en.is_signed() as u64,
BtfType::Int(i) => value.value = i.encoding() as u64 & IntEncoding::Signed as u64,
_ => (),
},
#[cfg(target_endian = "little")]
FieldLShift64 => {
value.value = 64 - (bit_off + bit_size - byte_off * 8);
value.value = 64 - (bit_off + bit_size - byte_off * 8) as u64;
}
#[cfg(target_endian = "big")]
FieldLShift64 => {
value.value = (8 - byte_size) * 8 + (bit_off - byte_off * 8);
}
FieldRShift64 => {
value.value = 64 - bit_size;
value.value = 64 - bit_size as u64;
}
FieldExists // this is handled at the start of the function
| _ => panic!("bug! this should not be reached"),
@ -1033,21 +1135,23 @@ impl ComputedRelocation {
rel: &Relocation,
local_spec: &AccessSpec,
target_spec: Option<&AccessSpec>,
) -> Result<ComputedRelocationValue, ErrorWrapper> {
) -> Result<ComputedRelocationValue, RelocationError> {
use RelocationKind::*;
let value = match rel.kind {
TypeIdLocal => local_spec.root_type_id,
_ => match target_spec {
Some(target_spec) => match rel.kind {
TypeIdTarget => target_spec.root_type_id,
TypeExists => 1,
TypeSize => target_spec.btf.type_size(target_spec.root_type_id)? as u32,
_ => panic!("bug! this should not be reached"),
},
// FIXME in the case of TypeIdTarget and TypeSize this should probably fail the
// relocation...
None => 0,
},
let value = match (rel.kind, target_spec) {
(TypeIdLocal, _) => local_spec.root_type_id as u64,
(TypeIdTarget, Some(target_spec)) => target_spec.root_type_id as u64,
(TypeExists, target_spec) => target_spec.is_some() as u64,
(TypeSize, Some(target_spec)) => {
target_spec.btf.type_size(target_spec.root_type_id)? as u64
}
_ => {
return Err(RelocationError::MissingTargetDefinition {
kind: rel.kind,
type_id: rel.type_id,
ins_index: rel.ins_offset / mem::size_of::<bpf_insn>(),
})?;
}
};
Ok(ComputedRelocationValue {
@ -1057,14 +1161,3 @@ impl ComputedRelocation {
})
}
}
// this exists only to simplify propagating errors from relocate_btf() and to associate
// RelocationError(s) with their respective program name
#[derive(Error, Debug)]
enum ErrorWrapper {
#[error(transparent)]
BtfError(#[from] BtfError),
#[error(transparent)]
RelocationError(#[from] RelocationError),
}

@ -1,11 +1,14 @@
use std::{fmt::Display, mem, ptr};
#![allow(missing_docs)]
use core::{fmt::Display, mem, ptr};
use alloc::{string::ToString, vec, vec::Vec};
use object::Endianness;
use crate::obj::btf::{Btf, BtfError, MAX_RESOLVE_DEPTH};
use crate::btf::{Btf, BtfError, MAX_RESOLVE_DEPTH};
#[derive(Clone, Debug)]
pub(crate) enum BtfType {
pub enum BtfType {
Unknown,
Fwd(Fwd),
Const(Const),
@ -25,11 +28,12 @@ pub(crate) enum BtfType {
DataSec(DataSec),
DeclTag(DeclTag),
TypeTag(TypeTag),
Enum64(Enum64),
}
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Fwd {
pub struct Fwd {
pub(crate) name_offset: u32,
info: u32,
_unused: u32,
@ -51,7 +55,7 @@ impl Fwd {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Const {
pub struct Const {
pub(crate) name_offset: u32,
info: u32,
pub(crate) btf_type: u32,
@ -82,7 +86,7 @@ impl Const {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Volatile {
pub struct Volatile {
pub(crate) name_offset: u32,
info: u32,
pub(crate) btf_type: u32,
@ -103,7 +107,7 @@ impl Volatile {
}
#[derive(Clone, Debug)]
pub(crate) struct Restrict {
pub struct Restrict {
pub(crate) name_offset: u32,
_info: u32,
pub(crate) btf_type: u32,
@ -125,7 +129,7 @@ impl Restrict {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Ptr {
pub struct Ptr {
pub(crate) name_offset: u32,
info: u32,
pub(crate) btf_type: u32,
@ -144,7 +148,7 @@ impl Ptr {
mem::size_of::<Self>()
}
pub(crate) fn new(name_offset: u32, btf_type: u32) -> Self {
pub fn new(name_offset: u32, btf_type: u32) -> Self {
let info = (BtfKind::Ptr as u32) << 24;
Ptr {
name_offset,
@ -156,7 +160,7 @@ impl Ptr {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Typedef {
pub struct Typedef {
pub(crate) name_offset: u32,
info: u32,
pub(crate) btf_type: u32,
@ -187,7 +191,7 @@ impl Typedef {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Float {
pub struct Float {
pub(crate) name_offset: u32,
info: u32,
pub(crate) size: u32,
@ -205,7 +209,7 @@ impl Float {
mem::size_of::<Self>()
}
pub(crate) fn new(name_offset: u32, size: u32) -> Self {
pub fn new(name_offset: u32, size: u32) -> Self {
let info = (BtfKind::Float as u32) << 24;
Float {
name_offset,
@ -217,7 +221,7 @@ impl Float {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Func {
pub struct Func {
pub(crate) name_offset: u32,
info: u32,
pub(crate) btf_type: u32,
@ -225,7 +229,7 @@ pub(crate) struct Func {
#[repr(u32)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) enum FuncLinkage {
pub enum FuncLinkage {
Static = 0,
Global = 1,
Extern = 2,
@ -255,7 +259,7 @@ impl Func {
mem::size_of::<Self>()
}
pub(crate) fn new(name_offset: u32, proto: u32, linkage: FuncLinkage) -> Self {
pub fn new(name_offset: u32, proto: u32, linkage: FuncLinkage) -> Self {
let mut info = (BtfKind::Func as u32) << 24;
info |= (linkage as u32) & 0xFFFF;
Func {
@ -276,7 +280,7 @@ impl Func {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct TypeTag {
pub struct TypeTag {
pub(crate) name_offset: u32,
info: u32,
pub(crate) btf_type: u32,
@ -295,7 +299,7 @@ impl TypeTag {
mem::size_of::<Self>()
}
pub(crate) fn new(name_offset: u32, btf_type: u32) -> Self {
pub fn new(name_offset: u32, btf_type: u32) -> Self {
let info = (BtfKind::TypeTag as u32) << 24;
TypeTag {
name_offset,
@ -307,7 +311,7 @@ impl TypeTag {
#[repr(u32)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) enum IntEncoding {
pub enum IntEncoding {
None,
Signed = 1,
Char = 2,
@ -329,7 +333,7 @@ impl From<u32> for IntEncoding {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Int {
pub struct Int {
pub(crate) name_offset: u32,
info: u32,
pub(crate) size: u32,
@ -353,7 +357,7 @@ impl Int {
mem::size_of::<Self>()
}
pub(crate) fn new(name_offset: u32, size: u32, encoding: IntEncoding, offset: u32) -> Self {
pub fn new(name_offset: u32, size: u32, encoding: IntEncoding, offset: u32) -> Self {
let info = (BtfKind::Int as u32) << 24;
let mut data = 0u32;
data |= (encoding as u32 & 0x0f) << 24;
@ -386,12 +390,12 @@ impl Int {
#[derive(Debug, Clone)]
pub(crate) struct BtfEnum {
pub(crate) name_offset: u32,
pub(crate) value: i32,
pub(crate) value: u32,
}
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Enum {
pub struct Enum {
pub(crate) name_offset: u32,
info: u32,
pub(crate) size: u32,
@ -406,7 +410,7 @@ impl Enum {
buf.extend(bytes_of::<u32>(&self.size));
for v in &self.variants {
buf.extend(bytes_of::<u32>(&v.name_offset));
buf.extend(bytes_of::<i32>(&v.value));
buf.extend(bytes_of::<u32>(&v.value));
}
buf
}
@ -429,6 +433,54 @@ impl Enum {
variants,
}
}
pub(crate) fn is_signed(&self) -> bool {
self.info >> 31 == 1
}
}
#[repr(C)]
#[derive(Debug, Clone)]
pub struct BtfEnum64 {
pub(crate) name_offset: u32,
pub(crate) value_low: u32,
pub(crate) value_high: u32,
}
#[repr(C)]
#[derive(Clone, Debug)]
pub struct Enum64 {
pub(crate) name_offset: u32,
info: u32,
pub(crate) size: u32,
pub(crate) variants: Vec<BtfEnum64>,
}
impl Enum64 {
pub(crate) fn to_bytes(&self) -> Vec<u8> {
let mut buf = vec![];
buf.extend(bytes_of::<u32>(&self.name_offset));
buf.extend(bytes_of::<u32>(&self.info));
buf.extend(bytes_of::<u32>(&self.size));
for v in &self.variants {
buf.extend(bytes_of::<u32>(&v.name_offset));
buf.extend(bytes_of::<u32>(&v.value_high));
buf.extend(bytes_of::<u32>(&v.value_low));
}
buf
}
pub(crate) fn kind(&self) -> BtfKind {
BtfKind::Enum64
}
pub(crate) fn type_info_size(&self) -> usize {
mem::size_of::<Fwd>() + mem::size_of::<BtfEnum64>() * self.variants.len()
}
pub(crate) fn is_signed(&self) -> bool {
self.info >> 31 == 1
}
}
#[repr(C)]
@ -441,7 +493,7 @@ pub(crate) struct BtfMember {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Struct {
pub struct Struct {
pub(crate) name_offset: u32,
info: u32,
pub(crate) size: u32,
@ -502,7 +554,7 @@ impl Struct {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Union {
pub struct Union {
pub(crate) name_offset: u32,
info: u32,
pub(crate) size: u32,
@ -559,7 +611,7 @@ pub(crate) struct BtfArray {
}
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Array {
pub struct Array {
pub(crate) name_offset: u32,
info: u32,
_unused: u32,
@ -602,14 +654,14 @@ impl Array {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct BtfParam {
pub(crate) name_offset: u32,
pub(crate) btf_type: u32,
pub struct BtfParam {
pub name_offset: u32,
pub btf_type: u32,
}
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct FuncProto {
pub struct FuncProto {
pub(crate) name_offset: u32,
info: u32,
pub(crate) return_type: u32,
@ -637,7 +689,7 @@ impl FuncProto {
mem::size_of::<Fwd>() + mem::size_of::<BtfParam>() * self.params.len()
}
pub(crate) fn new(params: Vec<BtfParam>, return_type: u32) -> Self {
pub fn new(params: Vec<BtfParam>, return_type: u32) -> Self {
let mut info = (BtfKind::FuncProto as u32) << 24;
info |= (params.len() as u32) & 0xFFFF;
FuncProto {
@ -651,7 +703,7 @@ impl FuncProto {
#[repr(u32)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) enum VarLinkage {
pub enum VarLinkage {
Static,
Global,
Extern,
@ -671,7 +723,7 @@ impl From<u32> for VarLinkage {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Var {
pub struct Var {
pub(crate) name_offset: u32,
info: u32,
pub(crate) btf_type: u32,
@ -696,7 +748,7 @@ impl Var {
mem::size_of::<Self>()
}
pub(crate) fn new(name_offset: u32, btf_type: u32, linkage: VarLinkage) -> Self {
pub fn new(name_offset: u32, btf_type: u32, linkage: VarLinkage) -> Self {
let info = (BtfKind::Var as u32) << 24;
Var {
name_offset,
@ -709,15 +761,15 @@ impl Var {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct DataSecEntry {
pub(crate) btf_type: u32,
pub(crate) offset: u32,
pub(crate) size: u32,
pub struct DataSecEntry {
pub btf_type: u32,
pub offset: u32,
pub size: u32,
}
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct DataSec {
pub struct DataSec {
pub(crate) name_offset: u32,
info: u32,
pub(crate) size: u32,
@ -746,7 +798,7 @@ impl DataSec {
mem::size_of::<Fwd>() + mem::size_of::<DataSecEntry>() * self.entries.len()
}
pub(crate) fn new(name_offset: u32, entries: Vec<DataSecEntry>, size: u32) -> Self {
pub fn new(name_offset: u32, entries: Vec<DataSecEntry>, size: u32) -> Self {
let mut info = (BtfKind::DataSec as u32) << 24;
info |= (entries.len() as u32) & 0xFFFF;
DataSec {
@ -760,7 +812,7 @@ impl DataSec {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct DeclTag {
pub struct DeclTag {
pub(crate) name_offset: u32,
info: u32,
pub(crate) btf_type: u32,
@ -785,7 +837,7 @@ impl DeclTag {
mem::size_of::<Self>()
}
pub(crate) fn new(name_offset: u32, btf_type: u32, component_index: i32) -> Self {
pub fn new(name_offset: u32, btf_type: u32, component_index: i32) -> Self {
let info = (BtfKind::DeclTag as u32) << 24;
DeclTag {
name_offset,
@ -796,9 +848,10 @@ impl DeclTag {
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
#[repr(u32)]
pub(crate) enum BtfKind {
pub enum BtfKind {
#[default]
Unknown = 0,
Int = 1,
Ptr = 2,
@ -818,6 +871,7 @@ pub(crate) enum BtfKind {
Float = 16,
DeclTag = 17,
TypeTag = 18,
Enum64 = 19,
}
impl TryFrom<u32> for BtfKind {
@ -845,13 +899,14 @@ impl TryFrom<u32> for BtfKind {
16 => Float,
17 => DeclTag,
18 => TypeTag,
19 => Enum64,
kind => return Err(BtfError::InvalidTypeKind { kind }),
})
}
}
impl Display for BtfKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
BtfKind::Unknown => write!(f, "[UNKNOWN]"),
BtfKind::Int => write!(f, "[INT]"),
@ -872,16 +927,11 @@ impl Display for BtfKind {
BtfKind::DataSec => write!(f, "[DATASEC]"),
BtfKind::DeclTag => write!(f, "[DECL_TAG]"),
BtfKind::TypeTag => write!(f, "[TYPE_TAG]"),
BtfKind::Enum64 => write!(f, "[ENUM64]"),
}
}
}
impl Default for BtfKind {
fn default() -> Self {
BtfKind::Unknown
}
}
unsafe fn read<T>(data: &[u8]) -> Result<T, BtfError> {
if mem::size_of::<T>() > data.len() {
return Err(BtfError::InvalidTypeInfo);
@ -972,6 +1022,12 @@ impl BtfType {
size: ty[2],
variants: unsafe { read_array::<BtfEnum>(data, vlen)? },
}),
BtfKind::Enum64 => BtfType::Enum64(Enum64 {
name_offset: ty[0],
info: ty[1],
size: ty[2],
variants: unsafe { read_array::<BtfEnum64>(data, vlen)? },
}),
BtfKind::Array => BtfType::Array(Array {
name_offset: ty[0],
info: ty[1],
@ -1035,6 +1091,7 @@ impl BtfType {
BtfType::Int(t) => t.to_bytes(),
BtfType::Float(t) => t.to_bytes(),
BtfType::Enum(t) => t.to_bytes(),
BtfType::Enum64(t) => t.to_bytes(),
BtfType::Array(t) => t.to_bytes(),
BtfType::Struct(t) => t.to_bytes(),
BtfType::Union(t) => t.to_bytes(),
@ -1051,9 +1108,11 @@ impl BtfType {
BtfType::Int(t) => Some(t.size),
BtfType::Float(t) => Some(t.size),
BtfType::Enum(t) => Some(t.size),
BtfType::Enum64(t) => Some(t.size),
BtfType::Struct(t) => Some(t.size),
BtfType::Union(t) => Some(t.size),
BtfType::DataSec(t) => Some(t.size),
BtfType::Ptr(_) => Some(mem::size_of::<&()>() as u32),
_ => None,
}
}
@ -1087,6 +1146,7 @@ impl BtfType {
BtfType::Int(t) => t.type_info_size(),
BtfType::Float(t) => t.type_info_size(),
BtfType::Enum(t) => t.type_info_size(),
BtfType::Enum64(t) => t.type_info_size(),
BtfType::Array(t) => t.type_info_size(),
BtfType::Struct(t) => t.type_info_size(),
BtfType::Union(t) => t.type_info_size(),
@ -1111,6 +1171,7 @@ impl BtfType {
BtfType::Int(t) => t.name_offset,
BtfType::Float(t) => t.name_offset,
BtfType::Enum(t) => t.name_offset,
BtfType::Enum64(t) => t.name_offset,
BtfType::Array(t) => t.name_offset,
BtfType::Struct(t) => t.name_offset,
BtfType::Union(t) => t.name_offset,
@ -1135,6 +1196,7 @@ impl BtfType {
BtfType::Int(t) => t.kind(),
BtfType::Float(t) => t.kind(),
BtfType::Enum(t) => t.kind(),
BtfType::Enum64(t) => t.kind(),
BtfType::Array(t) => t.kind(),
BtfType::Struct(t) => t.kind(),
BtfType::Union(t) => t.kind(),
@ -1173,6 +1235,17 @@ impl BtfType {
_ => None,
}
}
pub(crate) fn is_compatible(&self, other: &BtfType) -> bool {
if self.kind() == other.kind() {
return true;
}
matches!(
(self.kind(), other.kind()),
(BtfKind::Enum, BtfKind::Enum64) | (BtfKind::Enum64, BtfKind::Enum)
)
}
}
fn type_kind(info: u32) -> Result<BtfKind, BtfError> {
@ -1194,7 +1267,7 @@ pub(crate) fn types_are_compatible(
let local_ty = local_btf.type_by_id(local_id)?;
let target_ty = target_btf.type_by_id(target_id)?;
if local_ty.kind() != target_ty.kind() {
if !local_ty.is_compatible(target_ty) {
return Ok(false);
}
@ -1204,7 +1277,7 @@ pub(crate) fn types_are_compatible(
let local_ty = local_btf.type_by_id(local_id)?;
let target_ty = target_btf.type_by_id(target_id)?;
if local_ty.kind() != target_ty.kind() {
if !local_ty.is_compatible(target_ty) {
return Ok(false);
}
@ -1213,6 +1286,7 @@ pub(crate) fn types_are_compatible(
| BtfType::Struct(_)
| BtfType::Union(_)
| BtfType::Enum(_)
| BtfType::Enum64(_)
| BtfType::Fwd(_)
| BtfType::Float(_) => return Ok(true),
BtfType::Int(local) => {
@ -1276,12 +1350,12 @@ pub(crate) fn fields_are_compatible(
return Ok(true);
}
if local_ty.kind() != target_ty.kind() {
if !local_ty.is_compatible(target_ty) {
return Ok(false);
}
match local_ty {
BtfType::Fwd(_) | BtfType::Enum(_) => {
BtfType::Fwd(_) | BtfType::Enum(_) | BtfType::Enum64(_) => {
let flavorless_name =
|name: &str| name.split_once("___").map_or(name, |x| x.0).to_string();

@ -1,10 +1,10 @@
/* automatically generated by rust-bindgen 0.60.1 */
/* automatically generated by rust-bindgen 0.63.0 */
pub type __u8 = ::std::os::raw::c_uchar;
pub type __u16 = ::std::os::raw::c_ushort;
pub type __u32 = ::std::os::raw::c_uint;
pub type __u8 = ::core::ffi::c_uchar;
pub type __u16 = ::core::ffi::c_ushort;
pub type __u32 = ::core::ffi::c_uint;
pub mod bpf_core_relo_kind {
pub type Type = ::std::os::raw::c_uint;
pub type Type = ::core::ffi::c_uint;
pub const BPF_CORE_FIELD_BYTE_OFFSET: Type = 0;
pub const BPF_CORE_FIELD_BYTE_SIZE: Type = 1;
pub const BPF_CORE_FIELD_EXISTS: Type = 2;

@ -1,3 +1,5 @@
//! eBPF bindings generated by rust-bindgen
#![allow(
dead_code,
non_camel_case_types,

@ -0,0 +1,85 @@
//! An eBPF object file parsing library with BTF and relocation support.
//!
//! # Status
//!
//! This crate includes code that started as internal API used by
//! the [aya] crate. It has been split out so that it can be used by
//! other projects that deal with eBPF object files. Unless you're writing
//! low level eBPF plumbing tools, you should not need to use this crate
//! but see the [aya] crate instead.
//!
//! The API as it is today has a few rough edges and is generally not as
//! polished nor stable as the main [aya] crate API. As always,
//! improvements welcome!
//!
//! [aya]: https://github.com/aya-rs/aya
//!
//! # Overview
//!
//! eBPF programs written with [libbpf] or [aya-bpf] are usually compiled
//! into an ELF object file, using various sections to store information
//! about the eBPF programs.
//!
//! `aya-obj` is a library for parsing such eBPF object files, with BTF and
//! relocation support.
//!
//! [libbpf]: https://github.com/libbpf/libbpf
//! [aya-bpf]: https://github.com/aya-rs/aya
//!
//! # Example
//!
//! This example loads a simple eBPF program and runs it with [rbpf].
//!
//! ```no_run
//! use aya_obj::{generated::bpf_insn, Object};
//!
//! // Parse the object file
//! let bytes = std::fs::read("program.o").unwrap();
//! let mut object = Object::parse(&bytes).unwrap();
//! // Relocate the programs
//! object.relocate_calls().unwrap();
//! object.relocate_maps(std::iter::empty()).unwrap();
//!
//! // Run with rbpf
//! let instructions = &object.programs["prog_name"].function.instructions;
//! let data = unsafe {
//! core::slice::from_raw_parts(
//! instructions.as_ptr() as *const u8,
//! instructions.len() * core::mem::size_of::<bpf_insn>(),
//! )
//! };
//! let vm = rbpf::EbpfVmNoData::new(Some(data)).unwrap();
//! let _return = vm.execute_program().unwrap();
//! ```
//!
//! [rbpf]: https://github.com/qmonnet/rbpf
#![no_std]
#![doc(
html_logo_url = "https://aya-rs.dev/assets/images/crabby.svg",
html_favicon_url = "https://aya-rs.dev/assets/images/crabby.svg"
)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![deny(clippy::all, missing_docs)]
#![allow(clippy::missing_safety_doc, clippy::len_without_is_empty)]
#![cfg_attr(feature = "no_std", feature(error_in_core))]
#[cfg(feature = "no_std")]
pub(crate) use thiserror_core as thiserror;
#[cfg(not(feature = "no_std"))]
pub(crate) use thiserror_std as thiserror;
extern crate alloc;
#[cfg(not(feature = "no_std"))]
extern crate std;
pub mod btf;
pub mod generated;
pub mod maps;
pub mod obj;
pub mod programs;
pub mod relocation;
mod util;
pub use maps::Map;
pub use obj::*;

@ -0,0 +1,303 @@
//! Map struct and type bindings.
use core::mem;
use crate::thiserror::{self, Error};
use alloc::vec::Vec;
/// Invalid map type encontered
pub struct InvalidMapTypeError {
/// The map type
pub map_type: u32,
}
impl TryFrom<u32> for crate::generated::bpf_map_type {
type Error = InvalidMapTypeError;
fn try_from(map_type: u32) -> Result<Self, Self::Error> {
use crate::generated::bpf_map_type::*;
Ok(match map_type {
x if x == BPF_MAP_TYPE_UNSPEC as u32 => BPF_MAP_TYPE_UNSPEC,
x if x == BPF_MAP_TYPE_HASH as u32 => BPF_MAP_TYPE_HASH,
x if x == BPF_MAP_TYPE_ARRAY as u32 => BPF_MAP_TYPE_ARRAY,
x if x == BPF_MAP_TYPE_PROG_ARRAY as u32 => BPF_MAP_TYPE_PROG_ARRAY,
x if x == BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32 => BPF_MAP_TYPE_PERF_EVENT_ARRAY,
x if x == BPF_MAP_TYPE_PERCPU_HASH as u32 => BPF_MAP_TYPE_PERCPU_HASH,
x if x == BPF_MAP_TYPE_PERCPU_ARRAY as u32 => BPF_MAP_TYPE_PERCPU_ARRAY,
x if x == BPF_MAP_TYPE_STACK_TRACE as u32 => BPF_MAP_TYPE_STACK_TRACE,
x if x == BPF_MAP_TYPE_CGROUP_ARRAY as u32 => BPF_MAP_TYPE_CGROUP_ARRAY,
x if x == BPF_MAP_TYPE_LRU_HASH as u32 => BPF_MAP_TYPE_LRU_HASH,
x if x == BPF_MAP_TYPE_LRU_PERCPU_HASH as u32 => BPF_MAP_TYPE_LRU_PERCPU_HASH,
x if x == BPF_MAP_TYPE_LPM_TRIE as u32 => BPF_MAP_TYPE_LPM_TRIE,
x if x == BPF_MAP_TYPE_BLOOM_FILTER as u32 => BPF_MAP_TYPE_BLOOM_FILTER,
x if x == BPF_MAP_TYPE_ARRAY_OF_MAPS as u32 => BPF_MAP_TYPE_ARRAY_OF_MAPS,
x if x == BPF_MAP_TYPE_HASH_OF_MAPS as u32 => BPF_MAP_TYPE_HASH_OF_MAPS,
x if x == BPF_MAP_TYPE_DEVMAP as u32 => BPF_MAP_TYPE_DEVMAP,
x if x == BPF_MAP_TYPE_SOCKMAP as u32 => BPF_MAP_TYPE_SOCKMAP,
x if x == BPF_MAP_TYPE_CPUMAP as u32 => BPF_MAP_TYPE_CPUMAP,
x if x == BPF_MAP_TYPE_XSKMAP as u32 => BPF_MAP_TYPE_XSKMAP,
x if x == BPF_MAP_TYPE_SOCKHASH as u32 => BPF_MAP_TYPE_SOCKHASH,
x if x == BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED as u32 => {
BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED
}
x if x == BPF_MAP_TYPE_CGRP_STORAGE as u32 => BPF_MAP_TYPE_CGRP_STORAGE,
x if x == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY as u32 => BPF_MAP_TYPE_REUSEPORT_SOCKARRAY,
x if x == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE as u32 => {
BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE
}
x if x == BPF_MAP_TYPE_QUEUE as u32 => BPF_MAP_TYPE_QUEUE,
x if x == BPF_MAP_TYPE_STACK as u32 => BPF_MAP_TYPE_STACK,
x if x == BPF_MAP_TYPE_SK_STORAGE as u32 => BPF_MAP_TYPE_SK_STORAGE,
x if x == BPF_MAP_TYPE_DEVMAP_HASH as u32 => BPF_MAP_TYPE_DEVMAP_HASH,
x if x == BPF_MAP_TYPE_STRUCT_OPS as u32 => BPF_MAP_TYPE_STRUCT_OPS,
x if x == BPF_MAP_TYPE_RINGBUF as u32 => BPF_MAP_TYPE_RINGBUF,
x if x == BPF_MAP_TYPE_INODE_STORAGE as u32 => BPF_MAP_TYPE_INODE_STORAGE,
x if x == BPF_MAP_TYPE_TASK_STORAGE as u32 => BPF_MAP_TYPE_TASK_STORAGE,
x if x == BPF_MAP_TYPE_BLOOM_FILTER as u32 => BPF_MAP_TYPE_BLOOM_FILTER,
x if x == BPF_MAP_TYPE_USER_RINGBUF as u32 => BPF_MAP_TYPE_USER_RINGBUF,
x if x == BPF_MAP_TYPE_CGRP_STORAGE as u32 => BPF_MAP_TYPE_CGRP_STORAGE,
_ => return Err(InvalidMapTypeError { map_type }),
})
}
}
/// BTF definition of a map
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct BtfMapDef {
pub(crate) map_type: u32,
pub(crate) key_size: u32,
pub(crate) value_size: u32,
pub(crate) max_entries: u32,
pub(crate) map_flags: u32,
pub(crate) pinning: PinningType,
/// BTF type id of the map key
pub btf_key_type_id: u32,
/// BTF type id of the map value
pub btf_value_type_id: u32,
}
/// The pinning type
///
/// Upon pinning a map, a file representation is created for the map,
/// so that the map can be alive and retrievable across sessions.
#[repr(u32)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
pub enum PinningType {
/// No pinning
#[default]
None = 0,
/// Pin by the name
ByName = 1,
}
/// The error type returned when failing to parse a [PinningType]
#[derive(Debug, Error)]
pub enum PinningError {
/// Unsupported pinning type
#[error("unsupported pinning type `{pinning_type}`")]
Unsupported {
/// The unsupported pinning type
pinning_type: u32,
},
}
impl TryFrom<u32> for PinningType {
type Error = PinningError;
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
0 => Ok(PinningType::None),
1 => Ok(PinningType::ByName),
pinning_type => Err(PinningError::Unsupported { pinning_type }),
}
}
}
/// Map definition in legacy BPF map declaration style
#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct bpf_map_def {
// minimum features required by old BPF programs
/// The map type
pub map_type: u32,
/// The key_size
pub key_size: u32,
/// The value size
pub value_size: u32,
/// Max entry number
pub max_entries: u32,
/// Map flags
pub map_flags: u32,
// optional features
/// Id
pub id: u32,
/// Pinning type
pub pinning: PinningType,
}
/// The first five __u32 of `bpf_map_def` must be defined.
pub(crate) const MINIMUM_MAP_SIZE: usize = mem::size_of::<u32>() * 5;
/// Kinds of maps
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum MapKind {
/// A map holding `.bss` section data
Bss,
/// A map holding `.data` section data
Data,
/// A map holding `.rodata` section data
Rodata,
/// Other maps
Other,
}
impl From<&str> for MapKind {
fn from(s: &str) -> Self {
if s == ".bss" {
MapKind::Bss
} else if s.starts_with(".data") {
MapKind::Data
} else if s.starts_with(".rodata") {
MapKind::Rodata
} else {
MapKind::Other
}
}
}
/// Map data defined in `maps` or `.maps` sections
#[derive(Debug, Clone)]
pub enum Map {
/// A map defined in the `maps` section
Legacy(LegacyMap),
/// A map defined in the `.maps` section
Btf(BtfMap),
}
impl Map {
/// Returns the map type
pub fn map_type(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.map_type,
Map::Btf(m) => m.def.map_type,
}
}
/// Returns the key size in bytes
pub fn key_size(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.key_size,
Map::Btf(m) => m.def.key_size,
}
}
/// Returns the value size in bytes
pub fn value_size(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.value_size,
Map::Btf(m) => m.def.value_size,
}
}
/// Returns the max entry number
pub fn max_entries(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.max_entries,
Map::Btf(m) => m.def.max_entries,
}
}
/// Sets the max entry number
pub fn set_max_entries(&mut self, v: u32) {
match self {
Map::Legacy(m) => m.def.max_entries = v,
Map::Btf(m) => m.def.max_entries = v,
}
}
/// Returns the map flags
pub fn map_flags(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.map_flags,
Map::Btf(m) => m.def.map_flags,
}
}
/// Returns the pinning type of the map
pub fn pinning(&self) -> PinningType {
match self {
Map::Legacy(m) => m.def.pinning,
Map::Btf(m) => m.def.pinning,
}
}
/// Returns the map data
pub fn data(&self) -> &[u8] {
match self {
Map::Legacy(m) => &m.data,
Map::Btf(m) => &m.data,
}
}
/// Returns the map data as mutable
pub fn data_mut(&mut self) -> &mut Vec<u8> {
match self {
Map::Legacy(m) => m.data.as_mut(),
Map::Btf(m) => m.data.as_mut(),
}
}
/// Returns the map kind
pub fn kind(&self) -> MapKind {
match self {
Map::Legacy(m) => m.kind,
Map::Btf(m) => m.kind,
}
}
/// Returns the section index
pub fn section_index(&self) -> usize {
match self {
Map::Legacy(m) => m.section_index,
Map::Btf(m) => m.section_index,
}
}
/// Returns the symbol index
pub fn symbol_index(&self) -> usize {
match self {
Map::Legacy(m) => m.symbol_index,
Map::Btf(m) => m.symbol_index,
}
}
}
/// A map declared with legacy BPF map declaration style, most likely from a `maps` section.
///
/// See [Drop support for legacy BPF map declaration syntax - Libbpf: the road to v1.0](https://github.com/libbpf/libbpf/wiki/Libbpf:-the-road-to-v1.0#drop-support-for-legacy-bpf-map-declaration-syntax)
/// for more info.
#[derive(Debug, Clone)]
pub struct LegacyMap {
/// The definition of the map
pub def: bpf_map_def,
/// The section index
pub section_index: usize,
/// The symbol index
pub symbol_index: usize,
/// The map data
pub data: Vec<u8>,
/// The map kind
pub kind: MapKind,
}
/// A BTF-defined map, most likely from a `.maps` section.
#[derive(Debug, Clone)]
pub struct BtfMap {
/// The definition of the map
pub def: BtfMapDef,
pub(crate) section_index: usize,
pub(crate) symbol_index: usize,
pub(crate) kind: MapKind,
pub(crate) data: Vec<u8>,
}

@ -1,47 +1,58 @@
pub(crate) mod btf;
mod relocation;
//! Object file loading, parsing, and relocation.
use alloc::{
borrow::ToOwned,
ffi::CString,
string::{String, ToString},
vec::Vec,
};
use core::{ffi::CStr, mem, ptr, str::FromStr};
use log::debug;
use object::{
read::{Object as ElfObject, ObjectSection, Section as ObjSection},
Endianness, ObjectSymbol, ObjectSymbolTable, RelocationTarget, SectionIndex, SectionKind,
SymbolKind,
};
use std::{
collections::HashMap,
ffi::{CStr, CString},
mem, ptr,
str::FromStr,
};
use thiserror::Error;
use relocation::*;
use crate::{
maps::{BtfMap, LegacyMap, Map, MapKind, MINIMUM_MAP_SIZE},
relocation::*,
thiserror::{self, Error},
util::HashMap,
};
use crate::{
bpf_map_def,
btf::{Btf, BtfError, BtfExt, BtfType},
generated::{bpf_insn, bpf_map_info, bpf_map_type::BPF_MAP_TYPE_ARRAY, BPF_F_RDONLY_PROG},
obj::btf::{Btf, BtfError, BtfExt, BtfType},
maps::{bpf_map_def, BtfMapDef, PinningType},
programs::{CgroupSockAddrAttachType, CgroupSockAttachType, CgroupSockoptAttachType},
BpfError, BtfMapDef, PinningType,
};
use std::slice::from_raw_parts_mut;
use core::slice::from_raw_parts_mut;
use self::btf::{Array, DataSecEntry, FuncSecInfo, LineSecInfo};
use crate::btf::{Array, DataSecEntry, FuncSecInfo, LineSecInfo};
const KERNEL_VERSION_ANY: u32 = 0xFFFF_FFFE;
/// The first five __u32 of `bpf_map_def` must be defined.
const MINIMUM_MAP_SIZE: usize = mem::size_of::<u32>() * 5;
/// The loaded object file representation
#[derive(Clone)]
pub struct Object {
pub(crate) endianness: Endianness,
/// The endianness
pub endianness: Endianness,
/// Program license
pub license: CString,
/// Kernel version
pub kernel_version: KernelVersion,
/// Program BTF
pub btf: Option<Btf>,
/// Program BTF.ext
pub btf_ext: Option<BtfExt>,
pub(crate) maps: HashMap<String, Map>,
pub(crate) programs: HashMap<String, Program>,
pub(crate) functions: HashMap<u64, Function>,
/// Referenced maps
pub maps: HashMap<String, Map>,
/// A hash map of programs, using the program names parsed
/// in [ProgramSection]s as keys.
pub programs: HashMap<String, Program>,
/// Functions
pub functions: HashMap<u64, Function>,
pub(crate) relocations: HashMap<SectionIndex, HashMap<u64, Relocation>>,
pub(crate) symbols_by_index: HashMap<usize, Symbol>,
pub(crate) section_sizes: HashMap<String, u64>,
@ -51,160 +62,107 @@ pub struct Object {
pub(crate) text_section_index: Option<usize>,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub(crate) enum MapKind {
Bss,
Data,
Rodata,
Other,
}
impl From<&str> for MapKind {
fn from(s: &str) -> Self {
if s == ".bss" {
MapKind::Bss
} else if s.starts_with(".data") {
MapKind::Data
} else if s.starts_with(".rodata") {
MapKind::Rodata
} else {
MapKind::Other
}
}
}
/// An eBPF program
#[derive(Debug, Clone)]
pub enum Map {
Legacy(LegacyMap),
Btf(BtfMap),
}
impl Map {
pub(crate) fn map_type(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.map_type,
Map::Btf(m) => m.def.map_type,
}
}
pub(crate) fn key_size(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.key_size,
Map::Btf(m) => m.def.key_size,
}
}
pub(crate) fn value_size(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.value_size,
Map::Btf(m) => m.def.value_size,
}
}
pub(crate) fn max_entries(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.max_entries,
Map::Btf(m) => m.def.max_entries,
}
}
pub(crate) fn set_max_entries(&mut self, v: u32) {
match self {
Map::Legacy(m) => m.def.max_entries = v,
Map::Btf(m) => m.def.max_entries = v,
}
}
pub(crate) fn map_flags(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.map_flags,
Map::Btf(m) => m.def.map_flags,
}
}
pub(crate) fn pinning(&self) -> PinningType {
match self {
Map::Legacy(m) => m.def.pinning,
Map::Btf(m) => m.def.pinning,
}
}
pub(crate) fn data(&self) -> &[u8] {
match self {
Map::Legacy(m) => &m.data,
Map::Btf(m) => &m.data,
}
}
pub(crate) fn data_mut(&mut self) -> &mut Vec<u8> {
match self {
Map::Legacy(m) => m.data.as_mut(),
Map::Btf(m) => m.data.as_mut(),
}
}
pub(crate) fn kind(&self) -> MapKind {
match self {
Map::Legacy(m) => m.kind,
Map::Btf(m) => m.kind,
}
}
pub(crate) fn section_index(&self) -> usize {
match self {
Map::Legacy(m) => m.section_index,
Map::Btf(m) => m.section_index,
}
}
pub(crate) fn symbol_index(&self) -> usize {
match self {
Map::Legacy(m) => m.symbol_index,
Map::Btf(m) => m.symbol_index,
}
}
}
#[derive(Debug, Clone)]
pub struct LegacyMap {
pub(crate) def: bpf_map_def,
pub(crate) section_index: usize,
pub(crate) symbol_index: usize,
pub(crate) data: Vec<u8>,
pub(crate) kind: MapKind,
}
#[derive(Debug, Clone)]
pub struct BtfMap {
pub(crate) def: BtfMapDef,
pub(crate) section_index: usize,
pub(crate) symbol_index: usize,
pub(crate) kind: MapKind,
pub(crate) data: Vec<u8>,
}
#[derive(Debug, Clone)]
pub(crate) struct Program {
pub(crate) license: CString,
pub(crate) kernel_version: KernelVersion,
pub(crate) section: ProgramSection,
pub(crate) function: Function,
pub struct Program {
/// The license
pub license: CString,
/// The kernel version
pub kernel_version: KernelVersion,
/// The section containing the program
pub section: ProgramSection,
/// The function
pub function: Function,
}
/// An eBPF function
#[derive(Debug, Clone)]
pub(crate) struct Function {
pub(crate) address: u64,
pub(crate) name: String,
pub(crate) section_index: SectionIndex,
pub(crate) section_offset: usize,
pub(crate) instructions: Vec<bpf_insn>,
pub(crate) func_info: FuncSecInfo,
pub(crate) line_info: LineSecInfo,
pub(crate) func_info_rec_size: usize,
pub(crate) line_info_rec_size: usize,
pub struct Function {
/// The address
pub address: u64,
/// The function name
pub name: String,
/// The section index
pub section_index: SectionIndex,
/// The section offset
pub section_offset: usize,
/// The eBPF byte code instructions
pub instructions: Vec<bpf_insn>,
/// The function info
pub func_info: FuncSecInfo,
/// The line info
pub line_info: LineSecInfo,
/// Function info record size
pub func_info_rec_size: usize,
/// Line info record size
pub line_info_rec_size: usize,
}
/// Section types containing eBPF programs
///
/// # Section Name Parsing
///
/// Section types are parsed from the section name strings.
///
/// In order for Aya to treat a section as a [ProgramSection],
/// there are a few requirements:
/// - The section must be an executable code section.
/// - The section name must conform to [Program Types and ELF Sections].
///
/// [Program Types and ELF Sections]: https://docs.kernel.org/bpf/libbpf/program_types.html
///
/// ## Program Name
///
/// Each section name is parsed into a section type and a program name.
///
/// Generally speaking,
/// - if the section name does not contain any slashes,
/// then the program name is just that section name;
/// - if there are some slashes, the name is `section_name.rsplitn(2, '/')[0]`,
/// - except for tracepoint programs, for which the name is
/// `section_name.splitn(2, '/')[1]`.
///
/// ```rust
/// use aya_obj::ProgramSection;
/// use std::str::FromStr;
///
/// assert_eq!(
/// ProgramSection::from_str("kprobe/do_unlinkat")
/// .unwrap().name(),
/// "do_unlinkat",
/// );
/// assert_eq!(
/// ProgramSection::from_str("tracepoint/syscalls/sys_enter_openat")
/// .unwrap().name(),
/// "syscalls/sys_enter_openat",
/// );
/// ```
///
/// The program name will be used in [Object] as references to each program.
///
/// # Unsupported Sections
///
/// Currently, the following section names are not supported yet:
/// - `flow_dissector`: `BPF_PROG_TYPE_FLOW_DISSECTOR`
/// - `ksyscall+` or `kretsyscall+`
/// - `uprobe.s+` or `uretprobe.s+`
/// - `usdt+`
/// - `kprobe.multi+` or `kretprobe.multi+`: `BPF_TRACE_KPROBE_MULTI`
/// - `lsm_cgroup+` or `lsm.s+`
/// - `lwt_in`, `lwt_out`, `lwt_seg6local`, `lwt_xmit`
/// - `raw_tp.w+`, `raw_tracepoint.w+`
/// - `action`
/// - `sk_reuseport/migrate`, `sk_reuseport`
/// - `syscall`
/// - `struct_ops+`
/// - `fmod_ret+`, `fmod_ret.s+`
/// - `fentry.s+`, `fexit.s+`
/// - `iter+`, `iter.s+`
/// - `xdp.frags/cpumap`, `xdp/cpumap`
/// - `xdp.frags/devmap`, `xdp/devmap`
/// - `xdp.frags`
#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub enum ProgramSection {
KRetProbe {
name: String,
@ -299,7 +257,8 @@ pub enum ProgramSection {
}
impl ProgramSection {
fn name(&self) -> &str {
/// Returns the program name
pub fn name(&self) -> &str {
match self {
ProgramSection::KRetProbe { name } => name,
ProgramSection::KProbe { name } => name,
@ -521,7 +480,8 @@ impl FromStr for ProgramSection {
}
impl Object {
pub(crate) fn parse(data: &[u8]) -> Result<Object, BpfError> {
/// Parses the binary data as an object file into an [Object]
pub fn parse(data: &[u8]) -> Result<Object, ParseError> {
let obj = object::read::File::parse(data).map_err(ParseError::ElfError)?;
let endianness = obj.endianness();
@ -604,6 +564,7 @@ impl Object {
}
}
/// Patches map data
pub fn patch_map_data(&mut self, globals: HashMap<&str, &[u8]>) -> Result<(), ParseError> {
let symbols: HashMap<String, &Symbol> = self
.symbols_by_index
@ -829,9 +790,9 @@ impl Object {
&mut self,
section: &Section,
symbols: HashMap<String, Symbol>,
) -> Result<(), BpfError> {
) -> Result<(), ParseError> {
if self.btf.is_none() {
return Err(BpfError::NoBTF);
return Err(ParseError::NoBTF);
}
let btf = self.btf.as_ref().unwrap();
@ -847,10 +808,8 @@ impl Object {
let (map_name, def) = parse_btf_map_def(btf, info)?;
let symbol_index = symbols
.get(&map_name)
.ok_or_else(|| {
BpfError::ParseError(ParseError::SymbolNotFound {
name: map_name.to_string(),
})
.ok_or_else(|| ParseError::SymbolNotFound {
name: map_name.to_string(),
})?
.index;
self.maps.insert(
@ -870,7 +829,7 @@ impl Object {
Ok(())
}
fn parse_section(&mut self, mut section: Section) -> Result<(), BpfError> {
fn parse_section(&mut self, mut section: Section) -> Result<(), ParseError> {
let mut parts = section.name.rsplitn(2, '/').collect::<Vec<_>>();
parts.reverse();
@ -945,10 +904,16 @@ impl Object {
}
}
#[derive(Debug, Clone, Error)]
/// Errors caught during parsing the object file
#[derive(Debug, Error)]
#[allow(missing_docs)]
pub enum ParseError {
#[error("error parsing ELF data")]
ElfError(#[from] object::read::Error),
ElfError(object::read::Error),
/// Error parsing BTF object
#[error("BTF error")]
BtfError(#[from] BtfError),
#[error("invalid license `{data:?}`: missing NULL terminator")]
MissingLicenseNullTerminator { data: Vec<u8> },
@ -962,8 +927,7 @@ pub enum ParseError {
#[error("error parsing section with index {index}")]
SectionError {
index: usize,
#[source]
source: object::read::Error,
error: object::read::Error,
},
#[error("unsupported relocation target")]
@ -1005,6 +969,10 @@ pub enum ParseError {
#[error("no symbols found for the maps included in the maps section")]
NoSymbolsInMapSection {},
/// No BTF parsed for object
#[error("no BTF parsed for object")]
NoBTF,
}
#[derive(Debug)]
@ -1064,9 +1032,9 @@ impl<'data, 'file, 'a> TryFrom<&'a ObjSection<'data, 'file>> for Section<'a> {
fn try_from(section: &'a ObjSection) -> Result<Section<'a>, ParseError> {
let index = section.index();
let map_err = |source| ParseError::SectionError {
let map_err = |error| ParseError::SectionError {
index: index.0,
source,
error,
};
let name = section.name().map_err(map_err)?;
let kind = match BpfSectionKind::from_name(name) {
@ -1166,9 +1134,12 @@ fn get_map_field(btf: &Btf, type_id: u32) -> Result<u32, BtfError> {
Ok(arr.len)
}
/// The parsed kernel version
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum KernelVersion {
/// Specified version
Version(u32),
/// Any version
Any,
}
@ -1311,7 +1282,8 @@ fn parse_btf_map_def(btf: &Btf, info: &DataSecEntry) -> Result<(String, BtfMapDe
Ok((map_name.to_string(), map_def))
}
pub(crate) fn parse_map_info(info: bpf_map_info, pinned: PinningType) -> Map {
/// Parses a [bpf_map_info] into a [Map].
pub fn parse_map_info(info: bpf_map_info, pinned: PinningType) -> Map {
if info.btf_key_type_id != 0 {
Map::Btf(BtfMap {
def: BtfMapDef {
@ -1350,7 +1322,8 @@ pub(crate) fn parse_map_info(info: bpf_map_info, pinned: PinningType) -> Map {
}
}
pub(crate) fn copy_instructions(data: &[u8]) -> Result<Vec<bpf_insn>, ParseError> {
/// Copies a block of eBPF instructions
pub fn copy_instructions(data: &[u8]) -> Result<Vec<bpf_insn>, ParseError> {
if data.len() % mem::size_of::<bpf_insn>() > 0 {
return Err(ParseError::InvalidProgramCode);
}
@ -1363,11 +1336,12 @@ pub(crate) fn copy_instructions(data: &[u8]) -> Result<Vec<bpf_insn>, ParseError
#[cfg(test)]
mod tests {
use alloc::vec;
use matches::assert_matches;
use object::Endianness;
use super::*;
use crate::PinningType;
use crate::maps::PinningType;
fn fake_section<'a>(kind: BpfSectionKind, name: &'a str, data: &'a [u8]) -> Section<'a> {
Section {
@ -1416,7 +1390,7 @@ mod tests {
fn test_parse_generic_error() {
assert!(matches!(
Object::parse(&b"foo"[..]),
Err(BpfError::ParseError(ParseError::ElfError(_)))
Err(ParseError::ElfError(_))
))
}
@ -1489,7 +1463,6 @@ mod tests {
map_flags: 5,
id: 0,
pinning: PinningType::None,
..Default::default()
};
assert_eq!(
@ -1508,7 +1481,6 @@ mod tests {
map_flags: 5,
id: 6,
pinning: PinningType::ByName,
..Default::default()
};
assert_eq!(parse_map_def("foo", bytes_of(&def)).unwrap(), def);
@ -1524,7 +1496,6 @@ mod tests {
map_flags: 5,
id: 6,
pinning: PinningType::ByName,
..Default::default()
};
let mut buf = [0u8; 128];
unsafe { ptr::write_unaligned(buf.as_mut_ptr() as *mut _, def) };
@ -1555,7 +1526,6 @@ mod tests {
map_flags: 5,
id: 0,
pinning: PinningType::None,
..Default::default()
})
),
"foo"
@ -1690,7 +1660,7 @@ mod tests {
buf.extend(&map_data);
buf.extend(&map_data);
// throw in some padding
buf.extend(&[0, 0, 0, 0]);
buf.extend([0, 0, 0, 0]);
buf.extend(&map_data);
assert_matches!(
obj.parse_section(fake_section(BpfSectionKind::Maps, "maps", buf.as_slice(),)),
@ -2224,7 +2194,6 @@ mod tests {
map_flags: BPF_F_RDONLY_PROG,
id: 1,
pinning: PinningType::None,
..Default::default()
},
section_index: 1,
symbol_index: 1,

@ -0,0 +1,48 @@
//! Cgroup socket programs.
use alloc::{borrow::ToOwned, string::String};
use crate::{
generated::bpf_attach_type,
thiserror::{self, Error},
};
/// Defines where to attach a `CgroupSock` program.
#[derive(Copy, Clone, Debug, Default)]
pub enum CgroupSockAttachType {
/// Called after the IPv4 bind events.
PostBind4,
/// Called after the IPv6 bind events.
PostBind6,
/// Attach to IPv4 connect events.
#[default]
SockCreate,
/// Attach to IPv6 connect events.
SockRelease,
}
impl From<CgroupSockAttachType> for bpf_attach_type {
fn from(s: CgroupSockAttachType) -> bpf_attach_type {
match s {
CgroupSockAttachType::PostBind4 => bpf_attach_type::BPF_CGROUP_INET4_POST_BIND,
CgroupSockAttachType::PostBind6 => bpf_attach_type::BPF_CGROUP_INET6_POST_BIND,
CgroupSockAttachType::SockCreate => bpf_attach_type::BPF_CGROUP_INET_SOCK_CREATE,
CgroupSockAttachType::SockRelease => bpf_attach_type::BPF_CGROUP_INET_SOCK_RELEASE,
}
}
}
#[derive(Debug, Error)]
#[error("{0} is not a valid attach type for a CGROUP_SOCK program")]
pub(crate) struct InvalidAttachType(String);
impl CgroupSockAttachType {
pub(crate) fn try_from(value: &str) -> Result<CgroupSockAttachType, InvalidAttachType> {
match value {
"post_bind4" => Ok(CgroupSockAttachType::PostBind4),
"post_bind6" => Ok(CgroupSockAttachType::PostBind6),
"sock_create" => Ok(CgroupSockAttachType::SockCreate),
"sock_release" => Ok(CgroupSockAttachType::SockRelease),
_ => Err(InvalidAttachType(value.to_owned())),
}
}
}

@ -0,0 +1,79 @@
//! Cgroup socket address programs.
use alloc::{borrow::ToOwned, string::String};
use crate::{
generated::bpf_attach_type,
thiserror::{self, Error},
};
/// Defines where to attach a `CgroupSockAddr` program.
#[derive(Copy, Clone, Debug)]
pub enum CgroupSockAddrAttachType {
/// Attach to IPv4 bind events.
Bind4,
/// Attach to IPv6 bind events.
Bind6,
/// Attach to IPv4 connect events.
Connect4,
/// Attach to IPv6 connect events.
Connect6,
/// Attach to IPv4 getpeername events.
GetPeerName4,
/// Attach to IPv6 getpeername events.
GetPeerName6,
/// Attach to IPv4 getsockname events.
GetSockName4,
/// Attach to IPv6 getsockname events.
GetSockName6,
/// Attach to IPv4 udp_sendmsg events.
UDPSendMsg4,
/// Attach to IPv6 udp_sendmsg events.
UDPSendMsg6,
/// Attach to IPv4 udp_recvmsg events.
UDPRecvMsg4,
/// Attach to IPv6 udp_recvmsg events.
UDPRecvMsg6,
}
impl From<CgroupSockAddrAttachType> for bpf_attach_type {
fn from(s: CgroupSockAddrAttachType) -> bpf_attach_type {
match s {
CgroupSockAddrAttachType::Bind4 => bpf_attach_type::BPF_CGROUP_INET4_BIND,
CgroupSockAddrAttachType::Bind6 => bpf_attach_type::BPF_CGROUP_INET6_BIND,
CgroupSockAddrAttachType::Connect4 => bpf_attach_type::BPF_CGROUP_INET4_CONNECT,
CgroupSockAddrAttachType::Connect6 => bpf_attach_type::BPF_CGROUP_INET6_CONNECT,
CgroupSockAddrAttachType::GetPeerName4 => bpf_attach_type::BPF_CGROUP_INET4_GETPEERNAME,
CgroupSockAddrAttachType::GetPeerName6 => bpf_attach_type::BPF_CGROUP_INET6_GETPEERNAME,
CgroupSockAddrAttachType::GetSockName4 => bpf_attach_type::BPF_CGROUP_INET4_GETSOCKNAME,
CgroupSockAddrAttachType::GetSockName6 => bpf_attach_type::BPF_CGROUP_INET6_GETSOCKNAME,
CgroupSockAddrAttachType::UDPSendMsg4 => bpf_attach_type::BPF_CGROUP_UDP4_SENDMSG,
CgroupSockAddrAttachType::UDPSendMsg6 => bpf_attach_type::BPF_CGROUP_UDP6_SENDMSG,
CgroupSockAddrAttachType::UDPRecvMsg4 => bpf_attach_type::BPF_CGROUP_UDP4_RECVMSG,
CgroupSockAddrAttachType::UDPRecvMsg6 => bpf_attach_type::BPF_CGROUP_UDP6_RECVMSG,
}
}
}
#[derive(Debug, Error)]
#[error("{0} is not a valid attach type for a CGROUP_SOCK_ADDR program")]
pub(crate) struct InvalidAttachType(String);
impl CgroupSockAddrAttachType {
pub(crate) fn try_from(value: &str) -> Result<CgroupSockAddrAttachType, InvalidAttachType> {
match value {
"bind4" => Ok(CgroupSockAddrAttachType::Bind4),
"bind6" => Ok(CgroupSockAddrAttachType::Bind6),
"connect4" => Ok(CgroupSockAddrAttachType::Connect4),
"connect6" => Ok(CgroupSockAddrAttachType::Connect6),
"getpeername4" => Ok(CgroupSockAddrAttachType::GetPeerName4),
"getpeername6" => Ok(CgroupSockAddrAttachType::GetPeerName6),
"getsockname4" => Ok(CgroupSockAddrAttachType::GetSockName4),
"getsockname6" => Ok(CgroupSockAddrAttachType::GetSockName6),
"sendmsg4" => Ok(CgroupSockAddrAttachType::UDPSendMsg4),
"sendmsg6" => Ok(CgroupSockAddrAttachType::UDPSendMsg6),
"recvmsg4" => Ok(CgroupSockAddrAttachType::UDPRecvMsg4),
"recvmsg6" => Ok(CgroupSockAddrAttachType::UDPRecvMsg6),
_ => Err(InvalidAttachType(value.to_owned())),
}
}
}

@ -0,0 +1,39 @@
//! Cgroup socket option programs.
use alloc::{borrow::ToOwned, string::String};
use crate::{
generated::bpf_attach_type,
thiserror::{self, Error},
};
/// Defines where to attach a `CgroupSockopt` program.
#[derive(Copy, Clone, Debug)]
pub enum CgroupSockoptAttachType {
/// Attach to GetSockopt.
Get,
/// Attach to SetSockopt.
Set,
}
impl From<CgroupSockoptAttachType> for bpf_attach_type {
fn from(s: CgroupSockoptAttachType) -> bpf_attach_type {
match s {
CgroupSockoptAttachType::Get => bpf_attach_type::BPF_CGROUP_GETSOCKOPT,
CgroupSockoptAttachType::Set => bpf_attach_type::BPF_CGROUP_SETSOCKOPT,
}
}
}
#[derive(Debug, Error)]
#[error("{0} is not a valid attach type for a CGROUP_SOCKOPT program")]
pub(crate) struct InvalidAttachType(String);
impl CgroupSockoptAttachType {
pub(crate) fn try_from(value: &str) -> Result<CgroupSockoptAttachType, InvalidAttachType> {
match value {
"getsockopt" => Ok(CgroupSockoptAttachType::Get),
"setsockopt" => Ok(CgroupSockoptAttachType::Set),
_ => Err(InvalidAttachType(value.to_owned())),
}
}
}

@ -0,0 +1,9 @@
//! Program struct and type bindings.
pub mod cgroup_sock;
pub mod cgroup_sock_addr;
pub mod cgroup_sockopt;
pub use cgroup_sock::CgroupSockAttachType;
pub use cgroup_sock_addr::CgroupSockAddrAttachType;
pub use cgroup_sockopt::CgroupSockoptAttachType;

@ -1,43 +1,81 @@
use std::{collections::HashMap, mem};
//! Program relocation handling.
use core::mem;
use alloc::{borrow::ToOwned, string::String};
use log::debug;
use object::{SectionIndex, SymbolKind};
use thiserror::Error;
use crate::{
generated::{
bpf_insn, BPF_CALL, BPF_JMP, BPF_K, BPF_PSEUDO_CALL, BPF_PSEUDO_FUNC, BPF_PSEUDO_MAP_FD,
BPF_PSEUDO_MAP_VALUE,
},
maps::MapData,
maps::Map,
obj::{Function, Object, Program},
BpfError,
thiserror::{self, Error},
util::HashMap,
};
pub(crate) const INS_SIZE: usize = mem::size_of::<bpf_insn>();
/// The error type returned by [`Object::relocate_maps`] and [`Object::relocate_calls`]
#[derive(Error, Debug)]
#[error("error relocating `{function}`")]
pub struct BpfRelocationError {
/// The function name
function: String,
#[source]
/// The original error
error: RelocationError,
}
/// Relocation failures
#[derive(Debug, Error)]
enum RelocationError {
pub enum RelocationError {
/// Unknown symbol
#[error("unknown symbol, index `{index}`")]
UnknownSymbol { index: usize },
UnknownSymbol {
/// The symbol index
index: usize,
},
/// Section not found
#[error("section `{section_index}` not found, referenced by symbol `{}` #{symbol_index}",
.symbol_name.clone().unwrap_or_default())]
SectionNotFound {
/// The section index
section_index: usize,
/// The symbol index
symbol_index: usize,
/// The symbol name
symbol_name: Option<String>,
},
/// Unknown function
#[error("function {address:#x} not found while relocating `{caller_name}`")]
UnknownFunction { address: u64, caller_name: String },
UnknownFunction {
/// The function address
address: u64,
/// The caller name
caller_name: String,
},
/// Referenced map not created yet
#[error("the map `{name}` at section `{section_index}` has not been created")]
MapNotCreated { section_index: usize, name: String },
MapNotCreated {
/// The section index
section_index: usize,
/// The map name
name: String,
},
/// Invalid relocation offset
#[error("invalid offset `{offset}` applying relocation #{relocation_number}")]
InvalidRelocationOffset {
/// The relocation offset
offset: u64,
/// The relocation number
relocation_number: usize,
},
}
@ -62,16 +100,17 @@ pub(crate) struct Symbol {
}
impl Object {
pub fn relocate_maps(&mut self, maps: &HashMap<String, MapData>) -> Result<(), BpfError> {
let maps_by_section = maps
.iter()
.map(|(name, map)| (map.obj.section_index(), (name.as_str(), map)))
.collect::<HashMap<_, _>>();
let maps_by_symbol = maps
.iter()
.map(|(name, map)| (map.obj.symbol_index(), (name.as_str(), map)))
.collect::<HashMap<_, _>>();
/// Relocates the map references
pub fn relocate_maps<'a, I: Iterator<Item = (&'a str, Option<i32>, &'a Map)>>(
&mut self,
maps: I,
) -> Result<(), BpfRelocationError> {
let mut maps_by_section = HashMap::new();
let mut maps_by_symbol = HashMap::new();
for (name, fd, map) in maps {
maps_by_section.insert(map.section_index(), (name, fd, map));
maps_by_symbol.insert(map.symbol_index(), (name, fd, map));
}
let functions = self
.programs
@ -89,9 +128,9 @@ impl Object {
&self.symbols_by_index,
self.text_section_index,
)
.map_err(|error| BpfError::RelocationError {
.map_err(|error| BpfRelocationError {
function: function.name.clone(),
error: Box::new(error),
error,
})?;
}
}
@ -99,7 +138,8 @@ impl Object {
Ok(())
}
pub fn relocate_calls(&mut self) -> Result<(), BpfError> {
/// Relocates function calls
pub fn relocate_calls(&mut self) -> Result<(), BpfRelocationError> {
for (name, program) in self.programs.iter_mut() {
let linker = FunctionLinker::new(
self.text_section_index,
@ -107,12 +147,10 @@ impl Object {
&self.relocations,
&self.symbols_by_index,
);
linker
.link(program)
.map_err(|error| BpfError::RelocationError {
function: name.clone(),
error: Box::new(error),
})?;
linker.link(program).map_err(|error| BpfRelocationError {
function: name.to_owned(),
error,
})?;
}
Ok(())
@ -122,8 +160,8 @@ impl Object {
fn relocate_maps<'a, I: Iterator<Item = &'a Relocation>>(
fun: &mut Function,
relocations: I,
maps_by_section: &HashMap<usize, (&str, &MapData)>,
maps_by_symbol: &HashMap<usize, (&str, &MapData)>,
maps_by_section: &HashMap<usize, (&str, Option<i32>, &Map)>,
maps_by_symbol: &HashMap<usize, (&str, Option<i32>, &Map)>,
symbol_table: &HashMap<usize, Symbol>,
text_section_index: Option<usize>,
) -> Result<(), RelocationError> {
@ -166,7 +204,7 @@ fn relocate_maps<'a, I: Iterator<Item = &'a Relocation>>(
continue;
}
let (name, map) = if maps_by_symbol.contains_key(&rel.symbol_index) {
let (name, fd, map) = if maps_by_symbol.contains_key(&rel.symbol_index) {
maps_by_symbol
.get(&rel.symbol_index)
.ok_or(RelocationError::SectionNotFound {
@ -184,12 +222,12 @@ fn relocate_maps<'a, I: Iterator<Item = &'a Relocation>>(
})?
};
let map_fd = map.fd.ok_or_else(|| RelocationError::MapNotCreated {
let map_fd = fd.ok_or_else(|| RelocationError::MapNotCreated {
name: (*name).into(),
section_index,
})?;
if !map.obj.data().is_empty() {
if !map.data().is_empty() {
instructions[ins_index].set_src_reg(BPF_PSEUDO_MAP_VALUE as u8);
instructions[ins_index + 1].imm = instructions[ins_index].imm + sym.address as i32;
} else {
@ -436,12 +474,9 @@ fn insn_is_call(ins: &bpf_insn) -> bool {
#[cfg(test)]
mod test {
use crate::{
bpf_map_def,
maps::MapData,
obj::{self, BtfMap, LegacyMap, MapKind},
BtfMapDef,
};
use alloc::{string::ToString, vec, vec::Vec};
use crate::maps::{bpf_map_def, BtfMap, BtfMapDef, LegacyMap, Map, MapKind};
use super::*;
@ -458,41 +493,31 @@ mod test {
}
fn ins(bytes: &[u8]) -> bpf_insn {
unsafe { std::ptr::read_unaligned(bytes.as_ptr() as *const _) }
unsafe { core::ptr::read_unaligned(bytes.as_ptr() as *const _) }
}
fn fake_legacy_map(fd: i32, symbol_index: usize) -> MapData {
MapData {
obj: obj::Map::Legacy(LegacyMap {
def: bpf_map_def {
..Default::default()
},
section_index: 0,
symbol_index,
data: Vec::new(),
kind: MapKind::Other,
}),
fd: Some(fd),
btf_fd: None,
pinned: false,
}
fn fake_legacy_map(symbol_index: usize) -> Map {
Map::Legacy(LegacyMap {
def: bpf_map_def {
..Default::default()
},
section_index: 0,
symbol_index,
data: Vec::new(),
kind: MapKind::Other,
})
}
fn fake_btf_map(fd: i32, symbol_index: usize) -> MapData {
MapData {
obj: obj::Map::Btf(BtfMap {
def: BtfMapDef {
..Default::default()
},
section_index: 0,
symbol_index,
data: Vec::new(),
kind: MapKind::Other,
}),
fd: Some(fd),
btf_fd: None,
pinned: false,
}
fn fake_btf_map(symbol_index: usize) -> Map {
Map::Btf(BtfMap {
def: BtfMapDef {
..Default::default()
},
section_index: 0,
symbol_index,
data: Vec::new(),
kind: MapKind::Other,
})
}
fn fake_func(name: &str, instructions: Vec<bpf_insn>) -> Function {
@ -527,8 +552,8 @@ mod test {
}];
let maps_by_section = HashMap::new();
let map = fake_legacy_map(1, 1);
let maps_by_symbol = HashMap::from([(1, ("test_map", &map))]);
let map = fake_legacy_map(1);
let maps_by_symbol = HashMap::from([(1, ("test_map", Some(1), &map))]);
relocate_maps(
&mut fun,
@ -579,10 +604,12 @@ mod test {
];
let maps_by_section = HashMap::new();
let map_1 = fake_legacy_map(1, 1);
let map_2 = fake_legacy_map(2, 2);
let maps_by_symbol =
HashMap::from([(1, ("test_map_1", &map_1)), (2, ("test_map_2", &map_2))]);
let map_1 = fake_legacy_map(1);
let map_2 = fake_legacy_map(2);
let maps_by_symbol = HashMap::from([
(1, ("test_map_1", Some(1), &map_1)),
(2, ("test_map_2", Some(2), &map_2)),
]);
relocate_maps(
&mut fun,
@ -622,8 +649,8 @@ mod test {
}];
let maps_by_section = HashMap::new();
let map = fake_btf_map(1, 1);
let maps_by_symbol = HashMap::from([(1, ("test_map", &map))]);
let map = fake_btf_map(1);
let maps_by_symbol = HashMap::from([(1, ("test_map", Some(1), &map))]);
relocate_maps(
&mut fun,
@ -674,10 +701,12 @@ mod test {
];
let maps_by_section = HashMap::new();
let map_1 = fake_btf_map(1, 1);
let map_2 = fake_btf_map(2, 2);
let maps_by_symbol =
HashMap::from([(1, ("test_map_1", &map_1)), (2, ("test_map_2", &map_2))]);
let map_1 = fake_btf_map(1);
let map_2 = fake_btf_map(2);
let maps_by_symbol = HashMap::from([
(1, ("test_map_1", Some(1), &map_1)),
(2, ("test_map_2", Some(2), &map_2)),
]);
relocate_maps(
&mut fun,

@ -0,0 +1,12 @@
use core::{mem, slice};
#[cfg(feature = "no_std")]
pub(crate) use hashbrown::HashMap;
#[cfg(not(feature = "no_std"))]
pub(crate) use std::collections::HashMap;
/// bytes_of converts a <T> to a byte slice
pub(crate) unsafe fn bytes_of<T>(val: &T) -> &[u8] {
let size = mem::size_of::<T>();
slice::from_raw_parts(slice::from_ref(val).as_ptr().cast(), size)
}

@ -2,6 +2,7 @@ use bindgen::{self, Builder, EnumVariation};
pub fn user_builder() -> Builder {
bindgen::builder()
.use_core()
.layout_tests(false)
.generate_comments(false)
.prepend_enum_name(false)

@ -76,7 +76,7 @@ pub fn generate<T: AsRef<str>>(
let output = Command::new("bindgen")
.arg(file_path)
.args(&flags)
.args(flags)
.output()
.map_err(Error::Bindgen)?;

@ -12,13 +12,14 @@ edition = "2021"
[dependencies]
libc = { version = "0.2.105" }
aya-obj = { path = "../aya-obj", version = "0.1.0" }
thiserror = "1"
object = { version = "0.30", default-features = false, features = ["std", "read_core", "elf"] }
bitflags = "1.2.1"
bytes = "1"
lazy_static = "1"
parking_lot = { version = "0.12.0", features = ["send_guard"] }
tokio = { version = "1.2.0", features = ["macros", "rt", "rt-multi-thread", "net"], optional = true }
tokio = { version = "1.24.0", features = ["macros", "rt", "rt-multi-thread", "net"], optional = true }
async-io = { version = "1.3", optional = true }
log = "0.4"

@ -1,13 +1,16 @@
use std::{
borrow::Cow,
collections::{HashMap, HashSet},
error::Error,
ffi::CString,
fs, io,
os::{raw::c_int, unix::io::RawFd},
path::{Path, PathBuf},
};
use aya_obj::{
btf::{BtfFeatures, BtfRelocationError},
relocation::BpfRelocationError,
};
use log::debug;
use thiserror::Error;
@ -19,7 +22,8 @@ use crate::{
maps::{Map, MapData, MapError},
obj::{
btf::{Btf, BtfError},
MapKind, Object, ParseError, ProgramSection,
maps::MapKind,
Object, ParseError, ProgramSection,
},
programs::{
BtfTracePoint, CgroupDevice, CgroupSkb, CgroupSkbAttachType, CgroupSock, CgroupSockAddr,
@ -58,75 +62,13 @@ unsafe_impl_pod!(i8, u8, i16, u16, i32, u32, i64, u64, u128, i128);
// It only makes sense that an array of POD types is itself POD
unsafe impl<T: Pod, const N: usize> Pod for [T; N] {}
#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub(crate) struct bpf_map_def {
// minimum features required by old BPF programs
pub(crate) map_type: u32,
pub(crate) key_size: u32,
pub(crate) value_size: u32,
pub(crate) max_entries: u32,
pub(crate) map_flags: u32,
// optional features
pub(crate) id: u32,
pub(crate) pinning: PinningType,
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub(crate) struct BtfMapDef {
pub(crate) map_type: u32,
pub(crate) key_size: u32,
pub(crate) value_size: u32,
pub(crate) max_entries: u32,
pub(crate) map_flags: u32,
pub(crate) pinning: PinningType,
pub(crate) btf_key_type_id: u32,
pub(crate) btf_value_type_id: u32,
}
#[repr(u32)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) enum PinningType {
None = 0,
ByName = 1,
}
#[derive(Debug, Error)]
pub(crate) enum PinningError {
#[error("unsupported pinning type")]
Unsupported,
}
impl TryFrom<u32> for PinningType {
type Error = PinningError;
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
0 => Ok(PinningType::None),
1 => Ok(PinningType::ByName),
_ => Err(PinningError::Unsupported),
}
}
}
impl Default for PinningType {
fn default() -> Self {
PinningType::None
}
}
pub use aya_obj::maps::{bpf_map_def, PinningType};
// Features implements BPF and BTF feature detection
#[derive(Default, Debug)]
pub(crate) struct Features {
pub bpf_name: bool,
pub btf: bool,
pub btf_func: bool,
pub btf_func_global: bool,
pub btf_datasec: bool,
pub btf_float: bool,
pub btf_decl_tag: bool,
pub btf_type_tag: bool,
pub btf: Option<BtfFeatures>,
}
impl Features {
@ -134,33 +76,37 @@ impl Features {
self.bpf_name = is_prog_name_supported();
debug!("[FEAT PROBE] BPF program name support: {}", self.bpf_name);
self.btf = is_btf_supported();
debug!("[FEAT PROBE] BTF support: {}", self.btf);
self.btf = if is_btf_supported() {
Some(BtfFeatures::default())
} else {
None
};
debug!("[FEAT PROBE] BTF support: {}", self.btf.is_some());
if self.btf {
self.btf_func = is_btf_func_supported();
debug!("[FEAT PROBE] BTF func support: {}", self.btf_func);
if let Some(ref mut btf) = self.btf {
btf.btf_func = is_btf_func_supported();
debug!("[FEAT PROBE] BTF func support: {}", btf.btf_func);
self.btf_func_global = is_btf_func_global_supported();
btf.btf_func_global = is_btf_func_global_supported();
debug!(
"[FEAT PROBE] BTF global func support: {}",
self.btf_func_global
btf.btf_func_global
);
self.btf_datasec = is_btf_datasec_supported();
btf.btf_datasec = is_btf_datasec_supported();
debug!(
"[FEAT PROBE] BTF var and datasec support: {}",
self.btf_datasec
btf.btf_datasec
);
self.btf_float = is_btf_float_supported();
debug!("[FEAT PROBE] BTF float support: {}", self.btf_float);
btf.btf_float = is_btf_float_supported();
debug!("[FEAT PROBE] BTF float support: {}", btf.btf_float);
self.btf_decl_tag = is_btf_decl_tag_supported();
debug!("[FEAT PROBE] BTF decl_tag support: {}", self.btf_decl_tag);
btf.btf_decl_tag = is_btf_decl_tag_supported();
debug!("[FEAT PROBE] BTF decl_tag support: {}", btf.btf_decl_tag);
self.btf_type_tag = is_btf_type_tag_supported();
debug!("[FEAT PROBE] BTF type_tag support: {}", self.btf_type_tag);
btf.btf_type_tag = is_btf_type_tag_supported();
debug!("[FEAT PROBE] BTF type_tag support: {}", btf.btf_type_tag);
}
}
}
@ -413,15 +359,10 @@ impl<'a> BpfLoader<'a> {
let mut obj = Object::parse(data)?;
obj.patch_map_data(self.globals.clone())?;
let btf_fd = if self.features.btf {
if let Some(ref mut obj_btf) = obj.btf {
// fixup btf
let section_data = obj.section_sizes.clone();
let symbol_offsets = obj.symbol_offset_by_name.clone();
obj_btf.fixup_and_sanitize(&section_data, &symbol_offsets, &self.features)?;
let btf_fd = if let Some(ref btf) = self.features.btf {
if let Some(btf) = obj.fixup_and_sanitize_btf(btf)? {
// load btf to the kernel
let raw_btf = obj_btf.to_bytes();
Some(load_btf(raw_btf)?)
Some(load_btf(btf.to_bytes())?)
} else {
None
}
@ -497,7 +438,10 @@ impl<'a> BpfLoader<'a> {
maps.insert(name, map);
}
obj.relocate_maps(&maps)?;
obj.relocate_maps(
maps.iter()
.map(|(s, data)| (s.as_str(), data.fd, &data.obj)),
)?;
obj.relocate_calls()?;
let programs = obj
@ -655,7 +599,10 @@ impl<'a> BpfLoader<'a> {
fn parse_map(data: (String, MapData)) -> Result<(String, Map), BpfError> {
let name = data.0;
let map = data.1;
let map_type = bpf_map_type::try_from(map.obj.map_type())?;
let map_type =
bpf_map_type::try_from(map.obj.map_type()).map_err(|e| MapError::InvalidMapType {
map_type: e.map_type,
})?;
let map = match map_type {
BPF_MAP_TYPE_ARRAY => Ok(Map::Array(map)),
BPF_MAP_TYPE_PERCPU_ARRAY => Ok(Map::PerCpuArray(map)),
@ -910,32 +857,30 @@ pub enum BpfError {
},
/// Error parsing BPF object
#[error("error parsing BPF object")]
#[error("error parsing BPF object: {0}")]
ParseError(#[from] ParseError),
/// Error parsing BTF object
#[error("BTF error")]
#[error("BTF error: {0}")]
BtfError(#[from] BtfError),
/// Error performing relocations
#[error("error relocating `{function}`")]
RelocationError {
/// The function name
function: String,
#[source]
/// The original error
error: Box<dyn Error + Send + Sync>,
},
#[error("error relocating function")]
RelocationError(#[from] BpfRelocationError),
/// Error performing relocations
#[error("error relocating section")]
BtfRelocationError(#[from] BtfRelocationError),
/// No BTF parsed for object
#[error("no BTF parsed for object")]
NoBTF,
#[error("map error")]
#[error("map error: {0}")]
/// A map error
MapError(#[from] MapError),
#[error("program error")]
#[error("program error: {0}")]
/// A program error
ProgramError(#[from] ProgramError),
}

@ -46,9 +46,9 @@ extern crate lazy_static;
extern crate bitflags;
mod bpf;
mod generated;
use aya_obj::generated;
pub mod maps;
mod obj;
use aya_obj as obj;
pub mod pin;
pub mod programs;
mod sys;

@ -84,14 +84,17 @@ mod tests {
bpf_map_type::{BPF_MAP_TYPE_BLOOM_FILTER, BPF_MAP_TYPE_PERF_EVENT_ARRAY},
},
maps::{Map, MapData},
obj,
obj::{
self,
maps::{LegacyMap, MapKind},
},
sys::{override_syscall, SysResult, Syscall},
};
use libc::{EFAULT, ENOENT};
use std::io;
fn new_obj_map() -> obj::Map {
obj::Map::Legacy(obj::LegacyMap {
obj::Map::Legacy(LegacyMap {
def: bpf_map_def {
map_type: BPF_MAP_TYPE_BLOOM_FILTER as u32,
key_size: 4,
@ -102,7 +105,7 @@ mod tests {
section_index: 0,
symbol_index: 0,
data: Vec::new(),
kind: obj::MapKind::Other,
kind: MapKind::Other,
})
}
@ -130,7 +133,7 @@ mod tests {
#[test]
fn test_try_from_wrong_map() {
let map_data = MapData {
obj: obj::Map::Legacy(obj::LegacyMap {
obj: obj::Map::Legacy(LegacyMap {
def: bpf_map_def {
map_type: BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32,
key_size: 4,
@ -141,7 +144,7 @@ mod tests {
section_index: 0,
symbol_index: 0,
data: Vec::new(),
kind: obj::MapKind::Other,
kind: MapKind::Other,
}),
fd: None,
pinned: false,

@ -117,14 +117,17 @@ mod tests {
bpf_map_type::{BPF_MAP_TYPE_HASH, BPF_MAP_TYPE_LRU_HASH},
},
maps::{Map, MapData},
obj,
obj::{
self,
maps::{LegacyMap, MapKind},
},
sys::{override_syscall, SysResult, Syscall},
};
use super::*;
fn new_obj_map() -> obj::Map {
obj::Map::Legacy(obj::LegacyMap {
obj::Map::Legacy(LegacyMap {
def: bpf_map_def {
map_type: BPF_MAP_TYPE_HASH as u32,
key_size: 4,
@ -134,7 +137,7 @@ mod tests {
},
section_index: 0,
data: Vec::new(),
kind: obj::MapKind::Other,
kind: MapKind::Other,
symbol_index: 0,
})
}
@ -255,7 +258,7 @@ mod tests {
#[test]
fn test_try_from_ok_lru() {
let map_data = MapData {
obj: obj::Map::Legacy(obj::LegacyMap {
obj: obj::Map::Legacy(LegacyMap {
def: bpf_map_def {
map_type: BPF_MAP_TYPE_LRU_HASH as u32,
key_size: 4,
@ -266,7 +269,7 @@ mod tests {
section_index: 0,
symbol_index: 0,
data: Vec::new(),
kind: obj::MapKind::Other,
kind: MapKind::Other,
}),
fd: Some(42),
pinned: false,

@ -247,14 +247,17 @@ mod tests {
bpf_map_type::{BPF_MAP_TYPE_LPM_TRIE, BPF_MAP_TYPE_PERF_EVENT_ARRAY},
},
maps::{Map, MapData},
obj,
obj::{
self,
maps::{LegacyMap, MapKind},
},
sys::{override_syscall, SysResult, Syscall},
};
use libc::{EFAULT, ENOENT};
use std::{io, mem, net::Ipv4Addr};
fn new_obj_map() -> obj::Map {
obj::Map::Legacy(obj::LegacyMap {
obj::Map::Legacy(LegacyMap {
def: bpf_map_def {
map_type: BPF_MAP_TYPE_LPM_TRIE as u32,
key_size: mem::size_of::<Key<u32>>() as u32,
@ -265,7 +268,7 @@ mod tests {
section_index: 0,
symbol_index: 0,
data: Vec::new(),
kind: obj::MapKind::Other,
kind: MapKind::Other,
})
}
@ -310,7 +313,7 @@ mod tests {
#[test]
fn test_try_from_wrong_map() {
let map_data = MapData {
obj: obj::Map::Legacy(obj::LegacyMap {
obj: obj::Map::Legacy(LegacyMap {
def: bpf_map_def {
map_type: BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32,
key_size: 4,
@ -321,7 +324,7 @@ mod tests {
section_index: 0,
symbol_index: 0,
data: Vec::new(),
kind: obj::MapKind::Other,
kind: MapKind::Other,
}),
fd: None,
btf_fd: None,

@ -53,7 +53,6 @@ use log::warn;
use thiserror::Error;
use crate::{
generated::bpf_map_type,
obj::{self, parse_map_info},
pin::PinError,
sys::{
@ -739,50 +738,6 @@ impl<K: Pod, V, I: IterableMap<K, V>> Iterator for MapIter<'_, K, V, I> {
}
}
impl TryFrom<u32> for bpf_map_type {
type Error = MapError;
fn try_from(map_type: u32) -> Result<Self, Self::Error> {
use bpf_map_type::*;
Ok(match map_type {
x if x == BPF_MAP_TYPE_UNSPEC as u32 => BPF_MAP_TYPE_UNSPEC,
x if x == BPF_MAP_TYPE_HASH as u32 => BPF_MAP_TYPE_HASH,
x if x == BPF_MAP_TYPE_ARRAY as u32 => BPF_MAP_TYPE_ARRAY,
x if x == BPF_MAP_TYPE_PROG_ARRAY as u32 => BPF_MAP_TYPE_PROG_ARRAY,
x if x == BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32 => BPF_MAP_TYPE_PERF_EVENT_ARRAY,
x if x == BPF_MAP_TYPE_PERCPU_HASH as u32 => BPF_MAP_TYPE_PERCPU_HASH,
x if x == BPF_MAP_TYPE_PERCPU_ARRAY as u32 => BPF_MAP_TYPE_PERCPU_ARRAY,
x if x == BPF_MAP_TYPE_STACK_TRACE as u32 => BPF_MAP_TYPE_STACK_TRACE,
x if x == BPF_MAP_TYPE_CGROUP_ARRAY as u32 => BPF_MAP_TYPE_CGROUP_ARRAY,
x if x == BPF_MAP_TYPE_LRU_HASH as u32 => BPF_MAP_TYPE_LRU_HASH,
x if x == BPF_MAP_TYPE_LRU_PERCPU_HASH as u32 => BPF_MAP_TYPE_LRU_PERCPU_HASH,
x if x == BPF_MAP_TYPE_LPM_TRIE as u32 => BPF_MAP_TYPE_LPM_TRIE,
x if x == BPF_MAP_TYPE_BLOOM_FILTER as u32 => BPF_MAP_TYPE_BLOOM_FILTER,
x if x == BPF_MAP_TYPE_ARRAY_OF_MAPS as u32 => BPF_MAP_TYPE_ARRAY_OF_MAPS,
x if x == BPF_MAP_TYPE_HASH_OF_MAPS as u32 => BPF_MAP_TYPE_HASH_OF_MAPS,
x if x == BPF_MAP_TYPE_DEVMAP as u32 => BPF_MAP_TYPE_DEVMAP,
x if x == BPF_MAP_TYPE_SOCKMAP as u32 => BPF_MAP_TYPE_SOCKMAP,
x if x == BPF_MAP_TYPE_CPUMAP as u32 => BPF_MAP_TYPE_CPUMAP,
x if x == BPF_MAP_TYPE_XSKMAP as u32 => BPF_MAP_TYPE_XSKMAP,
x if x == BPF_MAP_TYPE_SOCKHASH as u32 => BPF_MAP_TYPE_SOCKHASH,
x if x == BPF_MAP_TYPE_CGROUP_STORAGE as u32 => BPF_MAP_TYPE_CGROUP_STORAGE,
x if x == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY as u32 => BPF_MAP_TYPE_REUSEPORT_SOCKARRAY,
x if x == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE as u32 => {
BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE
}
x if x == BPF_MAP_TYPE_QUEUE as u32 => BPF_MAP_TYPE_QUEUE,
x if x == BPF_MAP_TYPE_STACK as u32 => BPF_MAP_TYPE_STACK,
x if x == BPF_MAP_TYPE_SK_STORAGE as u32 => BPF_MAP_TYPE_SK_STORAGE,
x if x == BPF_MAP_TYPE_DEVMAP_HASH as u32 => BPF_MAP_TYPE_DEVMAP_HASH,
x if x == BPF_MAP_TYPE_STRUCT_OPS as u32 => BPF_MAP_TYPE_STRUCT_OPS,
x if x == BPF_MAP_TYPE_RINGBUF as u32 => BPF_MAP_TYPE_RINGBUF,
x if x == BPF_MAP_TYPE_INODE_STORAGE as u32 => BPF_MAP_TYPE_INODE_STORAGE,
x if x == BPF_MAP_TYPE_TASK_STORAGE as u32 => BPF_MAP_TYPE_TASK_STORAGE,
_ => return Err(MapError::InvalidMapType { map_type }),
})
}
}
pub(crate) struct PerCpuKernelMem {
bytes: Vec<u8>,
}
@ -889,14 +844,14 @@ mod tests {
bpf_map_def,
generated::{bpf_cmd, bpf_map_type::BPF_MAP_TYPE_HASH},
maps::MapData,
obj::MapKind,
obj::maps::{LegacyMap, MapKind},
sys::{override_syscall, Syscall},
};
use super::*;
fn new_obj_map() -> obj::Map {
obj::Map::Legacy(obj::LegacyMap {
obj::Map::Legacy(LegacyMap {
def: bpf_map_def {
map_type: BPF_MAP_TYPE_HASH as u32,
key_size: 4,

@ -1,10 +0,0 @@
#[allow(clippy::module_inception)]
mod btf;
mod info;
mod relocation;
mod types;
pub use btf::*;
pub(crate) use info::*;
pub use relocation::RelocationError;
pub(crate) use types::*;

@ -1,7 +1,6 @@
//! Cgroup socket programs.
use thiserror::Error;
pub use aya_obj::programs::CgroupSockAttachType;
use crate::generated::bpf_attach_type;
use std::{
hash::Hash,
os::unix::prelude::{AsRawFd, RawFd},
@ -154,51 +153,3 @@ define_link_wrapper!(
CgroupSockLinkInner,
CgroupSockLinkIdInner
);
/// Defines where to attach a [`CgroupSock`] program.
#[derive(Copy, Clone, Debug)]
pub enum CgroupSockAttachType {
/// Called after the IPv4 bind events.
PostBind4,
/// Called after the IPv6 bind events.
PostBind6,
/// Attach to IPv4 connect events.
SockCreate,
/// Attach to IPv6 connect events.
SockRelease,
}
impl Default for CgroupSockAttachType {
// The kernel checks for a 0 attach_type and sets it to sock_create
// We may as well do that here also
fn default() -> Self {
CgroupSockAttachType::SockCreate
}
}
impl From<CgroupSockAttachType> for bpf_attach_type {
fn from(s: CgroupSockAttachType) -> bpf_attach_type {
match s {
CgroupSockAttachType::PostBind4 => bpf_attach_type::BPF_CGROUP_INET4_POST_BIND,
CgroupSockAttachType::PostBind6 => bpf_attach_type::BPF_CGROUP_INET6_POST_BIND,
CgroupSockAttachType::SockCreate => bpf_attach_type::BPF_CGROUP_INET_SOCK_CREATE,
CgroupSockAttachType::SockRelease => bpf_attach_type::BPF_CGROUP_INET_SOCK_RELEASE,
}
}
}
#[derive(Debug, Error)]
#[error("{0} is not a valid attach type for a CGROUP_SOCK program")]
pub(crate) struct InvalidAttachType(String);
impl CgroupSockAttachType {
pub(crate) fn try_from(value: &str) -> Result<CgroupSockAttachType, InvalidAttachType> {
match value {
"post_bind4" => Ok(CgroupSockAttachType::PostBind4),
"post_bind6" => Ok(CgroupSockAttachType::PostBind6),
"sock_create" => Ok(CgroupSockAttachType::SockCreate),
"sock_release" => Ok(CgroupSockAttachType::SockRelease),
_ => Err(InvalidAttachType(value.to_owned())),
}
}
}

@ -1,7 +1,6 @@
//! Cgroup socket address programs.
use thiserror::Error;
pub use aya_obj::programs::CgroupSockAddrAttachType;
use crate::generated::bpf_attach_type;
use std::{
hash::Hash,
os::unix::prelude::{AsRawFd, RawFd},
@ -160,75 +159,3 @@ define_link_wrapper!(
CgroupSockAddrLinkInner,
CgroupSockAddrLinkIdInner
);
/// Defines where to attach a [`CgroupSockAddr`] program.
#[derive(Copy, Clone, Debug)]
pub enum CgroupSockAddrAttachType {
/// Attach to IPv4 bind events.
Bind4,
/// Attach to IPv6 bind events.
Bind6,
/// Attach to IPv4 connect events.
Connect4,
/// Attach to IPv6 connect events.
Connect6,
/// Attach to IPv4 getpeername events.
GetPeerName4,
/// Attach to IPv6 getpeername events.
GetPeerName6,
/// Attach to IPv4 getsockname events.
GetSockName4,
/// Attach to IPv6 getsockname events.
GetSockName6,
/// Attach to IPv4 udp_sendmsg events.
UDPSendMsg4,
/// Attach to IPv6 udp_sendmsg events.
UDPSendMsg6,
/// Attach to IPv4 udp_recvmsg events.
UDPRecvMsg4,
/// Attach to IPv6 udp_recvmsg events.
UDPRecvMsg6,
}
impl From<CgroupSockAddrAttachType> for bpf_attach_type {
fn from(s: CgroupSockAddrAttachType) -> bpf_attach_type {
match s {
CgroupSockAddrAttachType::Bind4 => bpf_attach_type::BPF_CGROUP_INET4_BIND,
CgroupSockAddrAttachType::Bind6 => bpf_attach_type::BPF_CGROUP_INET6_BIND,
CgroupSockAddrAttachType::Connect4 => bpf_attach_type::BPF_CGROUP_INET4_CONNECT,
CgroupSockAddrAttachType::Connect6 => bpf_attach_type::BPF_CGROUP_INET6_CONNECT,
CgroupSockAddrAttachType::GetPeerName4 => bpf_attach_type::BPF_CGROUP_INET4_GETPEERNAME,
CgroupSockAddrAttachType::GetPeerName6 => bpf_attach_type::BPF_CGROUP_INET6_GETPEERNAME,
CgroupSockAddrAttachType::GetSockName4 => bpf_attach_type::BPF_CGROUP_INET4_GETSOCKNAME,
CgroupSockAddrAttachType::GetSockName6 => bpf_attach_type::BPF_CGROUP_INET6_GETSOCKNAME,
CgroupSockAddrAttachType::UDPSendMsg4 => bpf_attach_type::BPF_CGROUP_UDP4_SENDMSG,
CgroupSockAddrAttachType::UDPSendMsg6 => bpf_attach_type::BPF_CGROUP_UDP6_SENDMSG,
CgroupSockAddrAttachType::UDPRecvMsg4 => bpf_attach_type::BPF_CGROUP_UDP4_RECVMSG,
CgroupSockAddrAttachType::UDPRecvMsg6 => bpf_attach_type::BPF_CGROUP_UDP6_RECVMSG,
}
}
}
#[derive(Debug, Error)]
#[error("{0} is not a valid attach type for a CGROUP_SOCK_ADDR program")]
pub(crate) struct InvalidAttachType(String);
impl CgroupSockAddrAttachType {
pub(crate) fn try_from(value: &str) -> Result<CgroupSockAddrAttachType, InvalidAttachType> {
match value {
"bind4" => Ok(CgroupSockAddrAttachType::Bind4),
"bind6" => Ok(CgroupSockAddrAttachType::Bind6),
"connect4" => Ok(CgroupSockAddrAttachType::Connect4),
"connect6" => Ok(CgroupSockAddrAttachType::Connect6),
"getpeername4" => Ok(CgroupSockAddrAttachType::GetPeerName4),
"getpeername6" => Ok(CgroupSockAddrAttachType::GetPeerName6),
"getsockname4" => Ok(CgroupSockAddrAttachType::GetSockName4),
"getsockname6" => Ok(CgroupSockAddrAttachType::GetSockName6),
"sendmsg4" => Ok(CgroupSockAddrAttachType::UDPSendMsg4),
"sendmsg6" => Ok(CgroupSockAddrAttachType::UDPSendMsg6),
"recvmsg4" => Ok(CgroupSockAddrAttachType::UDPRecvMsg4),
"recvmsg6" => Ok(CgroupSockAddrAttachType::UDPRecvMsg6),
_ => Err(InvalidAttachType(value.to_owned())),
}
}
}

@ -1,5 +1,5 @@
//! Cgroup socket option programs.
use thiserror::Error;
pub use aya_obj::programs::CgroupSockoptAttachType;
use std::{
hash::Hash,
@ -9,8 +9,7 @@ use std::{
use crate::{
generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCKOPT,
programs::{
bpf_attach_type, define_link_wrapper, load_program, FdLink, Link, ProgAttachLink,
ProgramData, ProgramError,
define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError,
},
sys::{bpf_link_create, bpf_prog_attach, kernel_version},
};
@ -155,35 +154,3 @@ define_link_wrapper!(
CgroupSockoptLinkInner,
CgroupSockoptLinkIdInner
);
/// Defines where to attach a [`CgroupSockopt`] program.
#[derive(Copy, Clone, Debug)]
pub enum CgroupSockoptAttachType {
/// Attach to GetSockopt.
Get,
/// Attach to SetSockopt.
Set,
}
impl From<CgroupSockoptAttachType> for bpf_attach_type {
fn from(s: CgroupSockoptAttachType) -> bpf_attach_type {
match s {
CgroupSockoptAttachType::Get => bpf_attach_type::BPF_CGROUP_GETSOCKOPT,
CgroupSockoptAttachType::Set => bpf_attach_type::BPF_CGROUP_SETSOCKOPT,
}
}
}
#[derive(Debug, Error)]
#[error("{0} is not a valid attach type for a CGROUP_SOCKOPT program")]
pub(crate) struct InvalidAttachType(String);
impl CgroupSockoptAttachType {
pub(crate) fn try_from(value: &str) -> Result<CgroupSockoptAttachType, InvalidAttachType> {
match value {
"getsockopt" => Ok(CgroupSockoptAttachType::Get),
"setsockopt" => Ok(CgroupSockoptAttachType::Set),
_ => Err(InvalidAttachType(value.to_owned())),
}
}
}

@ -210,6 +210,10 @@ pub enum ProgramError {
/// program name
name: String,
},
/// An error occurred while working with IO.
#[error(transparent)]
IOError(#[from] io::Error),
}
/// A [`Program`] file descriptor.

@ -2,14 +2,15 @@ use libc::pid_t;
use std::{
fs::{self, OpenOptions},
io::{self, Write},
path::Path,
process,
};
use crate::{
programs::{
kprobe::KProbeError, perf_attach, perf_attach::PerfLink, perf_attach_debugfs,
trace_point::read_sys_fs_trace_point_id, uprobe::UProbeError, Link, ProgramData,
ProgramError,
trace_point::read_sys_fs_trace_point_id, uprobe::UProbeError, utils::find_tracefs_path,
Link, ProgramData, ProgramError,
},
sys::{kernel_version, perf_event_open_probe, perf_event_open_trace_point},
};
@ -60,10 +61,12 @@ pub(crate) fn attach<T: Link + From<PerfLink>>(
pub(crate) fn detach_debug_fs(kind: ProbeKind, event_alias: &str) -> Result<(), ProgramError> {
use ProbeKind::*;
let tracefs = find_tracefs_path()?;
match kind {
KProbe | KRetProbe => delete_probe_event(kind, event_alias)
KProbe | KRetProbe => delete_probe_event(tracefs, kind, event_alias)
.map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })?,
UProbe | URetProbe => delete_probe_event(kind, event_alias)
UProbe | URetProbe => delete_probe_event(tracefs, kind, event_alias)
.map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })?,
};
@ -115,15 +118,17 @@ fn create_as_trace_point(
) -> Result<(i32, String), ProgramError> {
use ProbeKind::*;
let tracefs = find_tracefs_path()?;
let event_alias = match kind {
KProbe | KRetProbe => create_probe_event(kind, name, offset)
KProbe | KRetProbe => create_probe_event(tracefs, kind, name, offset)
.map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })?,
UProbe | URetProbe => create_probe_event(kind, name, offset)
UProbe | URetProbe => create_probe_event(tracefs, kind, name, offset)
.map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })?,
};
let category = format!("{}s", kind.pmu());
let tpid = read_sys_fs_trace_point_id(&category, &event_alias)?;
let tpid = read_sys_fs_trace_point_id(tracefs, &category, &event_alias)?;
let fd = perf_event_open_trace_point(tpid, pid).map_err(|(_code, io_error)| {
ProgramError::SyscallError {
call: "perf_event_open".to_owned(),
@ -135,13 +140,14 @@ fn create_as_trace_point(
}
fn create_probe_event(
tracefs: &Path,
kind: ProbeKind,
fn_name: &str,
offset: u64,
) -> Result<String, (String, io::Error)> {
use ProbeKind::*;
let events_file_name = format!("/sys/kernel/debug/tracing/{}_events", kind.pmu());
let events_file_name = tracefs.join(format!("{}_events", kind.pmu()));
let probe_type_prefix = match kind {
KProbe | UProbe => 'p',
KRetProbe | URetProbe => 'r',
@ -170,20 +176,24 @@ fn create_probe_event(
let mut events_file = OpenOptions::new()
.append(true)
.open(&events_file_name)
.map_err(|e| (events_file_name.clone(), e))?;
.map_err(|e| (events_file_name.display().to_string(), e))?;
events_file
.write_all(probe.as_bytes())
.map_err(|e| (events_file_name.clone(), e))?;
.map_err(|e| (events_file_name.display().to_string(), e))?;
Ok(event_alias)
}
fn delete_probe_event(kind: ProbeKind, event_alias: &str) -> Result<(), (String, io::Error)> {
let events_file_name = format!("/sys/kernel/debug/tracing/{}_events", kind.pmu());
fn delete_probe_event(
tracefs: &Path,
kind: ProbeKind,
event_alias: &str,
) -> Result<(), (String, io::Error)> {
let events_file_name = tracefs.join(format!("{}_events", kind.pmu()));
let events =
fs::read_to_string(&events_file_name).map_err(|e| (events_file_name.clone(), e))?;
let events = fs::read_to_string(&events_file_name)
.map_err(|e| (events_file_name.display().to_string(), e))?;
let found = events.lines().any(|line| line.contains(event_alias));
@ -191,13 +201,13 @@ fn delete_probe_event(kind: ProbeKind, event_alias: &str) -> Result<(), (String,
let mut events_file = OpenOptions::new()
.append(true)
.open(&events_file_name)
.map_err(|e| (events_file_name.to_string(), e))?;
.map_err(|e| (events_file_name.display().to_string(), e))?;
let rm = format!("-:{event_alias}\n");
events_file
.write_all(rm.as_bytes())
.map_err(|e| (events_file_name.to_string(), e))?;
.map_err(|e| (events_file_name.display().to_string(), e))?;
}
Ok(())

@ -237,6 +237,64 @@ define_link_wrapper!(
TcLinkId
);
impl SchedClassifierLink {
/// Constructs a [`SchedClassifierLink`] where the `if_name`, `attach_type`,
/// `priority` and `handle` are already known. This may have been found from a link created by
/// [SchedClassifier::attach], the output of the `tc filter` command or from the output of
/// another BPF loader.
///
/// Note: If you create a link for a program that you do not own, detaching it may have
/// unintended consequences.
///
/// # Errors
/// Returns [`io::Error`] if `if_name` is invalid. If the other parameters are invalid this call
/// will succeed, but calling [`SchedClassifierLink::detach`] will return [`TcError::NetlinkError`].
///
/// # Examples
/// ```no_run
/// # use aya::programs::tc::SchedClassifierLink;
/// # use aya::programs::TcAttachType;
/// # #[derive(Debug, thiserror::Error)]
/// # enum Error {
/// # #[error(transparent)]
/// # IO(#[from] std::io::Error),
/// # }
/// # fn read_persisted_link_details() -> (String, TcAttachType, u16, u32) {
/// # ("eth0".to_string(), TcAttachType::Ingress, 50, 1)
/// # }
/// // Get the link parameters from some external source. Where and how the parameters are
/// // persisted is up to your application.
/// let (if_name, attach_type, priority, handle) = read_persisted_link_details();
/// let new_tc_link = SchedClassifierLink::attached(&if_name, attach_type, priority, handle)?;
///
/// # Ok::<(), Error>(())
/// ```
pub fn attached(
if_name: &str,
attach_type: TcAttachType,
priority: u16,
handle: u32,
) -> Result<SchedClassifierLink, io::Error> {
let if_index = ifindex_from_ifname(if_name)?;
Ok(SchedClassifierLink(Some(TcLink {
if_index: if_index as i32,
attach_type,
priority,
handle,
})))
}
/// Returns the allocated priority. If none was provided at attach time, this was allocated for you.
pub fn priority(&self) -> u16 {
self.inner().priority
}
/// Returns the assigned handle. If none was provided at attach time, this was allocated for you.
pub fn handle(&self) -> u32 {
self.inner().handle
}
}
/// Add the `clasct` qdisc to the given interface.
///
/// The `clsact` qdisc must be added to an interface before [`SchedClassifier`]

@ -1,5 +1,5 @@
//! Tracepoint programs.
use std::{fs, io};
use std::{fs, io, path::Path};
use thiserror::Error;
use crate::{
@ -7,6 +7,7 @@ use crate::{
programs::{
define_link_wrapper, load_program,
perf_attach::{perf_attach, PerfLink, PerfLinkId},
utils::find_tracefs_path,
ProgramData, ProgramError,
},
sys::perf_event_open_trace_point,
@ -77,7 +78,8 @@ impl TracePoint {
///
/// The returned value can be used to detach, see [TracePoint::detach].
pub fn attach(&mut self, category: &str, name: &str) -> Result<TracePointLinkId, ProgramError> {
let id = read_sys_fs_trace_point_id(category, name)?;
let tracefs = find_tracefs_path()?;
let id = read_sys_fs_trace_point_id(tracefs, category, name)?;
let fd = perf_event_open_trace_point(id, None).map_err(|(_code, io_error)| {
ProgramError::SyscallError {
call: "perf_event_open".to_owned(),
@ -114,20 +116,21 @@ define_link_wrapper!(
);
pub(crate) fn read_sys_fs_trace_point_id(
tracefs: &Path,
category: &str,
name: &str,
) -> Result<u32, TracePointError> {
let file = format!("/sys/kernel/debug/tracing/events/{category}/{name}/id");
let file = tracefs.join("events").join(category).join(name).join("id");
let id = fs::read_to_string(&file).map_err(|io_error| TracePointError::FileError {
filename: file.clone(),
filename: file.display().to_string(),
io_error,
})?;
let id = id
.trim()
.parse::<u32>()
.map_err(|error| TracePointError::FileError {
filename: file.clone(),
filename: file.display().to_string(),
io_error: io::Error::new(io::ErrorKind::Other, error),
})?;

@ -1,5 +1,5 @@
//! Common functions shared between multiple eBPF program types.
use std::{ffi::CStr, os::unix::io::RawFd};
use std::{ffi::CStr, io, os::unix::io::RawFd, path::Path};
use crate::{
programs::{FdLink, Link, ProgramData, ProgramError},
@ -22,3 +22,26 @@ pub(crate) fn attach_raw_tracepoint<T: Link + From<FdLink>>(
program_data.links.insert(FdLink::new(pfd).into())
}
/// Find tracefs filesystem path
pub(crate) fn find_tracefs_path() -> Result<&'static Path, ProgramError> {
lazy_static::lazy_static! {
static ref TRACE_FS: Option<&'static Path> = {
let known_mounts = [
Path::new("/sys/kernel/tracing"),
Path::new("/sys/kernel/debug/tracing"),
];
for mount in known_mounts {
if mount.exists() {
return Some(mount);
}
}
None
};
}
TRACE_FS
.as_deref()
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "tracefs not found").into())
}

@ -12,7 +12,7 @@ use libc::{c_char, c_long, close, ENOENT, ENOSPC};
use crate::{
generated::{
bpf_attach_type, bpf_attr, bpf_btf_info, bpf_cmd, bpf_insn, bpf_link_info, bpf_map_info,
bpf_prog_info, bpf_prog_type, BPF_F_REPLACE,
bpf_map_type, bpf_prog_info, bpf_prog_type, BPF_F_REPLACE,
},
maps::PerCpuValues,
obj::{
@ -39,9 +39,36 @@ pub(crate) fn bpf_create_map(name: &CStr, def: &obj::Map, btf_fd: Option<RawFd>)
u.map_flags = def.map_flags();
if let obj::Map::Btf(m) = def {
u.btf_key_type_id = m.def.btf_key_type_id;
u.btf_value_type_id = m.def.btf_value_type_id;
u.btf_fd = btf_fd.unwrap() as u32;
use bpf_map_type::*;
// Mimic https://github.com/libbpf/libbpf/issues/355
// Currently a bunch of (usually pretty specialized) BPF maps do not support
// specifying BTF types for the key and value.
match u.map_type.try_into() {
Ok(BPF_MAP_TYPE_PERF_EVENT_ARRAY)
| Ok(BPF_MAP_TYPE_CGROUP_ARRAY)
| Ok(BPF_MAP_TYPE_STACK_TRACE)
| Ok(BPF_MAP_TYPE_ARRAY_OF_MAPS)
| Ok(BPF_MAP_TYPE_HASH_OF_MAPS)
| Ok(BPF_MAP_TYPE_DEVMAP)
| Ok(BPF_MAP_TYPE_DEVMAP_HASH)
| Ok(BPF_MAP_TYPE_CPUMAP)
| Ok(BPF_MAP_TYPE_XSKMAP)
| Ok(BPF_MAP_TYPE_SOCKMAP)
| Ok(BPF_MAP_TYPE_SOCKHASH)
| Ok(BPF_MAP_TYPE_QUEUE)
| Ok(BPF_MAP_TYPE_STACK)
| Ok(BPF_MAP_TYPE_RINGBUF) => {
u.btf_key_type_id = 0;
u.btf_value_type_id = 0;
u.btf_fd = 0;
}
_ => {
u.btf_key_type_id = m.def.btf_key_type_id;
u.btf_value_type_id = m.def.btf_value_type_id;
u.btf_fd = btf_fd.unwrap() as u32;
}
}
}
// https://github.com/torvalds/linux/commit/ad5b177bd73f5107d97c36f56395c4281fb6f089

@ -358,16 +358,40 @@ pub struct bpf_cgroup_storage_key {
pub cgroup_inode_id: __u64,
pub attach_type: __u32,
}
pub mod bpf_cgroup_iter_order {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_CGROUP_ITER_ORDER_UNSPEC: Type = 0;
pub const BPF_CGROUP_ITER_SELF_ONLY: Type = 1;
pub const BPF_CGROUP_ITER_DESCENDANTS_PRE: Type = 2;
pub const BPF_CGROUP_ITER_DESCENDANTS_POST: Type = 3;
pub const BPF_CGROUP_ITER_ANCESTORS_UP: Type = 4;
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union bpf_iter_link_info {
pub map: bpf_iter_link_info__bindgen_ty_1,
pub cgroup: bpf_iter_link_info__bindgen_ty_2,
pub task: bpf_iter_link_info__bindgen_ty_3,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_iter_link_info__bindgen_ty_1 {
pub map_fd: __u32,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_iter_link_info__bindgen_ty_2 {
pub order: bpf_cgroup_iter_order::Type,
pub cgroup_fd: __u32,
pub cgroup_id: __u64,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_iter_link_info__bindgen_ty_3 {
pub tid: __u32,
pub pid: __u32,
pub pid_fd: __u32,
}
pub mod bpf_cmd {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_MAP_CREATE: Type = 0;
@ -429,6 +453,7 @@ pub mod bpf_map_type {
pub const BPF_MAP_TYPE_CPUMAP: Type = 16;
pub const BPF_MAP_TYPE_XSKMAP: Type = 17;
pub const BPF_MAP_TYPE_SOCKHASH: Type = 18;
pub const BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED: Type = 19;
pub const BPF_MAP_TYPE_CGROUP_STORAGE: Type = 19;
pub const BPF_MAP_TYPE_REUSEPORT_SOCKARRAY: Type = 20;
pub const BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE: Type = 21;
@ -441,6 +466,8 @@ pub mod bpf_map_type {
pub const BPF_MAP_TYPE_INODE_STORAGE: Type = 28;
pub const BPF_MAP_TYPE_TASK_STORAGE: Type = 29;
pub const BPF_MAP_TYPE_BLOOM_FILTER: Type = 30;
pub const BPF_MAP_TYPE_USER_RINGBUF: Type = 31;
pub const BPF_MAP_TYPE_CGRP_STORAGE: Type = 32;
}
pub mod bpf_prog_type {
pub type Type = ::aya_bpf_cty::c_uint;
@ -1072,7 +1099,10 @@ pub mod bpf_func_id {
pub const BPF_FUNC_tcp_raw_check_syncookie_ipv4: Type = 206;
pub const BPF_FUNC_tcp_raw_check_syncookie_ipv6: Type = 207;
pub const BPF_FUNC_ktime_get_tai_ns: Type = 208;
pub const __BPF_FUNC_MAX_ID: Type = 209;
pub const BPF_FUNC_user_ringbuf_drain: Type = 209;
pub const BPF_FUNC_cgrp_storage_get: Type = 210;
pub const BPF_FUNC_cgrp_storage_delete: Type = 211;
pub const __BPF_FUNC_MAX_ID: Type = 212;
}
pub const BPF_F_RECOMPUTE_CSUM: _bindgen_ty_4 = 1;
pub const BPF_F_INVALIDATE_HASH: _bindgen_ty_4 = 2;
@ -1096,51 +1126,54 @@ pub type _bindgen_ty_9 = ::aya_bpf_cty::c_uint;
pub const BPF_F_ZERO_CSUM_TX: _bindgen_ty_10 = 2;
pub const BPF_F_DONT_FRAGMENT: _bindgen_ty_10 = 4;
pub const BPF_F_SEQ_NUMBER: _bindgen_ty_10 = 8;
pub const BPF_F_NO_TUNNEL_KEY: _bindgen_ty_10 = 16;
pub type _bindgen_ty_10 = ::aya_bpf_cty::c_uint;
pub const BPF_F_INDEX_MASK: _bindgen_ty_11 = 4294967295;
pub const BPF_F_CURRENT_CPU: _bindgen_ty_11 = 4294967295;
pub const BPF_F_CTXLEN_MASK: _bindgen_ty_11 = 4503595332403200;
pub type _bindgen_ty_11 = ::aya_bpf_cty::c_ulong;
pub const BPF_F_CURRENT_NETNS: _bindgen_ty_12 = -1;
pub type _bindgen_ty_12 = ::aya_bpf_cty::c_int;
pub const BPF_CSUM_LEVEL_QUERY: _bindgen_ty_13 = 0;
pub const BPF_CSUM_LEVEL_INC: _bindgen_ty_13 = 1;
pub const BPF_CSUM_LEVEL_DEC: _bindgen_ty_13 = 2;
pub const BPF_CSUM_LEVEL_RESET: _bindgen_ty_13 = 3;
pub type _bindgen_ty_13 = ::aya_bpf_cty::c_uint;
pub const BPF_F_ADJ_ROOM_FIXED_GSO: _bindgen_ty_14 = 1;
pub const BPF_F_ADJ_ROOM_ENCAP_L3_IPV4: _bindgen_ty_14 = 2;
pub const BPF_F_ADJ_ROOM_ENCAP_L3_IPV6: _bindgen_ty_14 = 4;
pub const BPF_F_ADJ_ROOM_ENCAP_L4_GRE: _bindgen_ty_14 = 8;
pub const BPF_F_ADJ_ROOM_ENCAP_L4_UDP: _bindgen_ty_14 = 16;
pub const BPF_F_ADJ_ROOM_NO_CSUM_RESET: _bindgen_ty_14 = 32;
pub const BPF_F_ADJ_ROOM_ENCAP_L2_ETH: _bindgen_ty_14 = 64;
pub const BPF_F_TUNINFO_FLAGS: _bindgen_ty_11 = 16;
pub type _bindgen_ty_11 = ::aya_bpf_cty::c_uint;
pub const BPF_F_INDEX_MASK: _bindgen_ty_12 = 4294967295;
pub const BPF_F_CURRENT_CPU: _bindgen_ty_12 = 4294967295;
pub const BPF_F_CTXLEN_MASK: _bindgen_ty_12 = 4503595332403200;
pub type _bindgen_ty_12 = ::aya_bpf_cty::c_ulong;
pub const BPF_F_CURRENT_NETNS: _bindgen_ty_13 = -1;
pub type _bindgen_ty_13 = ::aya_bpf_cty::c_int;
pub const BPF_CSUM_LEVEL_QUERY: _bindgen_ty_14 = 0;
pub const BPF_CSUM_LEVEL_INC: _bindgen_ty_14 = 1;
pub const BPF_CSUM_LEVEL_DEC: _bindgen_ty_14 = 2;
pub const BPF_CSUM_LEVEL_RESET: _bindgen_ty_14 = 3;
pub type _bindgen_ty_14 = ::aya_bpf_cty::c_uint;
pub const BPF_ADJ_ROOM_ENCAP_L2_MASK: _bindgen_ty_15 = 255;
pub const BPF_ADJ_ROOM_ENCAP_L2_SHIFT: _bindgen_ty_15 = 56;
pub const BPF_F_ADJ_ROOM_FIXED_GSO: _bindgen_ty_15 = 1;
pub const BPF_F_ADJ_ROOM_ENCAP_L3_IPV4: _bindgen_ty_15 = 2;
pub const BPF_F_ADJ_ROOM_ENCAP_L3_IPV6: _bindgen_ty_15 = 4;
pub const BPF_F_ADJ_ROOM_ENCAP_L4_GRE: _bindgen_ty_15 = 8;
pub const BPF_F_ADJ_ROOM_ENCAP_L4_UDP: _bindgen_ty_15 = 16;
pub const BPF_F_ADJ_ROOM_NO_CSUM_RESET: _bindgen_ty_15 = 32;
pub const BPF_F_ADJ_ROOM_ENCAP_L2_ETH: _bindgen_ty_15 = 64;
pub type _bindgen_ty_15 = ::aya_bpf_cty::c_uint;
pub const BPF_F_SYSCTL_BASE_NAME: _bindgen_ty_16 = 1;
pub const BPF_ADJ_ROOM_ENCAP_L2_MASK: _bindgen_ty_16 = 255;
pub const BPF_ADJ_ROOM_ENCAP_L2_SHIFT: _bindgen_ty_16 = 56;
pub type _bindgen_ty_16 = ::aya_bpf_cty::c_uint;
pub const BPF_LOCAL_STORAGE_GET_F_CREATE: _bindgen_ty_17 = 1;
pub const BPF_SK_STORAGE_GET_F_CREATE: _bindgen_ty_17 = 1;
pub const BPF_F_SYSCTL_BASE_NAME: _bindgen_ty_17 = 1;
pub type _bindgen_ty_17 = ::aya_bpf_cty::c_uint;
pub const BPF_F_GET_BRANCH_RECORDS_SIZE: _bindgen_ty_18 = 1;
pub const BPF_LOCAL_STORAGE_GET_F_CREATE: _bindgen_ty_18 = 1;
pub const BPF_SK_STORAGE_GET_F_CREATE: _bindgen_ty_18 = 1;
pub type _bindgen_ty_18 = ::aya_bpf_cty::c_uint;
pub const BPF_RB_NO_WAKEUP: _bindgen_ty_19 = 1;
pub const BPF_RB_FORCE_WAKEUP: _bindgen_ty_19 = 2;
pub const BPF_F_GET_BRANCH_RECORDS_SIZE: _bindgen_ty_19 = 1;
pub type _bindgen_ty_19 = ::aya_bpf_cty::c_uint;
pub const BPF_RB_AVAIL_DATA: _bindgen_ty_20 = 0;
pub const BPF_RB_RING_SIZE: _bindgen_ty_20 = 1;
pub const BPF_RB_CONS_POS: _bindgen_ty_20 = 2;
pub const BPF_RB_PROD_POS: _bindgen_ty_20 = 3;
pub const BPF_RB_NO_WAKEUP: _bindgen_ty_20 = 1;
pub const BPF_RB_FORCE_WAKEUP: _bindgen_ty_20 = 2;
pub type _bindgen_ty_20 = ::aya_bpf_cty::c_uint;
pub const BPF_RINGBUF_BUSY_BIT: _bindgen_ty_21 = 2147483648;
pub const BPF_RINGBUF_DISCARD_BIT: _bindgen_ty_21 = 1073741824;
pub const BPF_RINGBUF_HDR_SZ: _bindgen_ty_21 = 8;
pub const BPF_RB_AVAIL_DATA: _bindgen_ty_21 = 0;
pub const BPF_RB_RING_SIZE: _bindgen_ty_21 = 1;
pub const BPF_RB_CONS_POS: _bindgen_ty_21 = 2;
pub const BPF_RB_PROD_POS: _bindgen_ty_21 = 3;
pub type _bindgen_ty_21 = ::aya_bpf_cty::c_uint;
pub const BPF_SK_LOOKUP_F_REPLACE: _bindgen_ty_22 = 1;
pub const BPF_SK_LOOKUP_F_NO_REUSEPORT: _bindgen_ty_22 = 2;
pub const BPF_RINGBUF_BUSY_BIT: _bindgen_ty_22 = 2147483648;
pub const BPF_RINGBUF_DISCARD_BIT: _bindgen_ty_22 = 1073741824;
pub const BPF_RINGBUF_HDR_SZ: _bindgen_ty_22 = 8;
pub type _bindgen_ty_22 = ::aya_bpf_cty::c_uint;
pub const BPF_SK_LOOKUP_F_REPLACE: _bindgen_ty_23 = 1;
pub const BPF_SK_LOOKUP_F_NO_REUSEPORT: _bindgen_ty_23 = 2;
pub type _bindgen_ty_23 = ::aya_bpf_cty::c_uint;
pub mod bpf_adj_room_mode {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_ADJ_ROOM_NET: Type = 0;
@ -1157,12 +1190,12 @@ pub mod bpf_lwt_encap_mode {
pub const BPF_LWT_ENCAP_SEG6_INLINE: Type = 1;
pub const BPF_LWT_ENCAP_IP: Type = 2;
}
pub const BPF_F_BPRM_SECUREEXEC: _bindgen_ty_23 = 1;
pub type _bindgen_ty_23 = ::aya_bpf_cty::c_uint;
pub const BPF_F_BROADCAST: _bindgen_ty_24 = 8;
pub const BPF_F_EXCLUDE_INGRESS: _bindgen_ty_24 = 16;
pub const BPF_F_BPRM_SECUREEXEC: _bindgen_ty_24 = 1;
pub type _bindgen_ty_24 = ::aya_bpf_cty::c_uint;
pub mod _bindgen_ty_25 {
pub const BPF_F_BROADCAST: _bindgen_ty_25 = 8;
pub const BPF_F_EXCLUDE_INGRESS: _bindgen_ty_25 = 16;
pub type _bindgen_ty_25 = ::aya_bpf_cty::c_uint;
pub mod _bindgen_ty_26 {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_SKB_TSTAMP_UNSPEC: Type = 0;
pub const BPF_SKB_TSTAMP_DELIVERY_MONO: Type = 1;
@ -1249,9 +1282,9 @@ pub struct bpf_tunnel_key {
pub __bindgen_anon_1: bpf_tunnel_key__bindgen_ty_1,
pub tunnel_tos: __u8,
pub tunnel_ttl: __u8,
pub tunnel_ext: __u16,
pub tunnel_label: __u32,
pub __bindgen_anon_2: bpf_tunnel_key__bindgen_ty_2,
pub tunnel_label: __u32,
pub __bindgen_anon_3: bpf_tunnel_key__bindgen_ty_3,
}
#[repr(C)]
#[derive(Copy, Clone)]
@ -1262,6 +1295,12 @@ pub union bpf_tunnel_key__bindgen_ty_1 {
#[repr(C)]
#[derive(Copy, Clone)]
pub union bpf_tunnel_key__bindgen_ty_2 {
pub tunnel_ext: __u16,
pub tunnel_flags: __be16,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union bpf_tunnel_key__bindgen_ty_3 {
pub local_ipv4: __u32,
pub local_ipv6: [__u32; 4usize],
}
@ -1286,6 +1325,7 @@ pub mod bpf_ret_code {
pub const BPF_DROP: Type = 2;
pub const BPF_REDIRECT: Type = 7;
pub const BPF_LWT_REROUTE: Type = 128;
pub const BPF_FLOW_DISSECTOR_CONTINUE: Type = 129;
}
#[repr(C)]
#[derive(Copy, Clone)]
@ -1695,6 +1735,7 @@ pub struct bpf_link_info__bindgen_ty_1__bindgen_ty_4 {
pub target_name: __u64,
pub target_name_len: __u32,
pub __bindgen_anon_1: bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_1,
pub __bindgen_anon_2: bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2,
}
#[repr(C)]
#[derive(Copy, Clone)]
@ -1708,6 +1749,24 @@ pub struct bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_1__bindgen_ty_1
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2 {
pub cgroup: bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2__bindgen_ty_1,
pub task: bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2__bindgen_ty_2,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2__bindgen_ty_1 {
pub cgroup_id: __u64,
pub order: __u32,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2__bindgen_ty_2 {
pub tid: __u32,
pub pid: __u32,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_link_info__bindgen_ty_1__bindgen_ty_5 {
pub netns_ino: __u32,
pub attach_type: __u32,
@ -1788,6 +1847,7 @@ pub struct bpf_sock_ops {
pub __bindgen_anon_4: bpf_sock_ops__bindgen_ty_4,
pub skb_len: __u32,
pub skb_tcp_flags: __u32,
pub skb_hwtstamp: __u64,
}
#[repr(C)]
#[derive(Copy, Clone)]
@ -1838,51 +1898,51 @@ impl bpf_sock_ops__bindgen_ty_4 {
__bindgen_bitfield_unit
}
}
pub const BPF_SOCK_OPS_RTO_CB_FLAG: _bindgen_ty_26 = 1;
pub const BPF_SOCK_OPS_RETRANS_CB_FLAG: _bindgen_ty_26 = 2;
pub const BPF_SOCK_OPS_STATE_CB_FLAG: _bindgen_ty_26 = 4;
pub const BPF_SOCK_OPS_RTT_CB_FLAG: _bindgen_ty_26 = 8;
pub const BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG: _bindgen_ty_26 = 16;
pub const BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG: _bindgen_ty_26 = 32;
pub const BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG: _bindgen_ty_26 = 64;
pub const BPF_SOCK_OPS_ALL_CB_FLAGS: _bindgen_ty_26 = 127;
pub type _bindgen_ty_26 = ::aya_bpf_cty::c_uint;
pub const BPF_SOCK_OPS_VOID: _bindgen_ty_27 = 0;
pub const BPF_SOCK_OPS_TIMEOUT_INIT: _bindgen_ty_27 = 1;
pub const BPF_SOCK_OPS_RWND_INIT: _bindgen_ty_27 = 2;
pub const BPF_SOCK_OPS_TCP_CONNECT_CB: _bindgen_ty_27 = 3;
pub const BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB: _bindgen_ty_27 = 4;
pub const BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB: _bindgen_ty_27 = 5;
pub const BPF_SOCK_OPS_NEEDS_ECN: _bindgen_ty_27 = 6;
pub const BPF_SOCK_OPS_BASE_RTT: _bindgen_ty_27 = 7;
pub const BPF_SOCK_OPS_RTO_CB: _bindgen_ty_27 = 8;
pub const BPF_SOCK_OPS_RETRANS_CB: _bindgen_ty_27 = 9;
pub const BPF_SOCK_OPS_STATE_CB: _bindgen_ty_27 = 10;
pub const BPF_SOCK_OPS_TCP_LISTEN_CB: _bindgen_ty_27 = 11;
pub const BPF_SOCK_OPS_RTT_CB: _bindgen_ty_27 = 12;
pub const BPF_SOCK_OPS_PARSE_HDR_OPT_CB: _bindgen_ty_27 = 13;
pub const BPF_SOCK_OPS_HDR_OPT_LEN_CB: _bindgen_ty_27 = 14;
pub const BPF_SOCK_OPS_WRITE_HDR_OPT_CB: _bindgen_ty_27 = 15;
pub const BPF_SOCK_OPS_RTO_CB_FLAG: _bindgen_ty_27 = 1;
pub const BPF_SOCK_OPS_RETRANS_CB_FLAG: _bindgen_ty_27 = 2;
pub const BPF_SOCK_OPS_STATE_CB_FLAG: _bindgen_ty_27 = 4;
pub const BPF_SOCK_OPS_RTT_CB_FLAG: _bindgen_ty_27 = 8;
pub const BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG: _bindgen_ty_27 = 16;
pub const BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG: _bindgen_ty_27 = 32;
pub const BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG: _bindgen_ty_27 = 64;
pub const BPF_SOCK_OPS_ALL_CB_FLAGS: _bindgen_ty_27 = 127;
pub type _bindgen_ty_27 = ::aya_bpf_cty::c_uint;
pub const BPF_TCP_ESTABLISHED: _bindgen_ty_28 = 1;
pub const BPF_TCP_SYN_SENT: _bindgen_ty_28 = 2;
pub const BPF_TCP_SYN_RECV: _bindgen_ty_28 = 3;
pub const BPF_TCP_FIN_WAIT1: _bindgen_ty_28 = 4;
pub const BPF_TCP_FIN_WAIT2: _bindgen_ty_28 = 5;
pub const BPF_TCP_TIME_WAIT: _bindgen_ty_28 = 6;
pub const BPF_TCP_CLOSE: _bindgen_ty_28 = 7;
pub const BPF_TCP_CLOSE_WAIT: _bindgen_ty_28 = 8;
pub const BPF_TCP_LAST_ACK: _bindgen_ty_28 = 9;
pub const BPF_TCP_LISTEN: _bindgen_ty_28 = 10;
pub const BPF_TCP_CLOSING: _bindgen_ty_28 = 11;
pub const BPF_TCP_NEW_SYN_RECV: _bindgen_ty_28 = 12;
pub const BPF_TCP_MAX_STATES: _bindgen_ty_28 = 13;
pub const BPF_SOCK_OPS_VOID: _bindgen_ty_28 = 0;
pub const BPF_SOCK_OPS_TIMEOUT_INIT: _bindgen_ty_28 = 1;
pub const BPF_SOCK_OPS_RWND_INIT: _bindgen_ty_28 = 2;
pub const BPF_SOCK_OPS_TCP_CONNECT_CB: _bindgen_ty_28 = 3;
pub const BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB: _bindgen_ty_28 = 4;
pub const BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB: _bindgen_ty_28 = 5;
pub const BPF_SOCK_OPS_NEEDS_ECN: _bindgen_ty_28 = 6;
pub const BPF_SOCK_OPS_BASE_RTT: _bindgen_ty_28 = 7;
pub const BPF_SOCK_OPS_RTO_CB: _bindgen_ty_28 = 8;
pub const BPF_SOCK_OPS_RETRANS_CB: _bindgen_ty_28 = 9;
pub const BPF_SOCK_OPS_STATE_CB: _bindgen_ty_28 = 10;
pub const BPF_SOCK_OPS_TCP_LISTEN_CB: _bindgen_ty_28 = 11;
pub const BPF_SOCK_OPS_RTT_CB: _bindgen_ty_28 = 12;
pub const BPF_SOCK_OPS_PARSE_HDR_OPT_CB: _bindgen_ty_28 = 13;
pub const BPF_SOCK_OPS_HDR_OPT_LEN_CB: _bindgen_ty_28 = 14;
pub const BPF_SOCK_OPS_WRITE_HDR_OPT_CB: _bindgen_ty_28 = 15;
pub type _bindgen_ty_28 = ::aya_bpf_cty::c_uint;
pub mod _bindgen_ty_30 {
pub const BPF_TCP_ESTABLISHED: _bindgen_ty_29 = 1;
pub const BPF_TCP_SYN_SENT: _bindgen_ty_29 = 2;
pub const BPF_TCP_SYN_RECV: _bindgen_ty_29 = 3;
pub const BPF_TCP_FIN_WAIT1: _bindgen_ty_29 = 4;
pub const BPF_TCP_FIN_WAIT2: _bindgen_ty_29 = 5;
pub const BPF_TCP_TIME_WAIT: _bindgen_ty_29 = 6;
pub const BPF_TCP_CLOSE: _bindgen_ty_29 = 7;
pub const BPF_TCP_CLOSE_WAIT: _bindgen_ty_29 = 8;
pub const BPF_TCP_LAST_ACK: _bindgen_ty_29 = 9;
pub const BPF_TCP_LISTEN: _bindgen_ty_29 = 10;
pub const BPF_TCP_CLOSING: _bindgen_ty_29 = 11;
pub const BPF_TCP_NEW_SYN_RECV: _bindgen_ty_29 = 12;
pub const BPF_TCP_MAX_STATES: _bindgen_ty_29 = 13;
pub type _bindgen_ty_29 = ::aya_bpf_cty::c_uint;
pub mod _bindgen_ty_31 {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_LOAD_HDR_OPT_TCP_SYN: Type = 1;
}
pub mod _bindgen_ty_31 {
pub mod _bindgen_ty_32 {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_WRITE_HDR_TCP_CURRENT_MSS: Type = 1;
pub const BPF_WRITE_HDR_TCP_SYNACK_COOKIE: Type = 2;
@ -1894,13 +1954,13 @@ pub struct bpf_perf_event_value {
pub enabled: __u64,
pub running: __u64,
}
pub const BPF_DEVCG_ACC_MKNOD: _bindgen_ty_32 = 1;
pub const BPF_DEVCG_ACC_READ: _bindgen_ty_32 = 2;
pub const BPF_DEVCG_ACC_WRITE: _bindgen_ty_32 = 4;
pub type _bindgen_ty_32 = ::aya_bpf_cty::c_uint;
pub const BPF_DEVCG_DEV_BLOCK: _bindgen_ty_33 = 1;
pub const BPF_DEVCG_DEV_CHAR: _bindgen_ty_33 = 2;
pub const BPF_DEVCG_ACC_MKNOD: _bindgen_ty_33 = 1;
pub const BPF_DEVCG_ACC_READ: _bindgen_ty_33 = 2;
pub const BPF_DEVCG_ACC_WRITE: _bindgen_ty_33 = 4;
pub type _bindgen_ty_33 = ::aya_bpf_cty::c_uint;
pub const BPF_DEVCG_DEV_BLOCK: _bindgen_ty_34 = 1;
pub const BPF_DEVCG_DEV_CHAR: _bindgen_ty_34 = 2;
pub type _bindgen_ty_34 = ::aya_bpf_cty::c_uint;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_cgroup_dev_ctx {
@ -1912,19 +1972,19 @@ pub struct bpf_cgroup_dev_ctx {
pub struct bpf_raw_tracepoint_args {
pub args: __IncompleteArrayField<__u64>,
}
pub const BPF_FIB_LOOKUP_DIRECT: _bindgen_ty_34 = 1;
pub const BPF_FIB_LOOKUP_OUTPUT: _bindgen_ty_34 = 2;
pub type _bindgen_ty_34 = ::aya_bpf_cty::c_uint;
pub const BPF_FIB_LKUP_RET_SUCCESS: _bindgen_ty_35 = 0;
pub const BPF_FIB_LKUP_RET_BLACKHOLE: _bindgen_ty_35 = 1;
pub const BPF_FIB_LKUP_RET_UNREACHABLE: _bindgen_ty_35 = 2;
pub const BPF_FIB_LKUP_RET_PROHIBIT: _bindgen_ty_35 = 3;
pub const BPF_FIB_LKUP_RET_NOT_FWDED: _bindgen_ty_35 = 4;
pub const BPF_FIB_LKUP_RET_FWD_DISABLED: _bindgen_ty_35 = 5;
pub const BPF_FIB_LKUP_RET_UNSUPP_LWT: _bindgen_ty_35 = 6;
pub const BPF_FIB_LKUP_RET_NO_NEIGH: _bindgen_ty_35 = 7;
pub const BPF_FIB_LKUP_RET_FRAG_NEEDED: _bindgen_ty_35 = 8;
pub const BPF_FIB_LOOKUP_DIRECT: _bindgen_ty_35 = 1;
pub const BPF_FIB_LOOKUP_OUTPUT: _bindgen_ty_35 = 2;
pub type _bindgen_ty_35 = ::aya_bpf_cty::c_uint;
pub const BPF_FIB_LKUP_RET_SUCCESS: _bindgen_ty_36 = 0;
pub const BPF_FIB_LKUP_RET_BLACKHOLE: _bindgen_ty_36 = 1;
pub const BPF_FIB_LKUP_RET_UNREACHABLE: _bindgen_ty_36 = 2;
pub const BPF_FIB_LKUP_RET_PROHIBIT: _bindgen_ty_36 = 3;
pub const BPF_FIB_LKUP_RET_NOT_FWDED: _bindgen_ty_36 = 4;
pub const BPF_FIB_LKUP_RET_FWD_DISABLED: _bindgen_ty_36 = 5;
pub const BPF_FIB_LKUP_RET_UNSUPP_LWT: _bindgen_ty_36 = 6;
pub const BPF_FIB_LKUP_RET_NO_NEIGH: _bindgen_ty_36 = 7;
pub const BPF_FIB_LKUP_RET_FRAG_NEEDED: _bindgen_ty_36 = 8;
pub type _bindgen_ty_36 = ::aya_bpf_cty::c_uint;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_fib_lookup {
@ -1998,10 +2058,10 @@ pub mod bpf_task_fd_type {
pub const BPF_FD_TYPE_UPROBE: Type = 4;
pub const BPF_FD_TYPE_URETPROBE: Type = 5;
}
pub const BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG: _bindgen_ty_36 = 1;
pub const BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL: _bindgen_ty_36 = 2;
pub const BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP: _bindgen_ty_36 = 4;
pub type _bindgen_ty_36 = ::aya_bpf_cty::c_uint;
pub const BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG: _bindgen_ty_37 = 1;
pub const BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL: _bindgen_ty_37 = 2;
pub const BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP: _bindgen_ty_37 = 4;
pub type _bindgen_ty_37 = ::aya_bpf_cty::c_uint;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_flow_keys {
@ -2085,6 +2145,34 @@ impl bpf_dynptr {
}
}
#[repr(C)]
#[repr(align(8))]
#[derive(Copy, Clone)]
pub struct bpf_list_head {
pub _bitfield_align_1: [u8; 0],
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize]>,
}
impl bpf_list_head {
#[inline]
pub fn new_bitfield_1() -> __BindgenBitfieldUnit<[u8; 16usize]> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 16usize]> = Default::default();
__bindgen_bitfield_unit
}
}
#[repr(C)]
#[repr(align(8))]
#[derive(Copy, Clone)]
pub struct bpf_list_node {
pub _bitfield_align_1: [u8; 0],
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize]>,
}
impl bpf_list_node {
#[inline]
pub fn new_bitfield_1() -> __BindgenBitfieldUnit<[u8; 16usize]> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 16usize]> = Default::default();
__bindgen_bitfield_unit
}
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_sysctl {
pub write: __u32,
@ -2300,6 +2388,11 @@ pub struct task_struct {
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct cgroup {
_unused: [u8; 0],
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct path {
_unused: [u8; 0],
}

@ -461,12 +461,12 @@ pub unsafe fn bpf_skb_adjust_room(
}
pub unsafe fn bpf_redirect_map(
map: *mut ::aya_bpf_cty::c_void,
key: __u32,
key: __u64,
flags: __u64,
) -> ::aya_bpf_cty::c_long {
let fun: unsafe extern "C" fn(
map: *mut ::aya_bpf_cty::c_void,
key: __u32,
key: __u64,
flags: __u64,
) -> ::aya_bpf_cty::c_long = ::core::mem::transmute(51usize);
fun(map, key, flags)
@ -2027,28 +2027,28 @@ pub unsafe fn bpf_ringbuf_discard_dynptr(ptr: *mut bpf_dynptr, flags: __u64) {
pub unsafe fn bpf_dynptr_read(
dst: *mut ::aya_bpf_cty::c_void,
len: __u32,
src: *mut bpf_dynptr,
src: *const bpf_dynptr,
offset: __u32,
flags: __u64,
) -> ::aya_bpf_cty::c_long {
let fun: unsafe extern "C" fn(
dst: *mut ::aya_bpf_cty::c_void,
len: __u32,
src: *mut bpf_dynptr,
src: *const bpf_dynptr,
offset: __u32,
flags: __u64,
) -> ::aya_bpf_cty::c_long = ::core::mem::transmute(201usize);
fun(dst, len, src, offset, flags)
}
pub unsafe fn bpf_dynptr_write(
dst: *mut bpf_dynptr,
dst: *const bpf_dynptr,
offset: __u32,
src: *mut ::aya_bpf_cty::c_void,
len: __u32,
flags: __u64,
) -> ::aya_bpf_cty::c_long {
let fun: unsafe extern "C" fn(
dst: *mut bpf_dynptr,
dst: *const bpf_dynptr,
offset: __u32,
src: *mut ::aya_bpf_cty::c_void,
len: __u32,
@ -2057,12 +2057,12 @@ pub unsafe fn bpf_dynptr_write(
fun(dst, offset, src, len, flags)
}
pub unsafe fn bpf_dynptr_data(
ptr: *mut bpf_dynptr,
ptr: *const bpf_dynptr,
offset: __u32,
len: __u32,
) -> *mut ::aya_bpf_cty::c_void {
let fun: unsafe extern "C" fn(
ptr: *mut bpf_dynptr,
ptr: *const bpf_dynptr,
offset: __u32,
len: __u32,
) -> *mut ::aya_bpf_cty::c_void = ::core::mem::transmute(203usize);
@ -2106,3 +2106,41 @@ pub unsafe fn bpf_ktime_get_tai_ns() -> __u64 {
let fun: unsafe extern "C" fn() -> __u64 = ::core::mem::transmute(208usize);
fun()
}
pub unsafe fn bpf_user_ringbuf_drain(
map: *mut ::aya_bpf_cty::c_void,
callback_fn: *mut ::aya_bpf_cty::c_void,
ctx: *mut ::aya_bpf_cty::c_void,
flags: __u64,
) -> ::aya_bpf_cty::c_long {
let fun: unsafe extern "C" fn(
map: *mut ::aya_bpf_cty::c_void,
callback_fn: *mut ::aya_bpf_cty::c_void,
ctx: *mut ::aya_bpf_cty::c_void,
flags: __u64,
) -> ::aya_bpf_cty::c_long = ::core::mem::transmute(209usize);
fun(map, callback_fn, ctx, flags)
}
pub unsafe fn bpf_cgrp_storage_get(
map: *mut ::aya_bpf_cty::c_void,
cgroup: *mut cgroup,
value: *mut ::aya_bpf_cty::c_void,
flags: __u64,
) -> *mut ::aya_bpf_cty::c_void {
let fun: unsafe extern "C" fn(
map: *mut ::aya_bpf_cty::c_void,
cgroup: *mut cgroup,
value: *mut ::aya_bpf_cty::c_void,
flags: __u64,
) -> *mut ::aya_bpf_cty::c_void = ::core::mem::transmute(210usize);
fun(map, cgroup, value, flags)
}
pub unsafe fn bpf_cgrp_storage_delete(
map: *mut ::aya_bpf_cty::c_void,
cgroup: *mut cgroup,
) -> ::aya_bpf_cty::c_long {
let fun: unsafe extern "C" fn(
map: *mut ::aya_bpf_cty::c_void,
cgroup: *mut cgroup,
) -> ::aya_bpf_cty::c_long = ::core::mem::transmute(211usize);
fun(map, cgroup)
}

@ -353,16 +353,40 @@ pub struct bpf_cgroup_storage_key {
pub cgroup_inode_id: __u64,
pub attach_type: __u32,
}
pub mod bpf_cgroup_iter_order {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_CGROUP_ITER_ORDER_UNSPEC: Type = 0;
pub const BPF_CGROUP_ITER_SELF_ONLY: Type = 1;
pub const BPF_CGROUP_ITER_DESCENDANTS_PRE: Type = 2;
pub const BPF_CGROUP_ITER_DESCENDANTS_POST: Type = 3;
pub const BPF_CGROUP_ITER_ANCESTORS_UP: Type = 4;
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union bpf_iter_link_info {
pub map: bpf_iter_link_info__bindgen_ty_1,
pub cgroup: bpf_iter_link_info__bindgen_ty_2,
pub task: bpf_iter_link_info__bindgen_ty_3,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_iter_link_info__bindgen_ty_1 {
pub map_fd: __u32,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_iter_link_info__bindgen_ty_2 {
pub order: bpf_cgroup_iter_order::Type,
pub cgroup_fd: __u32,
pub cgroup_id: __u64,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_iter_link_info__bindgen_ty_3 {
pub tid: __u32,
pub pid: __u32,
pub pid_fd: __u32,
}
pub mod bpf_cmd {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_MAP_CREATE: Type = 0;
@ -424,6 +448,7 @@ pub mod bpf_map_type {
pub const BPF_MAP_TYPE_CPUMAP: Type = 16;
pub const BPF_MAP_TYPE_XSKMAP: Type = 17;
pub const BPF_MAP_TYPE_SOCKHASH: Type = 18;
pub const BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED: Type = 19;
pub const BPF_MAP_TYPE_CGROUP_STORAGE: Type = 19;
pub const BPF_MAP_TYPE_REUSEPORT_SOCKARRAY: Type = 20;
pub const BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE: Type = 21;
@ -436,6 +461,8 @@ pub mod bpf_map_type {
pub const BPF_MAP_TYPE_INODE_STORAGE: Type = 28;
pub const BPF_MAP_TYPE_TASK_STORAGE: Type = 29;
pub const BPF_MAP_TYPE_BLOOM_FILTER: Type = 30;
pub const BPF_MAP_TYPE_USER_RINGBUF: Type = 31;
pub const BPF_MAP_TYPE_CGRP_STORAGE: Type = 32;
}
pub mod bpf_prog_type {
pub type Type = ::aya_bpf_cty::c_uint;
@ -1067,7 +1094,10 @@ pub mod bpf_func_id {
pub const BPF_FUNC_tcp_raw_check_syncookie_ipv4: Type = 206;
pub const BPF_FUNC_tcp_raw_check_syncookie_ipv6: Type = 207;
pub const BPF_FUNC_ktime_get_tai_ns: Type = 208;
pub const __BPF_FUNC_MAX_ID: Type = 209;
pub const BPF_FUNC_user_ringbuf_drain: Type = 209;
pub const BPF_FUNC_cgrp_storage_get: Type = 210;
pub const BPF_FUNC_cgrp_storage_delete: Type = 211;
pub const __BPF_FUNC_MAX_ID: Type = 212;
}
pub const BPF_F_RECOMPUTE_CSUM: _bindgen_ty_4 = 1;
pub const BPF_F_INVALIDATE_HASH: _bindgen_ty_4 = 2;
@ -1091,51 +1121,54 @@ pub type _bindgen_ty_9 = ::aya_bpf_cty::c_uint;
pub const BPF_F_ZERO_CSUM_TX: _bindgen_ty_10 = 2;
pub const BPF_F_DONT_FRAGMENT: _bindgen_ty_10 = 4;
pub const BPF_F_SEQ_NUMBER: _bindgen_ty_10 = 8;
pub const BPF_F_NO_TUNNEL_KEY: _bindgen_ty_10 = 16;
pub type _bindgen_ty_10 = ::aya_bpf_cty::c_uint;
pub const BPF_F_INDEX_MASK: _bindgen_ty_11 = 4294967295;
pub const BPF_F_CURRENT_CPU: _bindgen_ty_11 = 4294967295;
pub const BPF_F_CTXLEN_MASK: _bindgen_ty_11 = 4503595332403200;
pub type _bindgen_ty_11 = ::aya_bpf_cty::c_ulonglong;
pub const BPF_F_CURRENT_NETNS: _bindgen_ty_12 = -1;
pub type _bindgen_ty_12 = ::aya_bpf_cty::c_int;
pub const BPF_CSUM_LEVEL_QUERY: _bindgen_ty_13 = 0;
pub const BPF_CSUM_LEVEL_INC: _bindgen_ty_13 = 1;
pub const BPF_CSUM_LEVEL_DEC: _bindgen_ty_13 = 2;
pub const BPF_CSUM_LEVEL_RESET: _bindgen_ty_13 = 3;
pub type _bindgen_ty_13 = ::aya_bpf_cty::c_uint;
pub const BPF_F_ADJ_ROOM_FIXED_GSO: _bindgen_ty_14 = 1;
pub const BPF_F_ADJ_ROOM_ENCAP_L3_IPV4: _bindgen_ty_14 = 2;
pub const BPF_F_ADJ_ROOM_ENCAP_L3_IPV6: _bindgen_ty_14 = 4;
pub const BPF_F_ADJ_ROOM_ENCAP_L4_GRE: _bindgen_ty_14 = 8;
pub const BPF_F_ADJ_ROOM_ENCAP_L4_UDP: _bindgen_ty_14 = 16;
pub const BPF_F_ADJ_ROOM_NO_CSUM_RESET: _bindgen_ty_14 = 32;
pub const BPF_F_ADJ_ROOM_ENCAP_L2_ETH: _bindgen_ty_14 = 64;
pub const BPF_F_TUNINFO_FLAGS: _bindgen_ty_11 = 16;
pub type _bindgen_ty_11 = ::aya_bpf_cty::c_uint;
pub const BPF_F_INDEX_MASK: _bindgen_ty_12 = 4294967295;
pub const BPF_F_CURRENT_CPU: _bindgen_ty_12 = 4294967295;
pub const BPF_F_CTXLEN_MASK: _bindgen_ty_12 = 4503595332403200;
pub type _bindgen_ty_12 = ::aya_bpf_cty::c_ulonglong;
pub const BPF_F_CURRENT_NETNS: _bindgen_ty_13 = -1;
pub type _bindgen_ty_13 = ::aya_bpf_cty::c_int;
pub const BPF_CSUM_LEVEL_QUERY: _bindgen_ty_14 = 0;
pub const BPF_CSUM_LEVEL_INC: _bindgen_ty_14 = 1;
pub const BPF_CSUM_LEVEL_DEC: _bindgen_ty_14 = 2;
pub const BPF_CSUM_LEVEL_RESET: _bindgen_ty_14 = 3;
pub type _bindgen_ty_14 = ::aya_bpf_cty::c_uint;
pub const BPF_ADJ_ROOM_ENCAP_L2_MASK: _bindgen_ty_15 = 255;
pub const BPF_ADJ_ROOM_ENCAP_L2_SHIFT: _bindgen_ty_15 = 56;
pub const BPF_F_ADJ_ROOM_FIXED_GSO: _bindgen_ty_15 = 1;
pub const BPF_F_ADJ_ROOM_ENCAP_L3_IPV4: _bindgen_ty_15 = 2;
pub const BPF_F_ADJ_ROOM_ENCAP_L3_IPV6: _bindgen_ty_15 = 4;
pub const BPF_F_ADJ_ROOM_ENCAP_L4_GRE: _bindgen_ty_15 = 8;
pub const BPF_F_ADJ_ROOM_ENCAP_L4_UDP: _bindgen_ty_15 = 16;
pub const BPF_F_ADJ_ROOM_NO_CSUM_RESET: _bindgen_ty_15 = 32;
pub const BPF_F_ADJ_ROOM_ENCAP_L2_ETH: _bindgen_ty_15 = 64;
pub type _bindgen_ty_15 = ::aya_bpf_cty::c_uint;
pub const BPF_F_SYSCTL_BASE_NAME: _bindgen_ty_16 = 1;
pub const BPF_ADJ_ROOM_ENCAP_L2_MASK: _bindgen_ty_16 = 255;
pub const BPF_ADJ_ROOM_ENCAP_L2_SHIFT: _bindgen_ty_16 = 56;
pub type _bindgen_ty_16 = ::aya_bpf_cty::c_uint;
pub const BPF_LOCAL_STORAGE_GET_F_CREATE: _bindgen_ty_17 = 1;
pub const BPF_SK_STORAGE_GET_F_CREATE: _bindgen_ty_17 = 1;
pub const BPF_F_SYSCTL_BASE_NAME: _bindgen_ty_17 = 1;
pub type _bindgen_ty_17 = ::aya_bpf_cty::c_uint;
pub const BPF_F_GET_BRANCH_RECORDS_SIZE: _bindgen_ty_18 = 1;
pub const BPF_LOCAL_STORAGE_GET_F_CREATE: _bindgen_ty_18 = 1;
pub const BPF_SK_STORAGE_GET_F_CREATE: _bindgen_ty_18 = 1;
pub type _bindgen_ty_18 = ::aya_bpf_cty::c_uint;
pub const BPF_RB_NO_WAKEUP: _bindgen_ty_19 = 1;
pub const BPF_RB_FORCE_WAKEUP: _bindgen_ty_19 = 2;
pub const BPF_F_GET_BRANCH_RECORDS_SIZE: _bindgen_ty_19 = 1;
pub type _bindgen_ty_19 = ::aya_bpf_cty::c_uint;
pub const BPF_RB_AVAIL_DATA: _bindgen_ty_20 = 0;
pub const BPF_RB_RING_SIZE: _bindgen_ty_20 = 1;
pub const BPF_RB_CONS_POS: _bindgen_ty_20 = 2;
pub const BPF_RB_PROD_POS: _bindgen_ty_20 = 3;
pub const BPF_RB_NO_WAKEUP: _bindgen_ty_20 = 1;
pub const BPF_RB_FORCE_WAKEUP: _bindgen_ty_20 = 2;
pub type _bindgen_ty_20 = ::aya_bpf_cty::c_uint;
pub const BPF_RINGBUF_BUSY_BIT: _bindgen_ty_21 = 2147483648;
pub const BPF_RINGBUF_DISCARD_BIT: _bindgen_ty_21 = 1073741824;
pub const BPF_RINGBUF_HDR_SZ: _bindgen_ty_21 = 8;
pub const BPF_RB_AVAIL_DATA: _bindgen_ty_21 = 0;
pub const BPF_RB_RING_SIZE: _bindgen_ty_21 = 1;
pub const BPF_RB_CONS_POS: _bindgen_ty_21 = 2;
pub const BPF_RB_PROD_POS: _bindgen_ty_21 = 3;
pub type _bindgen_ty_21 = ::aya_bpf_cty::c_uint;
pub const BPF_SK_LOOKUP_F_REPLACE: _bindgen_ty_22 = 1;
pub const BPF_SK_LOOKUP_F_NO_REUSEPORT: _bindgen_ty_22 = 2;
pub const BPF_RINGBUF_BUSY_BIT: _bindgen_ty_22 = 2147483648;
pub const BPF_RINGBUF_DISCARD_BIT: _bindgen_ty_22 = 1073741824;
pub const BPF_RINGBUF_HDR_SZ: _bindgen_ty_22 = 8;
pub type _bindgen_ty_22 = ::aya_bpf_cty::c_uint;
pub const BPF_SK_LOOKUP_F_REPLACE: _bindgen_ty_23 = 1;
pub const BPF_SK_LOOKUP_F_NO_REUSEPORT: _bindgen_ty_23 = 2;
pub type _bindgen_ty_23 = ::aya_bpf_cty::c_uint;
pub mod bpf_adj_room_mode {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_ADJ_ROOM_NET: Type = 0;
@ -1152,12 +1185,12 @@ pub mod bpf_lwt_encap_mode {
pub const BPF_LWT_ENCAP_SEG6_INLINE: Type = 1;
pub const BPF_LWT_ENCAP_IP: Type = 2;
}
pub const BPF_F_BPRM_SECUREEXEC: _bindgen_ty_23 = 1;
pub type _bindgen_ty_23 = ::aya_bpf_cty::c_uint;
pub const BPF_F_BROADCAST: _bindgen_ty_24 = 8;
pub const BPF_F_EXCLUDE_INGRESS: _bindgen_ty_24 = 16;
pub const BPF_F_BPRM_SECUREEXEC: _bindgen_ty_24 = 1;
pub type _bindgen_ty_24 = ::aya_bpf_cty::c_uint;
pub mod _bindgen_ty_25 {
pub const BPF_F_BROADCAST: _bindgen_ty_25 = 8;
pub const BPF_F_EXCLUDE_INGRESS: _bindgen_ty_25 = 16;
pub type _bindgen_ty_25 = ::aya_bpf_cty::c_uint;
pub mod _bindgen_ty_26 {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_SKB_TSTAMP_UNSPEC: Type = 0;
pub const BPF_SKB_TSTAMP_DELIVERY_MONO: Type = 1;
@ -1246,9 +1279,9 @@ pub struct bpf_tunnel_key {
pub __bindgen_anon_1: bpf_tunnel_key__bindgen_ty_1,
pub tunnel_tos: __u8,
pub tunnel_ttl: __u8,
pub tunnel_ext: __u16,
pub tunnel_label: __u32,
pub __bindgen_anon_2: bpf_tunnel_key__bindgen_ty_2,
pub tunnel_label: __u32,
pub __bindgen_anon_3: bpf_tunnel_key__bindgen_ty_3,
}
#[repr(C)]
#[derive(Copy, Clone)]
@ -1259,6 +1292,12 @@ pub union bpf_tunnel_key__bindgen_ty_1 {
#[repr(C)]
#[derive(Copy, Clone)]
pub union bpf_tunnel_key__bindgen_ty_2 {
pub tunnel_ext: __u16,
pub tunnel_flags: __be16,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union bpf_tunnel_key__bindgen_ty_3 {
pub local_ipv4: __u32,
pub local_ipv6: [__u32; 4usize],
}
@ -1283,6 +1322,7 @@ pub mod bpf_ret_code {
pub const BPF_DROP: Type = 2;
pub const BPF_REDIRECT: Type = 7;
pub const BPF_LWT_REROUTE: Type = 128;
pub const BPF_FLOW_DISSECTOR_CONTINUE: Type = 129;
}
#[repr(C)]
#[derive(Copy, Clone)]
@ -1699,6 +1739,7 @@ pub struct bpf_link_info__bindgen_ty_1__bindgen_ty_4 {
pub target_name: __u64,
pub target_name_len: __u32,
pub __bindgen_anon_1: bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_1,
pub __bindgen_anon_2: bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2,
}
#[repr(C)]
#[derive(Copy, Clone)]
@ -1712,6 +1753,24 @@ pub struct bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_1__bindgen_ty_1
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2 {
pub cgroup: bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2__bindgen_ty_1,
pub task: bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2__bindgen_ty_2,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2__bindgen_ty_1 {
pub cgroup_id: __u64,
pub order: __u32,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2__bindgen_ty_2 {
pub tid: __u32,
pub pid: __u32,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_link_info__bindgen_ty_1__bindgen_ty_5 {
pub netns_ino: __u32,
pub attach_type: __u32,
@ -1793,6 +1852,7 @@ pub struct bpf_sock_ops {
pub __bindgen_anon_4: bpf_sock_ops__bindgen_ty_4,
pub skb_len: __u32,
pub skb_tcp_flags: __u32,
pub skb_hwtstamp: __u64,
}
#[repr(C)]
#[derive(Copy, Clone)]
@ -1846,51 +1906,51 @@ impl bpf_sock_ops__bindgen_ty_4 {
__bindgen_bitfield_unit
}
}
pub const BPF_SOCK_OPS_RTO_CB_FLAG: _bindgen_ty_26 = 1;
pub const BPF_SOCK_OPS_RETRANS_CB_FLAG: _bindgen_ty_26 = 2;
pub const BPF_SOCK_OPS_STATE_CB_FLAG: _bindgen_ty_26 = 4;
pub const BPF_SOCK_OPS_RTT_CB_FLAG: _bindgen_ty_26 = 8;
pub const BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG: _bindgen_ty_26 = 16;
pub const BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG: _bindgen_ty_26 = 32;
pub const BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG: _bindgen_ty_26 = 64;
pub const BPF_SOCK_OPS_ALL_CB_FLAGS: _bindgen_ty_26 = 127;
pub type _bindgen_ty_26 = ::aya_bpf_cty::c_uint;
pub const BPF_SOCK_OPS_VOID: _bindgen_ty_27 = 0;
pub const BPF_SOCK_OPS_TIMEOUT_INIT: _bindgen_ty_27 = 1;
pub const BPF_SOCK_OPS_RWND_INIT: _bindgen_ty_27 = 2;
pub const BPF_SOCK_OPS_TCP_CONNECT_CB: _bindgen_ty_27 = 3;
pub const BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB: _bindgen_ty_27 = 4;
pub const BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB: _bindgen_ty_27 = 5;
pub const BPF_SOCK_OPS_NEEDS_ECN: _bindgen_ty_27 = 6;
pub const BPF_SOCK_OPS_BASE_RTT: _bindgen_ty_27 = 7;
pub const BPF_SOCK_OPS_RTO_CB: _bindgen_ty_27 = 8;
pub const BPF_SOCK_OPS_RETRANS_CB: _bindgen_ty_27 = 9;
pub const BPF_SOCK_OPS_STATE_CB: _bindgen_ty_27 = 10;
pub const BPF_SOCK_OPS_TCP_LISTEN_CB: _bindgen_ty_27 = 11;
pub const BPF_SOCK_OPS_RTT_CB: _bindgen_ty_27 = 12;
pub const BPF_SOCK_OPS_PARSE_HDR_OPT_CB: _bindgen_ty_27 = 13;
pub const BPF_SOCK_OPS_HDR_OPT_LEN_CB: _bindgen_ty_27 = 14;
pub const BPF_SOCK_OPS_WRITE_HDR_OPT_CB: _bindgen_ty_27 = 15;
pub const BPF_SOCK_OPS_RTO_CB_FLAG: _bindgen_ty_27 = 1;
pub const BPF_SOCK_OPS_RETRANS_CB_FLAG: _bindgen_ty_27 = 2;
pub const BPF_SOCK_OPS_STATE_CB_FLAG: _bindgen_ty_27 = 4;
pub const BPF_SOCK_OPS_RTT_CB_FLAG: _bindgen_ty_27 = 8;
pub const BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG: _bindgen_ty_27 = 16;
pub const BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG: _bindgen_ty_27 = 32;
pub const BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG: _bindgen_ty_27 = 64;
pub const BPF_SOCK_OPS_ALL_CB_FLAGS: _bindgen_ty_27 = 127;
pub type _bindgen_ty_27 = ::aya_bpf_cty::c_uint;
pub const BPF_TCP_ESTABLISHED: _bindgen_ty_28 = 1;
pub const BPF_TCP_SYN_SENT: _bindgen_ty_28 = 2;
pub const BPF_TCP_SYN_RECV: _bindgen_ty_28 = 3;
pub const BPF_TCP_FIN_WAIT1: _bindgen_ty_28 = 4;
pub const BPF_TCP_FIN_WAIT2: _bindgen_ty_28 = 5;
pub const BPF_TCP_TIME_WAIT: _bindgen_ty_28 = 6;
pub const BPF_TCP_CLOSE: _bindgen_ty_28 = 7;
pub const BPF_TCP_CLOSE_WAIT: _bindgen_ty_28 = 8;
pub const BPF_TCP_LAST_ACK: _bindgen_ty_28 = 9;
pub const BPF_TCP_LISTEN: _bindgen_ty_28 = 10;
pub const BPF_TCP_CLOSING: _bindgen_ty_28 = 11;
pub const BPF_TCP_NEW_SYN_RECV: _bindgen_ty_28 = 12;
pub const BPF_TCP_MAX_STATES: _bindgen_ty_28 = 13;
pub const BPF_SOCK_OPS_VOID: _bindgen_ty_28 = 0;
pub const BPF_SOCK_OPS_TIMEOUT_INIT: _bindgen_ty_28 = 1;
pub const BPF_SOCK_OPS_RWND_INIT: _bindgen_ty_28 = 2;
pub const BPF_SOCK_OPS_TCP_CONNECT_CB: _bindgen_ty_28 = 3;
pub const BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB: _bindgen_ty_28 = 4;
pub const BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB: _bindgen_ty_28 = 5;
pub const BPF_SOCK_OPS_NEEDS_ECN: _bindgen_ty_28 = 6;
pub const BPF_SOCK_OPS_BASE_RTT: _bindgen_ty_28 = 7;
pub const BPF_SOCK_OPS_RTO_CB: _bindgen_ty_28 = 8;
pub const BPF_SOCK_OPS_RETRANS_CB: _bindgen_ty_28 = 9;
pub const BPF_SOCK_OPS_STATE_CB: _bindgen_ty_28 = 10;
pub const BPF_SOCK_OPS_TCP_LISTEN_CB: _bindgen_ty_28 = 11;
pub const BPF_SOCK_OPS_RTT_CB: _bindgen_ty_28 = 12;
pub const BPF_SOCK_OPS_PARSE_HDR_OPT_CB: _bindgen_ty_28 = 13;
pub const BPF_SOCK_OPS_HDR_OPT_LEN_CB: _bindgen_ty_28 = 14;
pub const BPF_SOCK_OPS_WRITE_HDR_OPT_CB: _bindgen_ty_28 = 15;
pub type _bindgen_ty_28 = ::aya_bpf_cty::c_uint;
pub mod _bindgen_ty_30 {
pub const BPF_TCP_ESTABLISHED: _bindgen_ty_29 = 1;
pub const BPF_TCP_SYN_SENT: _bindgen_ty_29 = 2;
pub const BPF_TCP_SYN_RECV: _bindgen_ty_29 = 3;
pub const BPF_TCP_FIN_WAIT1: _bindgen_ty_29 = 4;
pub const BPF_TCP_FIN_WAIT2: _bindgen_ty_29 = 5;
pub const BPF_TCP_TIME_WAIT: _bindgen_ty_29 = 6;
pub const BPF_TCP_CLOSE: _bindgen_ty_29 = 7;
pub const BPF_TCP_CLOSE_WAIT: _bindgen_ty_29 = 8;
pub const BPF_TCP_LAST_ACK: _bindgen_ty_29 = 9;
pub const BPF_TCP_LISTEN: _bindgen_ty_29 = 10;
pub const BPF_TCP_CLOSING: _bindgen_ty_29 = 11;
pub const BPF_TCP_NEW_SYN_RECV: _bindgen_ty_29 = 12;
pub const BPF_TCP_MAX_STATES: _bindgen_ty_29 = 13;
pub type _bindgen_ty_29 = ::aya_bpf_cty::c_uint;
pub mod _bindgen_ty_31 {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_LOAD_HDR_OPT_TCP_SYN: Type = 1;
}
pub mod _bindgen_ty_31 {
pub mod _bindgen_ty_32 {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_WRITE_HDR_TCP_CURRENT_MSS: Type = 1;
pub const BPF_WRITE_HDR_TCP_SYNACK_COOKIE: Type = 2;
@ -1902,13 +1962,13 @@ pub struct bpf_perf_event_value {
pub enabled: __u64,
pub running: __u64,
}
pub const BPF_DEVCG_ACC_MKNOD: _bindgen_ty_32 = 1;
pub const BPF_DEVCG_ACC_READ: _bindgen_ty_32 = 2;
pub const BPF_DEVCG_ACC_WRITE: _bindgen_ty_32 = 4;
pub type _bindgen_ty_32 = ::aya_bpf_cty::c_uint;
pub const BPF_DEVCG_DEV_BLOCK: _bindgen_ty_33 = 1;
pub const BPF_DEVCG_DEV_CHAR: _bindgen_ty_33 = 2;
pub const BPF_DEVCG_ACC_MKNOD: _bindgen_ty_33 = 1;
pub const BPF_DEVCG_ACC_READ: _bindgen_ty_33 = 2;
pub const BPF_DEVCG_ACC_WRITE: _bindgen_ty_33 = 4;
pub type _bindgen_ty_33 = ::aya_bpf_cty::c_uint;
pub const BPF_DEVCG_DEV_BLOCK: _bindgen_ty_34 = 1;
pub const BPF_DEVCG_DEV_CHAR: _bindgen_ty_34 = 2;
pub type _bindgen_ty_34 = ::aya_bpf_cty::c_uint;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_cgroup_dev_ctx {
@ -1920,19 +1980,19 @@ pub struct bpf_cgroup_dev_ctx {
pub struct bpf_raw_tracepoint_args {
pub args: __IncompleteArrayField<__u64>,
}
pub const BPF_FIB_LOOKUP_DIRECT: _bindgen_ty_34 = 1;
pub const BPF_FIB_LOOKUP_OUTPUT: _bindgen_ty_34 = 2;
pub type _bindgen_ty_34 = ::aya_bpf_cty::c_uint;
pub const BPF_FIB_LKUP_RET_SUCCESS: _bindgen_ty_35 = 0;
pub const BPF_FIB_LKUP_RET_BLACKHOLE: _bindgen_ty_35 = 1;
pub const BPF_FIB_LKUP_RET_UNREACHABLE: _bindgen_ty_35 = 2;
pub const BPF_FIB_LKUP_RET_PROHIBIT: _bindgen_ty_35 = 3;
pub const BPF_FIB_LKUP_RET_NOT_FWDED: _bindgen_ty_35 = 4;
pub const BPF_FIB_LKUP_RET_FWD_DISABLED: _bindgen_ty_35 = 5;
pub const BPF_FIB_LKUP_RET_UNSUPP_LWT: _bindgen_ty_35 = 6;
pub const BPF_FIB_LKUP_RET_NO_NEIGH: _bindgen_ty_35 = 7;
pub const BPF_FIB_LKUP_RET_FRAG_NEEDED: _bindgen_ty_35 = 8;
pub const BPF_FIB_LOOKUP_DIRECT: _bindgen_ty_35 = 1;
pub const BPF_FIB_LOOKUP_OUTPUT: _bindgen_ty_35 = 2;
pub type _bindgen_ty_35 = ::aya_bpf_cty::c_uint;
pub const BPF_FIB_LKUP_RET_SUCCESS: _bindgen_ty_36 = 0;
pub const BPF_FIB_LKUP_RET_BLACKHOLE: _bindgen_ty_36 = 1;
pub const BPF_FIB_LKUP_RET_UNREACHABLE: _bindgen_ty_36 = 2;
pub const BPF_FIB_LKUP_RET_PROHIBIT: _bindgen_ty_36 = 3;
pub const BPF_FIB_LKUP_RET_NOT_FWDED: _bindgen_ty_36 = 4;
pub const BPF_FIB_LKUP_RET_FWD_DISABLED: _bindgen_ty_36 = 5;
pub const BPF_FIB_LKUP_RET_UNSUPP_LWT: _bindgen_ty_36 = 6;
pub const BPF_FIB_LKUP_RET_NO_NEIGH: _bindgen_ty_36 = 7;
pub const BPF_FIB_LKUP_RET_FRAG_NEEDED: _bindgen_ty_36 = 8;
pub type _bindgen_ty_36 = ::aya_bpf_cty::c_uint;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_fib_lookup {
@ -2006,10 +2066,10 @@ pub mod bpf_task_fd_type {
pub const BPF_FD_TYPE_UPROBE: Type = 4;
pub const BPF_FD_TYPE_URETPROBE: Type = 5;
}
pub const BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG: _bindgen_ty_36 = 1;
pub const BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL: _bindgen_ty_36 = 2;
pub const BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP: _bindgen_ty_36 = 4;
pub type _bindgen_ty_36 = ::aya_bpf_cty::c_uint;
pub const BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG: _bindgen_ty_37 = 1;
pub const BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL: _bindgen_ty_37 = 2;
pub const BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP: _bindgen_ty_37 = 4;
pub type _bindgen_ty_37 = ::aya_bpf_cty::c_uint;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_flow_keys {
@ -2093,6 +2153,34 @@ impl bpf_dynptr {
}
}
#[repr(C)]
#[repr(align(8))]
#[derive(Copy, Clone)]
pub struct bpf_list_head {
pub _bitfield_align_1: [u8; 0],
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize]>,
}
impl bpf_list_head {
#[inline]
pub fn new_bitfield_1() -> __BindgenBitfieldUnit<[u8; 16usize]> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 16usize]> = Default::default();
__bindgen_bitfield_unit
}
}
#[repr(C)]
#[repr(align(8))]
#[derive(Copy, Clone)]
pub struct bpf_list_node {
pub _bitfield_align_1: [u8; 0],
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize]>,
}
impl bpf_list_node {
#[inline]
pub fn new_bitfield_1() -> __BindgenBitfieldUnit<[u8; 16usize]> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 16usize]> = Default::default();
__bindgen_bitfield_unit
}
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_sysctl {
pub write: __u32,
@ -2304,6 +2392,11 @@ pub struct task_struct {
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct cgroup {
_unused: [u8; 0],
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct path {
_unused: [u8; 0],
}

@ -461,12 +461,12 @@ pub unsafe fn bpf_skb_adjust_room(
}
pub unsafe fn bpf_redirect_map(
map: *mut ::aya_bpf_cty::c_void,
key: __u32,
key: __u64,
flags: __u64,
) -> ::aya_bpf_cty::c_long {
let fun: unsafe extern "C" fn(
map: *mut ::aya_bpf_cty::c_void,
key: __u32,
key: __u64,
flags: __u64,
) -> ::aya_bpf_cty::c_long = ::core::mem::transmute(51usize);
fun(map, key, flags)
@ -2027,28 +2027,28 @@ pub unsafe fn bpf_ringbuf_discard_dynptr(ptr: *mut bpf_dynptr, flags: __u64) {
pub unsafe fn bpf_dynptr_read(
dst: *mut ::aya_bpf_cty::c_void,
len: __u32,
src: *mut bpf_dynptr,
src: *const bpf_dynptr,
offset: __u32,
flags: __u64,
) -> ::aya_bpf_cty::c_long {
let fun: unsafe extern "C" fn(
dst: *mut ::aya_bpf_cty::c_void,
len: __u32,
src: *mut bpf_dynptr,
src: *const bpf_dynptr,
offset: __u32,
flags: __u64,
) -> ::aya_bpf_cty::c_long = ::core::mem::transmute(201usize);
fun(dst, len, src, offset, flags)
}
pub unsafe fn bpf_dynptr_write(
dst: *mut bpf_dynptr,
dst: *const bpf_dynptr,
offset: __u32,
src: *mut ::aya_bpf_cty::c_void,
len: __u32,
flags: __u64,
) -> ::aya_bpf_cty::c_long {
let fun: unsafe extern "C" fn(
dst: *mut bpf_dynptr,
dst: *const bpf_dynptr,
offset: __u32,
src: *mut ::aya_bpf_cty::c_void,
len: __u32,
@ -2057,12 +2057,12 @@ pub unsafe fn bpf_dynptr_write(
fun(dst, offset, src, len, flags)
}
pub unsafe fn bpf_dynptr_data(
ptr: *mut bpf_dynptr,
ptr: *const bpf_dynptr,
offset: __u32,
len: __u32,
) -> *mut ::aya_bpf_cty::c_void {
let fun: unsafe extern "C" fn(
ptr: *mut bpf_dynptr,
ptr: *const bpf_dynptr,
offset: __u32,
len: __u32,
) -> *mut ::aya_bpf_cty::c_void = ::core::mem::transmute(203usize);
@ -2106,3 +2106,41 @@ pub unsafe fn bpf_ktime_get_tai_ns() -> __u64 {
let fun: unsafe extern "C" fn() -> __u64 = ::core::mem::transmute(208usize);
fun()
}
pub unsafe fn bpf_user_ringbuf_drain(
map: *mut ::aya_bpf_cty::c_void,
callback_fn: *mut ::aya_bpf_cty::c_void,
ctx: *mut ::aya_bpf_cty::c_void,
flags: __u64,
) -> ::aya_bpf_cty::c_long {
let fun: unsafe extern "C" fn(
map: *mut ::aya_bpf_cty::c_void,
callback_fn: *mut ::aya_bpf_cty::c_void,
ctx: *mut ::aya_bpf_cty::c_void,
flags: __u64,
) -> ::aya_bpf_cty::c_long = ::core::mem::transmute(209usize);
fun(map, callback_fn, ctx, flags)
}
pub unsafe fn bpf_cgrp_storage_get(
map: *mut ::aya_bpf_cty::c_void,
cgroup: *mut cgroup,
value: *mut ::aya_bpf_cty::c_void,
flags: __u64,
) -> *mut ::aya_bpf_cty::c_void {
let fun: unsafe extern "C" fn(
map: *mut ::aya_bpf_cty::c_void,
cgroup: *mut cgroup,
value: *mut ::aya_bpf_cty::c_void,
flags: __u64,
) -> *mut ::aya_bpf_cty::c_void = ::core::mem::transmute(210usize);
fun(map, cgroup, value, flags)
}
pub unsafe fn bpf_cgrp_storage_delete(
map: *mut ::aya_bpf_cty::c_void,
cgroup: *mut cgroup,
) -> ::aya_bpf_cty::c_long {
let fun: unsafe extern "C" fn(
map: *mut ::aya_bpf_cty::c_void,
cgroup: *mut cgroup,
) -> ::aya_bpf_cty::c_long = ::core::mem::transmute(211usize);
fun(map, cgroup)
}

@ -358,16 +358,40 @@ pub struct bpf_cgroup_storage_key {
pub cgroup_inode_id: __u64,
pub attach_type: __u32,
}
pub mod bpf_cgroup_iter_order {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_CGROUP_ITER_ORDER_UNSPEC: Type = 0;
pub const BPF_CGROUP_ITER_SELF_ONLY: Type = 1;
pub const BPF_CGROUP_ITER_DESCENDANTS_PRE: Type = 2;
pub const BPF_CGROUP_ITER_DESCENDANTS_POST: Type = 3;
pub const BPF_CGROUP_ITER_ANCESTORS_UP: Type = 4;
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union bpf_iter_link_info {
pub map: bpf_iter_link_info__bindgen_ty_1,
pub cgroup: bpf_iter_link_info__bindgen_ty_2,
pub task: bpf_iter_link_info__bindgen_ty_3,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_iter_link_info__bindgen_ty_1 {
pub map_fd: __u32,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_iter_link_info__bindgen_ty_2 {
pub order: bpf_cgroup_iter_order::Type,
pub cgroup_fd: __u32,
pub cgroup_id: __u64,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_iter_link_info__bindgen_ty_3 {
pub tid: __u32,
pub pid: __u32,
pub pid_fd: __u32,
}
pub mod bpf_cmd {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_MAP_CREATE: Type = 0;
@ -429,6 +453,7 @@ pub mod bpf_map_type {
pub const BPF_MAP_TYPE_CPUMAP: Type = 16;
pub const BPF_MAP_TYPE_XSKMAP: Type = 17;
pub const BPF_MAP_TYPE_SOCKHASH: Type = 18;
pub const BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED: Type = 19;
pub const BPF_MAP_TYPE_CGROUP_STORAGE: Type = 19;
pub const BPF_MAP_TYPE_REUSEPORT_SOCKARRAY: Type = 20;
pub const BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE: Type = 21;
@ -441,6 +466,8 @@ pub mod bpf_map_type {
pub const BPF_MAP_TYPE_INODE_STORAGE: Type = 28;
pub const BPF_MAP_TYPE_TASK_STORAGE: Type = 29;
pub const BPF_MAP_TYPE_BLOOM_FILTER: Type = 30;
pub const BPF_MAP_TYPE_USER_RINGBUF: Type = 31;
pub const BPF_MAP_TYPE_CGRP_STORAGE: Type = 32;
}
pub mod bpf_prog_type {
pub type Type = ::aya_bpf_cty::c_uint;
@ -1072,7 +1099,10 @@ pub mod bpf_func_id {
pub const BPF_FUNC_tcp_raw_check_syncookie_ipv4: Type = 206;
pub const BPF_FUNC_tcp_raw_check_syncookie_ipv6: Type = 207;
pub const BPF_FUNC_ktime_get_tai_ns: Type = 208;
pub const __BPF_FUNC_MAX_ID: Type = 209;
pub const BPF_FUNC_user_ringbuf_drain: Type = 209;
pub const BPF_FUNC_cgrp_storage_get: Type = 210;
pub const BPF_FUNC_cgrp_storage_delete: Type = 211;
pub const __BPF_FUNC_MAX_ID: Type = 212;
}
pub const BPF_F_RECOMPUTE_CSUM: _bindgen_ty_4 = 1;
pub const BPF_F_INVALIDATE_HASH: _bindgen_ty_4 = 2;
@ -1096,51 +1126,54 @@ pub type _bindgen_ty_9 = ::aya_bpf_cty::c_uint;
pub const BPF_F_ZERO_CSUM_TX: _bindgen_ty_10 = 2;
pub const BPF_F_DONT_FRAGMENT: _bindgen_ty_10 = 4;
pub const BPF_F_SEQ_NUMBER: _bindgen_ty_10 = 8;
pub const BPF_F_NO_TUNNEL_KEY: _bindgen_ty_10 = 16;
pub type _bindgen_ty_10 = ::aya_bpf_cty::c_uint;
pub const BPF_F_INDEX_MASK: _bindgen_ty_11 = 4294967295;
pub const BPF_F_CURRENT_CPU: _bindgen_ty_11 = 4294967295;
pub const BPF_F_CTXLEN_MASK: _bindgen_ty_11 = 4503595332403200;
pub type _bindgen_ty_11 = ::aya_bpf_cty::c_ulong;
pub const BPF_F_CURRENT_NETNS: _bindgen_ty_12 = -1;
pub type _bindgen_ty_12 = ::aya_bpf_cty::c_int;
pub const BPF_CSUM_LEVEL_QUERY: _bindgen_ty_13 = 0;
pub const BPF_CSUM_LEVEL_INC: _bindgen_ty_13 = 1;
pub const BPF_CSUM_LEVEL_DEC: _bindgen_ty_13 = 2;
pub const BPF_CSUM_LEVEL_RESET: _bindgen_ty_13 = 3;
pub type _bindgen_ty_13 = ::aya_bpf_cty::c_uint;
pub const BPF_F_ADJ_ROOM_FIXED_GSO: _bindgen_ty_14 = 1;
pub const BPF_F_ADJ_ROOM_ENCAP_L3_IPV4: _bindgen_ty_14 = 2;
pub const BPF_F_ADJ_ROOM_ENCAP_L3_IPV6: _bindgen_ty_14 = 4;
pub const BPF_F_ADJ_ROOM_ENCAP_L4_GRE: _bindgen_ty_14 = 8;
pub const BPF_F_ADJ_ROOM_ENCAP_L4_UDP: _bindgen_ty_14 = 16;
pub const BPF_F_ADJ_ROOM_NO_CSUM_RESET: _bindgen_ty_14 = 32;
pub const BPF_F_ADJ_ROOM_ENCAP_L2_ETH: _bindgen_ty_14 = 64;
pub const BPF_F_TUNINFO_FLAGS: _bindgen_ty_11 = 16;
pub type _bindgen_ty_11 = ::aya_bpf_cty::c_uint;
pub const BPF_F_INDEX_MASK: _bindgen_ty_12 = 4294967295;
pub const BPF_F_CURRENT_CPU: _bindgen_ty_12 = 4294967295;
pub const BPF_F_CTXLEN_MASK: _bindgen_ty_12 = 4503595332403200;
pub type _bindgen_ty_12 = ::aya_bpf_cty::c_ulong;
pub const BPF_F_CURRENT_NETNS: _bindgen_ty_13 = -1;
pub type _bindgen_ty_13 = ::aya_bpf_cty::c_int;
pub const BPF_CSUM_LEVEL_QUERY: _bindgen_ty_14 = 0;
pub const BPF_CSUM_LEVEL_INC: _bindgen_ty_14 = 1;
pub const BPF_CSUM_LEVEL_DEC: _bindgen_ty_14 = 2;
pub const BPF_CSUM_LEVEL_RESET: _bindgen_ty_14 = 3;
pub type _bindgen_ty_14 = ::aya_bpf_cty::c_uint;
pub const BPF_ADJ_ROOM_ENCAP_L2_MASK: _bindgen_ty_15 = 255;
pub const BPF_ADJ_ROOM_ENCAP_L2_SHIFT: _bindgen_ty_15 = 56;
pub const BPF_F_ADJ_ROOM_FIXED_GSO: _bindgen_ty_15 = 1;
pub const BPF_F_ADJ_ROOM_ENCAP_L3_IPV4: _bindgen_ty_15 = 2;
pub const BPF_F_ADJ_ROOM_ENCAP_L3_IPV6: _bindgen_ty_15 = 4;
pub const BPF_F_ADJ_ROOM_ENCAP_L4_GRE: _bindgen_ty_15 = 8;
pub const BPF_F_ADJ_ROOM_ENCAP_L4_UDP: _bindgen_ty_15 = 16;
pub const BPF_F_ADJ_ROOM_NO_CSUM_RESET: _bindgen_ty_15 = 32;
pub const BPF_F_ADJ_ROOM_ENCAP_L2_ETH: _bindgen_ty_15 = 64;
pub type _bindgen_ty_15 = ::aya_bpf_cty::c_uint;
pub const BPF_F_SYSCTL_BASE_NAME: _bindgen_ty_16 = 1;
pub const BPF_ADJ_ROOM_ENCAP_L2_MASK: _bindgen_ty_16 = 255;
pub const BPF_ADJ_ROOM_ENCAP_L2_SHIFT: _bindgen_ty_16 = 56;
pub type _bindgen_ty_16 = ::aya_bpf_cty::c_uint;
pub const BPF_LOCAL_STORAGE_GET_F_CREATE: _bindgen_ty_17 = 1;
pub const BPF_SK_STORAGE_GET_F_CREATE: _bindgen_ty_17 = 1;
pub const BPF_F_SYSCTL_BASE_NAME: _bindgen_ty_17 = 1;
pub type _bindgen_ty_17 = ::aya_bpf_cty::c_uint;
pub const BPF_F_GET_BRANCH_RECORDS_SIZE: _bindgen_ty_18 = 1;
pub const BPF_LOCAL_STORAGE_GET_F_CREATE: _bindgen_ty_18 = 1;
pub const BPF_SK_STORAGE_GET_F_CREATE: _bindgen_ty_18 = 1;
pub type _bindgen_ty_18 = ::aya_bpf_cty::c_uint;
pub const BPF_RB_NO_WAKEUP: _bindgen_ty_19 = 1;
pub const BPF_RB_FORCE_WAKEUP: _bindgen_ty_19 = 2;
pub const BPF_F_GET_BRANCH_RECORDS_SIZE: _bindgen_ty_19 = 1;
pub type _bindgen_ty_19 = ::aya_bpf_cty::c_uint;
pub const BPF_RB_AVAIL_DATA: _bindgen_ty_20 = 0;
pub const BPF_RB_RING_SIZE: _bindgen_ty_20 = 1;
pub const BPF_RB_CONS_POS: _bindgen_ty_20 = 2;
pub const BPF_RB_PROD_POS: _bindgen_ty_20 = 3;
pub const BPF_RB_NO_WAKEUP: _bindgen_ty_20 = 1;
pub const BPF_RB_FORCE_WAKEUP: _bindgen_ty_20 = 2;
pub type _bindgen_ty_20 = ::aya_bpf_cty::c_uint;
pub const BPF_RINGBUF_BUSY_BIT: _bindgen_ty_21 = 2147483648;
pub const BPF_RINGBUF_DISCARD_BIT: _bindgen_ty_21 = 1073741824;
pub const BPF_RINGBUF_HDR_SZ: _bindgen_ty_21 = 8;
pub const BPF_RB_AVAIL_DATA: _bindgen_ty_21 = 0;
pub const BPF_RB_RING_SIZE: _bindgen_ty_21 = 1;
pub const BPF_RB_CONS_POS: _bindgen_ty_21 = 2;
pub const BPF_RB_PROD_POS: _bindgen_ty_21 = 3;
pub type _bindgen_ty_21 = ::aya_bpf_cty::c_uint;
pub const BPF_SK_LOOKUP_F_REPLACE: _bindgen_ty_22 = 1;
pub const BPF_SK_LOOKUP_F_NO_REUSEPORT: _bindgen_ty_22 = 2;
pub const BPF_RINGBUF_BUSY_BIT: _bindgen_ty_22 = 2147483648;
pub const BPF_RINGBUF_DISCARD_BIT: _bindgen_ty_22 = 1073741824;
pub const BPF_RINGBUF_HDR_SZ: _bindgen_ty_22 = 8;
pub type _bindgen_ty_22 = ::aya_bpf_cty::c_uint;
pub const BPF_SK_LOOKUP_F_REPLACE: _bindgen_ty_23 = 1;
pub const BPF_SK_LOOKUP_F_NO_REUSEPORT: _bindgen_ty_23 = 2;
pub type _bindgen_ty_23 = ::aya_bpf_cty::c_uint;
pub mod bpf_adj_room_mode {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_ADJ_ROOM_NET: Type = 0;
@ -1157,12 +1190,12 @@ pub mod bpf_lwt_encap_mode {
pub const BPF_LWT_ENCAP_SEG6_INLINE: Type = 1;
pub const BPF_LWT_ENCAP_IP: Type = 2;
}
pub const BPF_F_BPRM_SECUREEXEC: _bindgen_ty_23 = 1;
pub type _bindgen_ty_23 = ::aya_bpf_cty::c_uint;
pub const BPF_F_BROADCAST: _bindgen_ty_24 = 8;
pub const BPF_F_EXCLUDE_INGRESS: _bindgen_ty_24 = 16;
pub const BPF_F_BPRM_SECUREEXEC: _bindgen_ty_24 = 1;
pub type _bindgen_ty_24 = ::aya_bpf_cty::c_uint;
pub mod _bindgen_ty_25 {
pub const BPF_F_BROADCAST: _bindgen_ty_25 = 8;
pub const BPF_F_EXCLUDE_INGRESS: _bindgen_ty_25 = 16;
pub type _bindgen_ty_25 = ::aya_bpf_cty::c_uint;
pub mod _bindgen_ty_26 {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_SKB_TSTAMP_UNSPEC: Type = 0;
pub const BPF_SKB_TSTAMP_DELIVERY_MONO: Type = 1;
@ -1249,9 +1282,9 @@ pub struct bpf_tunnel_key {
pub __bindgen_anon_1: bpf_tunnel_key__bindgen_ty_1,
pub tunnel_tos: __u8,
pub tunnel_ttl: __u8,
pub tunnel_ext: __u16,
pub tunnel_label: __u32,
pub __bindgen_anon_2: bpf_tunnel_key__bindgen_ty_2,
pub tunnel_label: __u32,
pub __bindgen_anon_3: bpf_tunnel_key__bindgen_ty_3,
}
#[repr(C)]
#[derive(Copy, Clone)]
@ -1262,6 +1295,12 @@ pub union bpf_tunnel_key__bindgen_ty_1 {
#[repr(C)]
#[derive(Copy, Clone)]
pub union bpf_tunnel_key__bindgen_ty_2 {
pub tunnel_ext: __u16,
pub tunnel_flags: __be16,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union bpf_tunnel_key__bindgen_ty_3 {
pub local_ipv4: __u32,
pub local_ipv6: [__u32; 4usize],
}
@ -1286,6 +1325,7 @@ pub mod bpf_ret_code {
pub const BPF_DROP: Type = 2;
pub const BPF_REDIRECT: Type = 7;
pub const BPF_LWT_REROUTE: Type = 128;
pub const BPF_FLOW_DISSECTOR_CONTINUE: Type = 129;
}
#[repr(C)]
#[derive(Copy, Clone)]
@ -1695,6 +1735,7 @@ pub struct bpf_link_info__bindgen_ty_1__bindgen_ty_4 {
pub target_name: __u64,
pub target_name_len: __u32,
pub __bindgen_anon_1: bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_1,
pub __bindgen_anon_2: bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2,
}
#[repr(C)]
#[derive(Copy, Clone)]
@ -1708,6 +1749,24 @@ pub struct bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_1__bindgen_ty_1
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2 {
pub cgroup: bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2__bindgen_ty_1,
pub task: bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2__bindgen_ty_2,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2__bindgen_ty_1 {
pub cgroup_id: __u64,
pub order: __u32,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2__bindgen_ty_2 {
pub tid: __u32,
pub pid: __u32,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_link_info__bindgen_ty_1__bindgen_ty_5 {
pub netns_ino: __u32,
pub attach_type: __u32,
@ -1788,6 +1847,7 @@ pub struct bpf_sock_ops {
pub __bindgen_anon_4: bpf_sock_ops__bindgen_ty_4,
pub skb_len: __u32,
pub skb_tcp_flags: __u32,
pub skb_hwtstamp: __u64,
}
#[repr(C)]
#[derive(Copy, Clone)]
@ -1838,51 +1898,51 @@ impl bpf_sock_ops__bindgen_ty_4 {
__bindgen_bitfield_unit
}
}
pub const BPF_SOCK_OPS_RTO_CB_FLAG: _bindgen_ty_26 = 1;
pub const BPF_SOCK_OPS_RETRANS_CB_FLAG: _bindgen_ty_26 = 2;
pub const BPF_SOCK_OPS_STATE_CB_FLAG: _bindgen_ty_26 = 4;
pub const BPF_SOCK_OPS_RTT_CB_FLAG: _bindgen_ty_26 = 8;
pub const BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG: _bindgen_ty_26 = 16;
pub const BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG: _bindgen_ty_26 = 32;
pub const BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG: _bindgen_ty_26 = 64;
pub const BPF_SOCK_OPS_ALL_CB_FLAGS: _bindgen_ty_26 = 127;
pub type _bindgen_ty_26 = ::aya_bpf_cty::c_uint;
pub const BPF_SOCK_OPS_VOID: _bindgen_ty_27 = 0;
pub const BPF_SOCK_OPS_TIMEOUT_INIT: _bindgen_ty_27 = 1;
pub const BPF_SOCK_OPS_RWND_INIT: _bindgen_ty_27 = 2;
pub const BPF_SOCK_OPS_TCP_CONNECT_CB: _bindgen_ty_27 = 3;
pub const BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB: _bindgen_ty_27 = 4;
pub const BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB: _bindgen_ty_27 = 5;
pub const BPF_SOCK_OPS_NEEDS_ECN: _bindgen_ty_27 = 6;
pub const BPF_SOCK_OPS_BASE_RTT: _bindgen_ty_27 = 7;
pub const BPF_SOCK_OPS_RTO_CB: _bindgen_ty_27 = 8;
pub const BPF_SOCK_OPS_RETRANS_CB: _bindgen_ty_27 = 9;
pub const BPF_SOCK_OPS_STATE_CB: _bindgen_ty_27 = 10;
pub const BPF_SOCK_OPS_TCP_LISTEN_CB: _bindgen_ty_27 = 11;
pub const BPF_SOCK_OPS_RTT_CB: _bindgen_ty_27 = 12;
pub const BPF_SOCK_OPS_PARSE_HDR_OPT_CB: _bindgen_ty_27 = 13;
pub const BPF_SOCK_OPS_HDR_OPT_LEN_CB: _bindgen_ty_27 = 14;
pub const BPF_SOCK_OPS_WRITE_HDR_OPT_CB: _bindgen_ty_27 = 15;
pub const BPF_SOCK_OPS_RTO_CB_FLAG: _bindgen_ty_27 = 1;
pub const BPF_SOCK_OPS_RETRANS_CB_FLAG: _bindgen_ty_27 = 2;
pub const BPF_SOCK_OPS_STATE_CB_FLAG: _bindgen_ty_27 = 4;
pub const BPF_SOCK_OPS_RTT_CB_FLAG: _bindgen_ty_27 = 8;
pub const BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG: _bindgen_ty_27 = 16;
pub const BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG: _bindgen_ty_27 = 32;
pub const BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG: _bindgen_ty_27 = 64;
pub const BPF_SOCK_OPS_ALL_CB_FLAGS: _bindgen_ty_27 = 127;
pub type _bindgen_ty_27 = ::aya_bpf_cty::c_uint;
pub const BPF_TCP_ESTABLISHED: _bindgen_ty_28 = 1;
pub const BPF_TCP_SYN_SENT: _bindgen_ty_28 = 2;
pub const BPF_TCP_SYN_RECV: _bindgen_ty_28 = 3;
pub const BPF_TCP_FIN_WAIT1: _bindgen_ty_28 = 4;
pub const BPF_TCP_FIN_WAIT2: _bindgen_ty_28 = 5;
pub const BPF_TCP_TIME_WAIT: _bindgen_ty_28 = 6;
pub const BPF_TCP_CLOSE: _bindgen_ty_28 = 7;
pub const BPF_TCP_CLOSE_WAIT: _bindgen_ty_28 = 8;
pub const BPF_TCP_LAST_ACK: _bindgen_ty_28 = 9;
pub const BPF_TCP_LISTEN: _bindgen_ty_28 = 10;
pub const BPF_TCP_CLOSING: _bindgen_ty_28 = 11;
pub const BPF_TCP_NEW_SYN_RECV: _bindgen_ty_28 = 12;
pub const BPF_TCP_MAX_STATES: _bindgen_ty_28 = 13;
pub const BPF_SOCK_OPS_VOID: _bindgen_ty_28 = 0;
pub const BPF_SOCK_OPS_TIMEOUT_INIT: _bindgen_ty_28 = 1;
pub const BPF_SOCK_OPS_RWND_INIT: _bindgen_ty_28 = 2;
pub const BPF_SOCK_OPS_TCP_CONNECT_CB: _bindgen_ty_28 = 3;
pub const BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB: _bindgen_ty_28 = 4;
pub const BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB: _bindgen_ty_28 = 5;
pub const BPF_SOCK_OPS_NEEDS_ECN: _bindgen_ty_28 = 6;
pub const BPF_SOCK_OPS_BASE_RTT: _bindgen_ty_28 = 7;
pub const BPF_SOCK_OPS_RTO_CB: _bindgen_ty_28 = 8;
pub const BPF_SOCK_OPS_RETRANS_CB: _bindgen_ty_28 = 9;
pub const BPF_SOCK_OPS_STATE_CB: _bindgen_ty_28 = 10;
pub const BPF_SOCK_OPS_TCP_LISTEN_CB: _bindgen_ty_28 = 11;
pub const BPF_SOCK_OPS_RTT_CB: _bindgen_ty_28 = 12;
pub const BPF_SOCK_OPS_PARSE_HDR_OPT_CB: _bindgen_ty_28 = 13;
pub const BPF_SOCK_OPS_HDR_OPT_LEN_CB: _bindgen_ty_28 = 14;
pub const BPF_SOCK_OPS_WRITE_HDR_OPT_CB: _bindgen_ty_28 = 15;
pub type _bindgen_ty_28 = ::aya_bpf_cty::c_uint;
pub mod _bindgen_ty_30 {
pub const BPF_TCP_ESTABLISHED: _bindgen_ty_29 = 1;
pub const BPF_TCP_SYN_SENT: _bindgen_ty_29 = 2;
pub const BPF_TCP_SYN_RECV: _bindgen_ty_29 = 3;
pub const BPF_TCP_FIN_WAIT1: _bindgen_ty_29 = 4;
pub const BPF_TCP_FIN_WAIT2: _bindgen_ty_29 = 5;
pub const BPF_TCP_TIME_WAIT: _bindgen_ty_29 = 6;
pub const BPF_TCP_CLOSE: _bindgen_ty_29 = 7;
pub const BPF_TCP_CLOSE_WAIT: _bindgen_ty_29 = 8;
pub const BPF_TCP_LAST_ACK: _bindgen_ty_29 = 9;
pub const BPF_TCP_LISTEN: _bindgen_ty_29 = 10;
pub const BPF_TCP_CLOSING: _bindgen_ty_29 = 11;
pub const BPF_TCP_NEW_SYN_RECV: _bindgen_ty_29 = 12;
pub const BPF_TCP_MAX_STATES: _bindgen_ty_29 = 13;
pub type _bindgen_ty_29 = ::aya_bpf_cty::c_uint;
pub mod _bindgen_ty_31 {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_LOAD_HDR_OPT_TCP_SYN: Type = 1;
}
pub mod _bindgen_ty_31 {
pub mod _bindgen_ty_32 {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_WRITE_HDR_TCP_CURRENT_MSS: Type = 1;
pub const BPF_WRITE_HDR_TCP_SYNACK_COOKIE: Type = 2;
@ -1894,13 +1954,13 @@ pub struct bpf_perf_event_value {
pub enabled: __u64,
pub running: __u64,
}
pub const BPF_DEVCG_ACC_MKNOD: _bindgen_ty_32 = 1;
pub const BPF_DEVCG_ACC_READ: _bindgen_ty_32 = 2;
pub const BPF_DEVCG_ACC_WRITE: _bindgen_ty_32 = 4;
pub type _bindgen_ty_32 = ::aya_bpf_cty::c_uint;
pub const BPF_DEVCG_DEV_BLOCK: _bindgen_ty_33 = 1;
pub const BPF_DEVCG_DEV_CHAR: _bindgen_ty_33 = 2;
pub const BPF_DEVCG_ACC_MKNOD: _bindgen_ty_33 = 1;
pub const BPF_DEVCG_ACC_READ: _bindgen_ty_33 = 2;
pub const BPF_DEVCG_ACC_WRITE: _bindgen_ty_33 = 4;
pub type _bindgen_ty_33 = ::aya_bpf_cty::c_uint;
pub const BPF_DEVCG_DEV_BLOCK: _bindgen_ty_34 = 1;
pub const BPF_DEVCG_DEV_CHAR: _bindgen_ty_34 = 2;
pub type _bindgen_ty_34 = ::aya_bpf_cty::c_uint;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_cgroup_dev_ctx {
@ -1912,19 +1972,19 @@ pub struct bpf_cgroup_dev_ctx {
pub struct bpf_raw_tracepoint_args {
pub args: __IncompleteArrayField<__u64>,
}
pub const BPF_FIB_LOOKUP_DIRECT: _bindgen_ty_34 = 1;
pub const BPF_FIB_LOOKUP_OUTPUT: _bindgen_ty_34 = 2;
pub type _bindgen_ty_34 = ::aya_bpf_cty::c_uint;
pub const BPF_FIB_LKUP_RET_SUCCESS: _bindgen_ty_35 = 0;
pub const BPF_FIB_LKUP_RET_BLACKHOLE: _bindgen_ty_35 = 1;
pub const BPF_FIB_LKUP_RET_UNREACHABLE: _bindgen_ty_35 = 2;
pub const BPF_FIB_LKUP_RET_PROHIBIT: _bindgen_ty_35 = 3;
pub const BPF_FIB_LKUP_RET_NOT_FWDED: _bindgen_ty_35 = 4;
pub const BPF_FIB_LKUP_RET_FWD_DISABLED: _bindgen_ty_35 = 5;
pub const BPF_FIB_LKUP_RET_UNSUPP_LWT: _bindgen_ty_35 = 6;
pub const BPF_FIB_LKUP_RET_NO_NEIGH: _bindgen_ty_35 = 7;
pub const BPF_FIB_LKUP_RET_FRAG_NEEDED: _bindgen_ty_35 = 8;
pub const BPF_FIB_LOOKUP_DIRECT: _bindgen_ty_35 = 1;
pub const BPF_FIB_LOOKUP_OUTPUT: _bindgen_ty_35 = 2;
pub type _bindgen_ty_35 = ::aya_bpf_cty::c_uint;
pub const BPF_FIB_LKUP_RET_SUCCESS: _bindgen_ty_36 = 0;
pub const BPF_FIB_LKUP_RET_BLACKHOLE: _bindgen_ty_36 = 1;
pub const BPF_FIB_LKUP_RET_UNREACHABLE: _bindgen_ty_36 = 2;
pub const BPF_FIB_LKUP_RET_PROHIBIT: _bindgen_ty_36 = 3;
pub const BPF_FIB_LKUP_RET_NOT_FWDED: _bindgen_ty_36 = 4;
pub const BPF_FIB_LKUP_RET_FWD_DISABLED: _bindgen_ty_36 = 5;
pub const BPF_FIB_LKUP_RET_UNSUPP_LWT: _bindgen_ty_36 = 6;
pub const BPF_FIB_LKUP_RET_NO_NEIGH: _bindgen_ty_36 = 7;
pub const BPF_FIB_LKUP_RET_FRAG_NEEDED: _bindgen_ty_36 = 8;
pub type _bindgen_ty_36 = ::aya_bpf_cty::c_uint;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_fib_lookup {
@ -1998,10 +2058,10 @@ pub mod bpf_task_fd_type {
pub const BPF_FD_TYPE_UPROBE: Type = 4;
pub const BPF_FD_TYPE_URETPROBE: Type = 5;
}
pub const BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG: _bindgen_ty_36 = 1;
pub const BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL: _bindgen_ty_36 = 2;
pub const BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP: _bindgen_ty_36 = 4;
pub type _bindgen_ty_36 = ::aya_bpf_cty::c_uint;
pub const BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG: _bindgen_ty_37 = 1;
pub const BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL: _bindgen_ty_37 = 2;
pub const BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP: _bindgen_ty_37 = 4;
pub type _bindgen_ty_37 = ::aya_bpf_cty::c_uint;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_flow_keys {
@ -2085,6 +2145,34 @@ impl bpf_dynptr {
}
}
#[repr(C)]
#[repr(align(8))]
#[derive(Copy, Clone)]
pub struct bpf_list_head {
pub _bitfield_align_1: [u8; 0],
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize]>,
}
impl bpf_list_head {
#[inline]
pub fn new_bitfield_1() -> __BindgenBitfieldUnit<[u8; 16usize]> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 16usize]> = Default::default();
__bindgen_bitfield_unit
}
}
#[repr(C)]
#[repr(align(8))]
#[derive(Copy, Clone)]
pub struct bpf_list_node {
pub _bitfield_align_1: [u8; 0],
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize]>,
}
impl bpf_list_node {
#[inline]
pub fn new_bitfield_1() -> __BindgenBitfieldUnit<[u8; 16usize]> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 16usize]> = Default::default();
__bindgen_bitfield_unit
}
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_sysctl {
pub write: __u32,
@ -2292,6 +2380,11 @@ pub struct task_struct {
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct cgroup {
_unused: [u8; 0],
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct path {
_unused: [u8; 0],
}

@ -461,12 +461,12 @@ pub unsafe fn bpf_skb_adjust_room(
}
pub unsafe fn bpf_redirect_map(
map: *mut ::aya_bpf_cty::c_void,
key: __u32,
key: __u64,
flags: __u64,
) -> ::aya_bpf_cty::c_long {
let fun: unsafe extern "C" fn(
map: *mut ::aya_bpf_cty::c_void,
key: __u32,
key: __u64,
flags: __u64,
) -> ::aya_bpf_cty::c_long = ::core::mem::transmute(51usize);
fun(map, key, flags)
@ -2027,28 +2027,28 @@ pub unsafe fn bpf_ringbuf_discard_dynptr(ptr: *mut bpf_dynptr, flags: __u64) {
pub unsafe fn bpf_dynptr_read(
dst: *mut ::aya_bpf_cty::c_void,
len: __u32,
src: *mut bpf_dynptr,
src: *const bpf_dynptr,
offset: __u32,
flags: __u64,
) -> ::aya_bpf_cty::c_long {
let fun: unsafe extern "C" fn(
dst: *mut ::aya_bpf_cty::c_void,
len: __u32,
src: *mut bpf_dynptr,
src: *const bpf_dynptr,
offset: __u32,
flags: __u64,
) -> ::aya_bpf_cty::c_long = ::core::mem::transmute(201usize);
fun(dst, len, src, offset, flags)
}
pub unsafe fn bpf_dynptr_write(
dst: *mut bpf_dynptr,
dst: *const bpf_dynptr,
offset: __u32,
src: *mut ::aya_bpf_cty::c_void,
len: __u32,
flags: __u64,
) -> ::aya_bpf_cty::c_long {
let fun: unsafe extern "C" fn(
dst: *mut bpf_dynptr,
dst: *const bpf_dynptr,
offset: __u32,
src: *mut ::aya_bpf_cty::c_void,
len: __u32,
@ -2057,12 +2057,12 @@ pub unsafe fn bpf_dynptr_write(
fun(dst, offset, src, len, flags)
}
pub unsafe fn bpf_dynptr_data(
ptr: *mut bpf_dynptr,
ptr: *const bpf_dynptr,
offset: __u32,
len: __u32,
) -> *mut ::aya_bpf_cty::c_void {
let fun: unsafe extern "C" fn(
ptr: *mut bpf_dynptr,
ptr: *const bpf_dynptr,
offset: __u32,
len: __u32,
) -> *mut ::aya_bpf_cty::c_void = ::core::mem::transmute(203usize);
@ -2106,3 +2106,41 @@ pub unsafe fn bpf_ktime_get_tai_ns() -> __u64 {
let fun: unsafe extern "C" fn() -> __u64 = ::core::mem::transmute(208usize);
fun()
}
pub unsafe fn bpf_user_ringbuf_drain(
map: *mut ::aya_bpf_cty::c_void,
callback_fn: *mut ::aya_bpf_cty::c_void,
ctx: *mut ::aya_bpf_cty::c_void,
flags: __u64,
) -> ::aya_bpf_cty::c_long {
let fun: unsafe extern "C" fn(
map: *mut ::aya_bpf_cty::c_void,
callback_fn: *mut ::aya_bpf_cty::c_void,
ctx: *mut ::aya_bpf_cty::c_void,
flags: __u64,
) -> ::aya_bpf_cty::c_long = ::core::mem::transmute(209usize);
fun(map, callback_fn, ctx, flags)
}
pub unsafe fn bpf_cgrp_storage_get(
map: *mut ::aya_bpf_cty::c_void,
cgroup: *mut cgroup,
value: *mut ::aya_bpf_cty::c_void,
flags: __u64,
) -> *mut ::aya_bpf_cty::c_void {
let fun: unsafe extern "C" fn(
map: *mut ::aya_bpf_cty::c_void,
cgroup: *mut cgroup,
value: *mut ::aya_bpf_cty::c_void,
flags: __u64,
) -> *mut ::aya_bpf_cty::c_void = ::core::mem::transmute(210usize);
fun(map, cgroup, value, flags)
}
pub unsafe fn bpf_cgrp_storage_delete(
map: *mut ::aya_bpf_cty::c_void,
cgroup: *mut cgroup,
) -> ::aya_bpf_cty::c_long {
let fun: unsafe extern "C" fn(
map: *mut ::aya_bpf_cty::c_void,
cgroup: *mut cgroup,
) -> ::aya_bpf_cty::c_long = ::core::mem::transmute(211usize);
fun(map, cgroup)
}

@ -358,16 +358,40 @@ pub struct bpf_cgroup_storage_key {
pub cgroup_inode_id: __u64,
pub attach_type: __u32,
}
pub mod bpf_cgroup_iter_order {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_CGROUP_ITER_ORDER_UNSPEC: Type = 0;
pub const BPF_CGROUP_ITER_SELF_ONLY: Type = 1;
pub const BPF_CGROUP_ITER_DESCENDANTS_PRE: Type = 2;
pub const BPF_CGROUP_ITER_DESCENDANTS_POST: Type = 3;
pub const BPF_CGROUP_ITER_ANCESTORS_UP: Type = 4;
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union bpf_iter_link_info {
pub map: bpf_iter_link_info__bindgen_ty_1,
pub cgroup: bpf_iter_link_info__bindgen_ty_2,
pub task: bpf_iter_link_info__bindgen_ty_3,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_iter_link_info__bindgen_ty_1 {
pub map_fd: __u32,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_iter_link_info__bindgen_ty_2 {
pub order: bpf_cgroup_iter_order::Type,
pub cgroup_fd: __u32,
pub cgroup_id: __u64,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_iter_link_info__bindgen_ty_3 {
pub tid: __u32,
pub pid: __u32,
pub pid_fd: __u32,
}
pub mod bpf_cmd {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_MAP_CREATE: Type = 0;
@ -429,6 +453,7 @@ pub mod bpf_map_type {
pub const BPF_MAP_TYPE_CPUMAP: Type = 16;
pub const BPF_MAP_TYPE_XSKMAP: Type = 17;
pub const BPF_MAP_TYPE_SOCKHASH: Type = 18;
pub const BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED: Type = 19;
pub const BPF_MAP_TYPE_CGROUP_STORAGE: Type = 19;
pub const BPF_MAP_TYPE_REUSEPORT_SOCKARRAY: Type = 20;
pub const BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE: Type = 21;
@ -441,6 +466,8 @@ pub mod bpf_map_type {
pub const BPF_MAP_TYPE_INODE_STORAGE: Type = 28;
pub const BPF_MAP_TYPE_TASK_STORAGE: Type = 29;
pub const BPF_MAP_TYPE_BLOOM_FILTER: Type = 30;
pub const BPF_MAP_TYPE_USER_RINGBUF: Type = 31;
pub const BPF_MAP_TYPE_CGRP_STORAGE: Type = 32;
}
pub mod bpf_prog_type {
pub type Type = ::aya_bpf_cty::c_uint;
@ -1072,7 +1099,10 @@ pub mod bpf_func_id {
pub const BPF_FUNC_tcp_raw_check_syncookie_ipv4: Type = 206;
pub const BPF_FUNC_tcp_raw_check_syncookie_ipv6: Type = 207;
pub const BPF_FUNC_ktime_get_tai_ns: Type = 208;
pub const __BPF_FUNC_MAX_ID: Type = 209;
pub const BPF_FUNC_user_ringbuf_drain: Type = 209;
pub const BPF_FUNC_cgrp_storage_get: Type = 210;
pub const BPF_FUNC_cgrp_storage_delete: Type = 211;
pub const __BPF_FUNC_MAX_ID: Type = 212;
}
pub const BPF_F_RECOMPUTE_CSUM: _bindgen_ty_4 = 1;
pub const BPF_F_INVALIDATE_HASH: _bindgen_ty_4 = 2;
@ -1096,51 +1126,54 @@ pub type _bindgen_ty_9 = ::aya_bpf_cty::c_uint;
pub const BPF_F_ZERO_CSUM_TX: _bindgen_ty_10 = 2;
pub const BPF_F_DONT_FRAGMENT: _bindgen_ty_10 = 4;
pub const BPF_F_SEQ_NUMBER: _bindgen_ty_10 = 8;
pub const BPF_F_NO_TUNNEL_KEY: _bindgen_ty_10 = 16;
pub type _bindgen_ty_10 = ::aya_bpf_cty::c_uint;
pub const BPF_F_INDEX_MASK: _bindgen_ty_11 = 4294967295;
pub const BPF_F_CURRENT_CPU: _bindgen_ty_11 = 4294967295;
pub const BPF_F_CTXLEN_MASK: _bindgen_ty_11 = 4503595332403200;
pub type _bindgen_ty_11 = ::aya_bpf_cty::c_ulong;
pub const BPF_F_CURRENT_NETNS: _bindgen_ty_12 = -1;
pub type _bindgen_ty_12 = ::aya_bpf_cty::c_int;
pub const BPF_CSUM_LEVEL_QUERY: _bindgen_ty_13 = 0;
pub const BPF_CSUM_LEVEL_INC: _bindgen_ty_13 = 1;
pub const BPF_CSUM_LEVEL_DEC: _bindgen_ty_13 = 2;
pub const BPF_CSUM_LEVEL_RESET: _bindgen_ty_13 = 3;
pub type _bindgen_ty_13 = ::aya_bpf_cty::c_uint;
pub const BPF_F_ADJ_ROOM_FIXED_GSO: _bindgen_ty_14 = 1;
pub const BPF_F_ADJ_ROOM_ENCAP_L3_IPV4: _bindgen_ty_14 = 2;
pub const BPF_F_ADJ_ROOM_ENCAP_L3_IPV6: _bindgen_ty_14 = 4;
pub const BPF_F_ADJ_ROOM_ENCAP_L4_GRE: _bindgen_ty_14 = 8;
pub const BPF_F_ADJ_ROOM_ENCAP_L4_UDP: _bindgen_ty_14 = 16;
pub const BPF_F_ADJ_ROOM_NO_CSUM_RESET: _bindgen_ty_14 = 32;
pub const BPF_F_ADJ_ROOM_ENCAP_L2_ETH: _bindgen_ty_14 = 64;
pub const BPF_F_TUNINFO_FLAGS: _bindgen_ty_11 = 16;
pub type _bindgen_ty_11 = ::aya_bpf_cty::c_uint;
pub const BPF_F_INDEX_MASK: _bindgen_ty_12 = 4294967295;
pub const BPF_F_CURRENT_CPU: _bindgen_ty_12 = 4294967295;
pub const BPF_F_CTXLEN_MASK: _bindgen_ty_12 = 4503595332403200;
pub type _bindgen_ty_12 = ::aya_bpf_cty::c_ulong;
pub const BPF_F_CURRENT_NETNS: _bindgen_ty_13 = -1;
pub type _bindgen_ty_13 = ::aya_bpf_cty::c_int;
pub const BPF_CSUM_LEVEL_QUERY: _bindgen_ty_14 = 0;
pub const BPF_CSUM_LEVEL_INC: _bindgen_ty_14 = 1;
pub const BPF_CSUM_LEVEL_DEC: _bindgen_ty_14 = 2;
pub const BPF_CSUM_LEVEL_RESET: _bindgen_ty_14 = 3;
pub type _bindgen_ty_14 = ::aya_bpf_cty::c_uint;
pub const BPF_ADJ_ROOM_ENCAP_L2_MASK: _bindgen_ty_15 = 255;
pub const BPF_ADJ_ROOM_ENCAP_L2_SHIFT: _bindgen_ty_15 = 56;
pub const BPF_F_ADJ_ROOM_FIXED_GSO: _bindgen_ty_15 = 1;
pub const BPF_F_ADJ_ROOM_ENCAP_L3_IPV4: _bindgen_ty_15 = 2;
pub const BPF_F_ADJ_ROOM_ENCAP_L3_IPV6: _bindgen_ty_15 = 4;
pub const BPF_F_ADJ_ROOM_ENCAP_L4_GRE: _bindgen_ty_15 = 8;
pub const BPF_F_ADJ_ROOM_ENCAP_L4_UDP: _bindgen_ty_15 = 16;
pub const BPF_F_ADJ_ROOM_NO_CSUM_RESET: _bindgen_ty_15 = 32;
pub const BPF_F_ADJ_ROOM_ENCAP_L2_ETH: _bindgen_ty_15 = 64;
pub type _bindgen_ty_15 = ::aya_bpf_cty::c_uint;
pub const BPF_F_SYSCTL_BASE_NAME: _bindgen_ty_16 = 1;
pub const BPF_ADJ_ROOM_ENCAP_L2_MASK: _bindgen_ty_16 = 255;
pub const BPF_ADJ_ROOM_ENCAP_L2_SHIFT: _bindgen_ty_16 = 56;
pub type _bindgen_ty_16 = ::aya_bpf_cty::c_uint;
pub const BPF_LOCAL_STORAGE_GET_F_CREATE: _bindgen_ty_17 = 1;
pub const BPF_SK_STORAGE_GET_F_CREATE: _bindgen_ty_17 = 1;
pub const BPF_F_SYSCTL_BASE_NAME: _bindgen_ty_17 = 1;
pub type _bindgen_ty_17 = ::aya_bpf_cty::c_uint;
pub const BPF_F_GET_BRANCH_RECORDS_SIZE: _bindgen_ty_18 = 1;
pub const BPF_LOCAL_STORAGE_GET_F_CREATE: _bindgen_ty_18 = 1;
pub const BPF_SK_STORAGE_GET_F_CREATE: _bindgen_ty_18 = 1;
pub type _bindgen_ty_18 = ::aya_bpf_cty::c_uint;
pub const BPF_RB_NO_WAKEUP: _bindgen_ty_19 = 1;
pub const BPF_RB_FORCE_WAKEUP: _bindgen_ty_19 = 2;
pub const BPF_F_GET_BRANCH_RECORDS_SIZE: _bindgen_ty_19 = 1;
pub type _bindgen_ty_19 = ::aya_bpf_cty::c_uint;
pub const BPF_RB_AVAIL_DATA: _bindgen_ty_20 = 0;
pub const BPF_RB_RING_SIZE: _bindgen_ty_20 = 1;
pub const BPF_RB_CONS_POS: _bindgen_ty_20 = 2;
pub const BPF_RB_PROD_POS: _bindgen_ty_20 = 3;
pub const BPF_RB_NO_WAKEUP: _bindgen_ty_20 = 1;
pub const BPF_RB_FORCE_WAKEUP: _bindgen_ty_20 = 2;
pub type _bindgen_ty_20 = ::aya_bpf_cty::c_uint;
pub const BPF_RINGBUF_BUSY_BIT: _bindgen_ty_21 = 2147483648;
pub const BPF_RINGBUF_DISCARD_BIT: _bindgen_ty_21 = 1073741824;
pub const BPF_RINGBUF_HDR_SZ: _bindgen_ty_21 = 8;
pub const BPF_RB_AVAIL_DATA: _bindgen_ty_21 = 0;
pub const BPF_RB_RING_SIZE: _bindgen_ty_21 = 1;
pub const BPF_RB_CONS_POS: _bindgen_ty_21 = 2;
pub const BPF_RB_PROD_POS: _bindgen_ty_21 = 3;
pub type _bindgen_ty_21 = ::aya_bpf_cty::c_uint;
pub const BPF_SK_LOOKUP_F_REPLACE: _bindgen_ty_22 = 1;
pub const BPF_SK_LOOKUP_F_NO_REUSEPORT: _bindgen_ty_22 = 2;
pub const BPF_RINGBUF_BUSY_BIT: _bindgen_ty_22 = 2147483648;
pub const BPF_RINGBUF_DISCARD_BIT: _bindgen_ty_22 = 1073741824;
pub const BPF_RINGBUF_HDR_SZ: _bindgen_ty_22 = 8;
pub type _bindgen_ty_22 = ::aya_bpf_cty::c_uint;
pub const BPF_SK_LOOKUP_F_REPLACE: _bindgen_ty_23 = 1;
pub const BPF_SK_LOOKUP_F_NO_REUSEPORT: _bindgen_ty_23 = 2;
pub type _bindgen_ty_23 = ::aya_bpf_cty::c_uint;
pub mod bpf_adj_room_mode {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_ADJ_ROOM_NET: Type = 0;
@ -1157,12 +1190,12 @@ pub mod bpf_lwt_encap_mode {
pub const BPF_LWT_ENCAP_SEG6_INLINE: Type = 1;
pub const BPF_LWT_ENCAP_IP: Type = 2;
}
pub const BPF_F_BPRM_SECUREEXEC: _bindgen_ty_23 = 1;
pub type _bindgen_ty_23 = ::aya_bpf_cty::c_uint;
pub const BPF_F_BROADCAST: _bindgen_ty_24 = 8;
pub const BPF_F_EXCLUDE_INGRESS: _bindgen_ty_24 = 16;
pub const BPF_F_BPRM_SECUREEXEC: _bindgen_ty_24 = 1;
pub type _bindgen_ty_24 = ::aya_bpf_cty::c_uint;
pub mod _bindgen_ty_25 {
pub const BPF_F_BROADCAST: _bindgen_ty_25 = 8;
pub const BPF_F_EXCLUDE_INGRESS: _bindgen_ty_25 = 16;
pub type _bindgen_ty_25 = ::aya_bpf_cty::c_uint;
pub mod _bindgen_ty_26 {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_SKB_TSTAMP_UNSPEC: Type = 0;
pub const BPF_SKB_TSTAMP_DELIVERY_MONO: Type = 1;
@ -1249,9 +1282,9 @@ pub struct bpf_tunnel_key {
pub __bindgen_anon_1: bpf_tunnel_key__bindgen_ty_1,
pub tunnel_tos: __u8,
pub tunnel_ttl: __u8,
pub tunnel_ext: __u16,
pub tunnel_label: __u32,
pub __bindgen_anon_2: bpf_tunnel_key__bindgen_ty_2,
pub tunnel_label: __u32,
pub __bindgen_anon_3: bpf_tunnel_key__bindgen_ty_3,
}
#[repr(C)]
#[derive(Copy, Clone)]
@ -1262,6 +1295,12 @@ pub union bpf_tunnel_key__bindgen_ty_1 {
#[repr(C)]
#[derive(Copy, Clone)]
pub union bpf_tunnel_key__bindgen_ty_2 {
pub tunnel_ext: __u16,
pub tunnel_flags: __be16,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union bpf_tunnel_key__bindgen_ty_3 {
pub local_ipv4: __u32,
pub local_ipv6: [__u32; 4usize],
}
@ -1286,6 +1325,7 @@ pub mod bpf_ret_code {
pub const BPF_DROP: Type = 2;
pub const BPF_REDIRECT: Type = 7;
pub const BPF_LWT_REROUTE: Type = 128;
pub const BPF_FLOW_DISSECTOR_CONTINUE: Type = 129;
}
#[repr(C)]
#[derive(Copy, Clone)]
@ -1695,6 +1735,7 @@ pub struct bpf_link_info__bindgen_ty_1__bindgen_ty_4 {
pub target_name: __u64,
pub target_name_len: __u32,
pub __bindgen_anon_1: bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_1,
pub __bindgen_anon_2: bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2,
}
#[repr(C)]
#[derive(Copy, Clone)]
@ -1708,6 +1749,24 @@ pub struct bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_1__bindgen_ty_1
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2 {
pub cgroup: bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2__bindgen_ty_1,
pub task: bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2__bindgen_ty_2,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2__bindgen_ty_1 {
pub cgroup_id: __u64,
pub order: __u32,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_link_info__bindgen_ty_1__bindgen_ty_4__bindgen_ty_2__bindgen_ty_2 {
pub tid: __u32,
pub pid: __u32,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_link_info__bindgen_ty_1__bindgen_ty_5 {
pub netns_ino: __u32,
pub attach_type: __u32,
@ -1788,6 +1847,7 @@ pub struct bpf_sock_ops {
pub __bindgen_anon_4: bpf_sock_ops__bindgen_ty_4,
pub skb_len: __u32,
pub skb_tcp_flags: __u32,
pub skb_hwtstamp: __u64,
}
#[repr(C)]
#[derive(Copy, Clone)]
@ -1838,51 +1898,51 @@ impl bpf_sock_ops__bindgen_ty_4 {
__bindgen_bitfield_unit
}
}
pub const BPF_SOCK_OPS_RTO_CB_FLAG: _bindgen_ty_26 = 1;
pub const BPF_SOCK_OPS_RETRANS_CB_FLAG: _bindgen_ty_26 = 2;
pub const BPF_SOCK_OPS_STATE_CB_FLAG: _bindgen_ty_26 = 4;
pub const BPF_SOCK_OPS_RTT_CB_FLAG: _bindgen_ty_26 = 8;
pub const BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG: _bindgen_ty_26 = 16;
pub const BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG: _bindgen_ty_26 = 32;
pub const BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG: _bindgen_ty_26 = 64;
pub const BPF_SOCK_OPS_ALL_CB_FLAGS: _bindgen_ty_26 = 127;
pub type _bindgen_ty_26 = ::aya_bpf_cty::c_uint;
pub const BPF_SOCK_OPS_VOID: _bindgen_ty_27 = 0;
pub const BPF_SOCK_OPS_TIMEOUT_INIT: _bindgen_ty_27 = 1;
pub const BPF_SOCK_OPS_RWND_INIT: _bindgen_ty_27 = 2;
pub const BPF_SOCK_OPS_TCP_CONNECT_CB: _bindgen_ty_27 = 3;
pub const BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB: _bindgen_ty_27 = 4;
pub const BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB: _bindgen_ty_27 = 5;
pub const BPF_SOCK_OPS_NEEDS_ECN: _bindgen_ty_27 = 6;
pub const BPF_SOCK_OPS_BASE_RTT: _bindgen_ty_27 = 7;
pub const BPF_SOCK_OPS_RTO_CB: _bindgen_ty_27 = 8;
pub const BPF_SOCK_OPS_RETRANS_CB: _bindgen_ty_27 = 9;
pub const BPF_SOCK_OPS_STATE_CB: _bindgen_ty_27 = 10;
pub const BPF_SOCK_OPS_TCP_LISTEN_CB: _bindgen_ty_27 = 11;
pub const BPF_SOCK_OPS_RTT_CB: _bindgen_ty_27 = 12;
pub const BPF_SOCK_OPS_PARSE_HDR_OPT_CB: _bindgen_ty_27 = 13;
pub const BPF_SOCK_OPS_HDR_OPT_LEN_CB: _bindgen_ty_27 = 14;
pub const BPF_SOCK_OPS_WRITE_HDR_OPT_CB: _bindgen_ty_27 = 15;
pub const BPF_SOCK_OPS_RTO_CB_FLAG: _bindgen_ty_27 = 1;
pub const BPF_SOCK_OPS_RETRANS_CB_FLAG: _bindgen_ty_27 = 2;
pub const BPF_SOCK_OPS_STATE_CB_FLAG: _bindgen_ty_27 = 4;
pub const BPF_SOCK_OPS_RTT_CB_FLAG: _bindgen_ty_27 = 8;
pub const BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG: _bindgen_ty_27 = 16;
pub const BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG: _bindgen_ty_27 = 32;
pub const BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG: _bindgen_ty_27 = 64;
pub const BPF_SOCK_OPS_ALL_CB_FLAGS: _bindgen_ty_27 = 127;
pub type _bindgen_ty_27 = ::aya_bpf_cty::c_uint;
pub const BPF_TCP_ESTABLISHED: _bindgen_ty_28 = 1;
pub const BPF_TCP_SYN_SENT: _bindgen_ty_28 = 2;
pub const BPF_TCP_SYN_RECV: _bindgen_ty_28 = 3;
pub const BPF_TCP_FIN_WAIT1: _bindgen_ty_28 = 4;
pub const BPF_TCP_FIN_WAIT2: _bindgen_ty_28 = 5;
pub const BPF_TCP_TIME_WAIT: _bindgen_ty_28 = 6;
pub const BPF_TCP_CLOSE: _bindgen_ty_28 = 7;
pub const BPF_TCP_CLOSE_WAIT: _bindgen_ty_28 = 8;
pub const BPF_TCP_LAST_ACK: _bindgen_ty_28 = 9;
pub const BPF_TCP_LISTEN: _bindgen_ty_28 = 10;
pub const BPF_TCP_CLOSING: _bindgen_ty_28 = 11;
pub const BPF_TCP_NEW_SYN_RECV: _bindgen_ty_28 = 12;
pub const BPF_TCP_MAX_STATES: _bindgen_ty_28 = 13;
pub const BPF_SOCK_OPS_VOID: _bindgen_ty_28 = 0;
pub const BPF_SOCK_OPS_TIMEOUT_INIT: _bindgen_ty_28 = 1;
pub const BPF_SOCK_OPS_RWND_INIT: _bindgen_ty_28 = 2;
pub const BPF_SOCK_OPS_TCP_CONNECT_CB: _bindgen_ty_28 = 3;
pub const BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB: _bindgen_ty_28 = 4;
pub const BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB: _bindgen_ty_28 = 5;
pub const BPF_SOCK_OPS_NEEDS_ECN: _bindgen_ty_28 = 6;
pub const BPF_SOCK_OPS_BASE_RTT: _bindgen_ty_28 = 7;
pub const BPF_SOCK_OPS_RTO_CB: _bindgen_ty_28 = 8;
pub const BPF_SOCK_OPS_RETRANS_CB: _bindgen_ty_28 = 9;
pub const BPF_SOCK_OPS_STATE_CB: _bindgen_ty_28 = 10;
pub const BPF_SOCK_OPS_TCP_LISTEN_CB: _bindgen_ty_28 = 11;
pub const BPF_SOCK_OPS_RTT_CB: _bindgen_ty_28 = 12;
pub const BPF_SOCK_OPS_PARSE_HDR_OPT_CB: _bindgen_ty_28 = 13;
pub const BPF_SOCK_OPS_HDR_OPT_LEN_CB: _bindgen_ty_28 = 14;
pub const BPF_SOCK_OPS_WRITE_HDR_OPT_CB: _bindgen_ty_28 = 15;
pub type _bindgen_ty_28 = ::aya_bpf_cty::c_uint;
pub mod _bindgen_ty_30 {
pub const BPF_TCP_ESTABLISHED: _bindgen_ty_29 = 1;
pub const BPF_TCP_SYN_SENT: _bindgen_ty_29 = 2;
pub const BPF_TCP_SYN_RECV: _bindgen_ty_29 = 3;
pub const BPF_TCP_FIN_WAIT1: _bindgen_ty_29 = 4;
pub const BPF_TCP_FIN_WAIT2: _bindgen_ty_29 = 5;
pub const BPF_TCP_TIME_WAIT: _bindgen_ty_29 = 6;
pub const BPF_TCP_CLOSE: _bindgen_ty_29 = 7;
pub const BPF_TCP_CLOSE_WAIT: _bindgen_ty_29 = 8;
pub const BPF_TCP_LAST_ACK: _bindgen_ty_29 = 9;
pub const BPF_TCP_LISTEN: _bindgen_ty_29 = 10;
pub const BPF_TCP_CLOSING: _bindgen_ty_29 = 11;
pub const BPF_TCP_NEW_SYN_RECV: _bindgen_ty_29 = 12;
pub const BPF_TCP_MAX_STATES: _bindgen_ty_29 = 13;
pub type _bindgen_ty_29 = ::aya_bpf_cty::c_uint;
pub mod _bindgen_ty_31 {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_LOAD_HDR_OPT_TCP_SYN: Type = 1;
}
pub mod _bindgen_ty_31 {
pub mod _bindgen_ty_32 {
pub type Type = ::aya_bpf_cty::c_uint;
pub const BPF_WRITE_HDR_TCP_CURRENT_MSS: Type = 1;
pub const BPF_WRITE_HDR_TCP_SYNACK_COOKIE: Type = 2;
@ -1894,13 +1954,13 @@ pub struct bpf_perf_event_value {
pub enabled: __u64,
pub running: __u64,
}
pub const BPF_DEVCG_ACC_MKNOD: _bindgen_ty_32 = 1;
pub const BPF_DEVCG_ACC_READ: _bindgen_ty_32 = 2;
pub const BPF_DEVCG_ACC_WRITE: _bindgen_ty_32 = 4;
pub type _bindgen_ty_32 = ::aya_bpf_cty::c_uint;
pub const BPF_DEVCG_DEV_BLOCK: _bindgen_ty_33 = 1;
pub const BPF_DEVCG_DEV_CHAR: _bindgen_ty_33 = 2;
pub const BPF_DEVCG_ACC_MKNOD: _bindgen_ty_33 = 1;
pub const BPF_DEVCG_ACC_READ: _bindgen_ty_33 = 2;
pub const BPF_DEVCG_ACC_WRITE: _bindgen_ty_33 = 4;
pub type _bindgen_ty_33 = ::aya_bpf_cty::c_uint;
pub const BPF_DEVCG_DEV_BLOCK: _bindgen_ty_34 = 1;
pub const BPF_DEVCG_DEV_CHAR: _bindgen_ty_34 = 2;
pub type _bindgen_ty_34 = ::aya_bpf_cty::c_uint;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_cgroup_dev_ctx {
@ -1912,19 +1972,19 @@ pub struct bpf_cgroup_dev_ctx {
pub struct bpf_raw_tracepoint_args {
pub args: __IncompleteArrayField<__u64>,
}
pub const BPF_FIB_LOOKUP_DIRECT: _bindgen_ty_34 = 1;
pub const BPF_FIB_LOOKUP_OUTPUT: _bindgen_ty_34 = 2;
pub type _bindgen_ty_34 = ::aya_bpf_cty::c_uint;
pub const BPF_FIB_LKUP_RET_SUCCESS: _bindgen_ty_35 = 0;
pub const BPF_FIB_LKUP_RET_BLACKHOLE: _bindgen_ty_35 = 1;
pub const BPF_FIB_LKUP_RET_UNREACHABLE: _bindgen_ty_35 = 2;
pub const BPF_FIB_LKUP_RET_PROHIBIT: _bindgen_ty_35 = 3;
pub const BPF_FIB_LKUP_RET_NOT_FWDED: _bindgen_ty_35 = 4;
pub const BPF_FIB_LKUP_RET_FWD_DISABLED: _bindgen_ty_35 = 5;
pub const BPF_FIB_LKUP_RET_UNSUPP_LWT: _bindgen_ty_35 = 6;
pub const BPF_FIB_LKUP_RET_NO_NEIGH: _bindgen_ty_35 = 7;
pub const BPF_FIB_LKUP_RET_FRAG_NEEDED: _bindgen_ty_35 = 8;
pub const BPF_FIB_LOOKUP_DIRECT: _bindgen_ty_35 = 1;
pub const BPF_FIB_LOOKUP_OUTPUT: _bindgen_ty_35 = 2;
pub type _bindgen_ty_35 = ::aya_bpf_cty::c_uint;
pub const BPF_FIB_LKUP_RET_SUCCESS: _bindgen_ty_36 = 0;
pub const BPF_FIB_LKUP_RET_BLACKHOLE: _bindgen_ty_36 = 1;
pub const BPF_FIB_LKUP_RET_UNREACHABLE: _bindgen_ty_36 = 2;
pub const BPF_FIB_LKUP_RET_PROHIBIT: _bindgen_ty_36 = 3;
pub const BPF_FIB_LKUP_RET_NOT_FWDED: _bindgen_ty_36 = 4;
pub const BPF_FIB_LKUP_RET_FWD_DISABLED: _bindgen_ty_36 = 5;
pub const BPF_FIB_LKUP_RET_UNSUPP_LWT: _bindgen_ty_36 = 6;
pub const BPF_FIB_LKUP_RET_NO_NEIGH: _bindgen_ty_36 = 7;
pub const BPF_FIB_LKUP_RET_FRAG_NEEDED: _bindgen_ty_36 = 8;
pub type _bindgen_ty_36 = ::aya_bpf_cty::c_uint;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_fib_lookup {
@ -1998,10 +2058,10 @@ pub mod bpf_task_fd_type {
pub const BPF_FD_TYPE_UPROBE: Type = 4;
pub const BPF_FD_TYPE_URETPROBE: Type = 5;
}
pub const BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG: _bindgen_ty_36 = 1;
pub const BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL: _bindgen_ty_36 = 2;
pub const BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP: _bindgen_ty_36 = 4;
pub type _bindgen_ty_36 = ::aya_bpf_cty::c_uint;
pub const BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG: _bindgen_ty_37 = 1;
pub const BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL: _bindgen_ty_37 = 2;
pub const BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP: _bindgen_ty_37 = 4;
pub type _bindgen_ty_37 = ::aya_bpf_cty::c_uint;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_flow_keys {
@ -2085,6 +2145,34 @@ impl bpf_dynptr {
}
}
#[repr(C)]
#[repr(align(8))]
#[derive(Copy, Clone)]
pub struct bpf_list_head {
pub _bitfield_align_1: [u8; 0],
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize]>,
}
impl bpf_list_head {
#[inline]
pub fn new_bitfield_1() -> __BindgenBitfieldUnit<[u8; 16usize]> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 16usize]> = Default::default();
__bindgen_bitfield_unit
}
}
#[repr(C)]
#[repr(align(8))]
#[derive(Copy, Clone)]
pub struct bpf_list_node {
pub _bitfield_align_1: [u8; 0],
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize]>,
}
impl bpf_list_node {
#[inline]
pub fn new_bitfield_1() -> __BindgenBitfieldUnit<[u8; 16usize]> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 16usize]> = Default::default();
__bindgen_bitfield_unit
}
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bpf_sysctl {
pub write: __u32,
@ -2312,6 +2400,11 @@ pub struct task_struct {
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct cgroup {
_unused: [u8; 0],
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct path {
_unused: [u8; 0],
}

@ -461,12 +461,12 @@ pub unsafe fn bpf_skb_adjust_room(
}
pub unsafe fn bpf_redirect_map(
map: *mut ::aya_bpf_cty::c_void,
key: __u32,
key: __u64,
flags: __u64,
) -> ::aya_bpf_cty::c_long {
let fun: unsafe extern "C" fn(
map: *mut ::aya_bpf_cty::c_void,
key: __u32,
key: __u64,
flags: __u64,
) -> ::aya_bpf_cty::c_long = ::core::mem::transmute(51usize);
fun(map, key, flags)
@ -2027,28 +2027,28 @@ pub unsafe fn bpf_ringbuf_discard_dynptr(ptr: *mut bpf_dynptr, flags: __u64) {
pub unsafe fn bpf_dynptr_read(
dst: *mut ::aya_bpf_cty::c_void,
len: __u32,
src: *mut bpf_dynptr,
src: *const bpf_dynptr,
offset: __u32,
flags: __u64,
) -> ::aya_bpf_cty::c_long {
let fun: unsafe extern "C" fn(
dst: *mut ::aya_bpf_cty::c_void,
len: __u32,
src: *mut bpf_dynptr,
src: *const bpf_dynptr,
offset: __u32,
flags: __u64,
) -> ::aya_bpf_cty::c_long = ::core::mem::transmute(201usize);
fun(dst, len, src, offset, flags)
}
pub unsafe fn bpf_dynptr_write(
dst: *mut bpf_dynptr,
dst: *const bpf_dynptr,
offset: __u32,
src: *mut ::aya_bpf_cty::c_void,
len: __u32,
flags: __u64,
) -> ::aya_bpf_cty::c_long {
let fun: unsafe extern "C" fn(
dst: *mut bpf_dynptr,
dst: *const bpf_dynptr,
offset: __u32,
src: *mut ::aya_bpf_cty::c_void,
len: __u32,
@ -2057,12 +2057,12 @@ pub unsafe fn bpf_dynptr_write(
fun(dst, offset, src, len, flags)
}
pub unsafe fn bpf_dynptr_data(
ptr: *mut bpf_dynptr,
ptr: *const bpf_dynptr,
offset: __u32,
len: __u32,
) -> *mut ::aya_bpf_cty::c_void {
let fun: unsafe extern "C" fn(
ptr: *mut bpf_dynptr,
ptr: *const bpf_dynptr,
offset: __u32,
len: __u32,
) -> *mut ::aya_bpf_cty::c_void = ::core::mem::transmute(203usize);
@ -2106,3 +2106,41 @@ pub unsafe fn bpf_ktime_get_tai_ns() -> __u64 {
let fun: unsafe extern "C" fn() -> __u64 = ::core::mem::transmute(208usize);
fun()
}
pub unsafe fn bpf_user_ringbuf_drain(
map: *mut ::aya_bpf_cty::c_void,
callback_fn: *mut ::aya_bpf_cty::c_void,
ctx: *mut ::aya_bpf_cty::c_void,
flags: __u64,
) -> ::aya_bpf_cty::c_long {
let fun: unsafe extern "C" fn(
map: *mut ::aya_bpf_cty::c_void,
callback_fn: *mut ::aya_bpf_cty::c_void,
ctx: *mut ::aya_bpf_cty::c_void,
flags: __u64,
) -> ::aya_bpf_cty::c_long = ::core::mem::transmute(209usize);
fun(map, callback_fn, ctx, flags)
}
pub unsafe fn bpf_cgrp_storage_get(
map: *mut ::aya_bpf_cty::c_void,
cgroup: *mut cgroup,
value: *mut ::aya_bpf_cty::c_void,
flags: __u64,
) -> *mut ::aya_bpf_cty::c_void {
let fun: unsafe extern "C" fn(
map: *mut ::aya_bpf_cty::c_void,
cgroup: *mut cgroup,
value: *mut ::aya_bpf_cty::c_void,
flags: __u64,
) -> *mut ::aya_bpf_cty::c_void = ::core::mem::transmute(210usize);
fun(map, cgroup, value, flags)
}
pub unsafe fn bpf_cgrp_storage_delete(
map: *mut ::aya_bpf_cty::c_void,
cgroup: *mut cgroup,
) -> ::aya_bpf_cty::c_long {
let fun: unsafe extern "C" fn(
map: *mut ::aya_bpf_cty::c_void,
cgroup: *mut cgroup,
) -> ::aya_bpf_cty::c_long = ::core::mem::transmute(211usize);
fun(map, cgroup)
}

@ -47,14 +47,28 @@ impl<T> Array<T> {
}
}
#[inline(always)]
pub fn get(&self, index: u32) -> Option<&T> {
unsafe {
let value = bpf_map_lookup_elem(
self.def.get() as *mut _,
&index as *const _ as *const c_void,
);
// FIXME: alignment
NonNull::new(value as *mut T).map(|p| p.as_ref())
}
// FIXME: alignment
unsafe { self.lookup(index).map(|p| p.as_ref()) }
}
#[inline(always)]
pub fn get_ptr(&self, index: u32) -> Option<*const T> {
unsafe { self.lookup(index).map(|p| p.as_ptr() as *const T) }
}
#[inline(always)]
pub fn get_ptr_mut(&self, index: u32) -> Option<*mut T> {
unsafe { self.lookup(index).map(|p| p.as_ptr()) }
}
#[inline(always)]
unsafe fn lookup(&self, index: u32) -> Option<NonNull<T>> {
let ptr = bpf_map_lookup_elem(
self.def.get() as *mut _,
&index as *const _ as *const c_void,
);
NonNull::new(ptr as *mut T)
}
}

@ -217,6 +217,46 @@ impl SkBuff {
pub(crate) fn as_ptr(&self) -> *mut c_void {
self.skb as *mut _
}
#[inline]
pub fn protocol(&self) -> u32 {
unsafe { (*self.skb).protocol }
}
#[inline]
pub fn family(&self) -> u32 {
unsafe { (*self.skb).family }
}
#[inline]
pub fn local_ipv4(&self) -> u32 {
unsafe { (*self.skb).local_ip4 }
}
#[inline]
pub fn local_ipv6(&self) -> &[u32; 4] {
unsafe { &(*self.skb).local_ip6 }
}
#[inline]
pub fn remote_ipv4(&self) -> u32 {
unsafe { (*self.skb).remote_ip4 }
}
#[inline]
pub fn remote_ipv6(&self) -> &[u32; 4] {
unsafe { &(*self.skb).remote_ip6 }
}
#[inline]
pub fn local_port(&self) -> u32 {
unsafe { (*self.skb).local_port }
}
#[inline]
pub fn remote_port(&self) -> u32 {
unsafe { (*self.skb).remote_port }
}
}
pub struct SkBuffContext {

@ -0,0 +1,264 @@
#!/bin/bash
VERBOSITY=0
TEMP_D=""
DEF_DISK_FORMAT="raw"
DEF_FILESYSTEM="iso9660"
CR="
"
error() { echo "$@" 1>&2; }
fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
Usage() {
cat <<EOF
Usage: ${0##*/} [ options ] output user-data [meta-data]
Create a disk for cloud-init to utilize nocloud
options:
-h | --help show usage
-d | --disk-format D disk format to output. default: raw
can be anything supported by qemu-img or
tar, tar-seed-local, tar-seed-net
-H | --hostname H set hostname in metadata to H
-f | --filesystem F filesystem format (vfat or iso), default: iso9660
-i | --interfaces F write network interfaces file into metadata
-N | --network-config F write network config file to local datasource
-m | --dsmode M add 'dsmode' ('local' or 'net') to the metadata
default in cloud-init is 'net', meaning network is
required.
-V | --vendor-data F vendor-data file
-v | --verbose increase verbosity
Note, --dsmode, --hostname, and --interfaces are incompatible
with metadata.
Example:
* cat my-user-data
#cloud-config
password: passw0rd
chpasswd: { expire: False }
ssh_pwauth: True
* echo "instance-id: \$(uuidgen || echo i-abcdefg)" > my-meta-data
* ${0##*/} my-seed.img my-user-data my-meta-data
* kvm -net nic -net user,hostfwd=tcp::2222-:22 \\
-drive file=disk1.img,if=virtio -drive file=my-seed.img,if=virtio
* ssh -p 2222 ubuntu@localhost
EOF
}
bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; exit 1; }
cleanup() {
[ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}"
}
debug() {
local level=${1}; shift;
[ "${level}" -gt "${VERBOSITY}" ] && return
error "${@}"
}
has_cmd() {
command -v "$1" >/dev/null 2>&1
}
short_opts="hH:i:d:f:m:N:o:V:v"
long_opts="disk-format:,dsmode:,filesystem:,help,hostname:,interfaces:,"
long_opts="${long_opts}network-config:,output:,vendor-data:,verbose"
getopt_out=$(getopt -n "${0##*/}" \
-o "${short_opts}" -l "${long_opts}" -- "$@") &&
eval set -- "${getopt_out}" ||
bad_Usage
## <<insert default variables here>>
output=""
userdata=""
metadata=""
vendordata=""
filesystem=""
diskformat=$DEF_DISK_FORMAT
interfaces=_unset
dsmode=""
hostname=""
ncname="network-config"
while [ $# -ne 0 ]; do
cur=${1}; next=${2};
case "$cur" in
-h|--help) Usage ; exit 0;;
-d|--disk-format) diskformat=$next; shift;;
-f|--filesystem) filesystem=$next; shift;;
-H|--hostname) hostname=$next; shift;;
-i|--interfaces) interfaces=$next; shift;;
-N|--network-config) netcfg=$next; shift;;
-m|--dsmode) dsmode=$next; shift;;
-v|--verbose) VERBOSITY=$((${VERBOSITY}+1));;
-V|--vendor-data) vendordata="$next";;
--) shift; break;;
esac
shift;
done
## check arguments here
## how many args do you expect?
echo $1
echo $2
echo $3
[ $# -ge 2 ] || bad_Usage "must provide output, userdata"
[ $# -le 3 ] || bad_Usage "confused by additional args"
output=$1
userdata=$2
metadata=$3
if [ -n "$metadata" ]; then
[ "$interfaces" = "_unset" -a -z "$dsmode" -a -z "$hostname" ] ||
fail "metadata is incompatible with:" \
"--interfaces, --hostname, --dsmode"
fi
case "$diskformat" in
tar|tar-seed-local|tar-seed-net)
if [ "${filesystem:-tar}" != "tar" ]; then
fail "diskformat=tar is incompatible with filesystem"
fi
filesystem="$diskformat"
;;
tar*)
fail "supported 'tar' formats are tar, tar-seed-local, tar-seed-net"
esac
if [ -z "$filesystem" ]; then
filesystem="$DEF_FILESYSTEM"
fi
if [ "$filesystem" = "iso" ]; then
filesystem="iso9660"
fi
case "$filesystem" in
tar*)
has_cmd tar ||
fail "missing 'tar'. Required for --filesystem=$filesystem";;
vfat)
has_cmd mkfs.vfat ||
fail "missing 'mkfs.vfat'. Required for --filesystem=vfat."
has_cmd mcopy ||
fail "missing 'mcopy'. Required for --filesystem=vfat."
;;
iso9660)
has_cmd mkisofs ||
fail "missing 'mkisofs'. Required for --filesystem=iso9660."
;;
*) fail "unknown filesystem $filesystem";;
esac
case "$diskformat" in
tar*|raw) :;;
*) has_cmd "qemu-img" ||
fail "missing 'qemu-img'. Required for --disk-format=$diskformat."
esac
[ "$interfaces" = "_unset" -o -r "$interfaces" ] ||
fail "$interfaces: not a readable file"
TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX") ||
fail "failed to make tempdir"
trap cleanup EXIT
files=( "${TEMP_D}/user-data" "${TEMP_D}/meta-data" )
if [ -n "$metadata" ]; then
cp "$metadata" "$TEMP_D/meta-data" || fail "$metadata: failed to copy"
else
instance_id="iid-local01"
iface_data=""
[ "$interfaces" != "_unset" ] &&
iface_data=$(sed ':a;N;$!ba;s/\n/\\n/g' "$interfaces")
# write json formatted user-data (json is a subset of yaml)
mdata=""
for kv in "instance-id:$instance_id" "local-hostname:$hostname" \
"interfaces:${iface_data}" "dsmode:$dsmode"; do
key=${kv%%:*}
val=${kv#*:}
[ -n "$val" ] || continue
mdata="${mdata:+${mdata},${CR}}\"$key\": \"$val\""
done
printf "{\n%s\n}\n" "$mdata" > "${TEMP_D}/meta-data"
fi
if [ -n "$netcfg" ]; then
cp "$netcfg" "${TEMP_D}/$ncname" ||
fail "failed to copy network config"
files[${#files[@]}]="$TEMP_D/$ncname"
fi
if [ -n "$vendordata" ]; then
cp "$vendordata" "${TEMP_D}/vendor-data" ||
fail "failed to copy vendor data"
files[${#files[@]}]="$TEMP_D/vendor-data"
fi
files_rel=( )
for f in "${files[@]}"; do
files_rel[${#files_rel[@]}]="${f#${TEMP_D}/}"
done
if [ "$userdata" = "-" ]; then
cat > "$TEMP_D/user-data" || fail "failed to read from stdin"
else
cp "$userdata" "$TEMP_D/user-data" || fail "$userdata: failed to copy"
fi
## alternatively, create a vfat filesystem with same files
img="$TEMP_D/seed-data"
tar_opts=( --owner=root --group=root )
case "$filesystem" in
tar)
tar "${tar_opts[@]}" -C "${TEMP_D}" -cf "$img" "${files_rel[@]}" ||
fail "failed to create tarball of ${files_rel[*]}"
;;
tar-seed-local|tar-seed-net)
if [ "$filesystem" = "tar-seed-local" ]; then
path="var/lib/cloud/seed/nocloud"
else
path="var/lib/cloud/seed/nocloud-net"
fi
mkdir -p "${TEMP_D}/${path}" ||
fail "failed making path for seed files"
mv "${files[@]}" "${TEMP_D}/$path" ||
fail "failed moving files"
tar "${tar_opts[@]}" -C "${TEMP_D}" -cf "$img" "${path}" ||
fail "failed to create tarball with $path"
;;
iso9660)
mkisofs -output "$img" -volid cidata \
-joliet -rock "${files[@]}" > "$TEMP_D/err" 2>&1 ||
{ cat "$TEMP_D/err" 1>&2; fail "failed to mkisofs"; }
;;
vfat)
truncate -s 128K "$img" || fail "failed truncate image"
out=$(mkfs.vfat -n cidata "$img" 2>&1) ||
{ error "failed: mkfs.vfat -n cidata $img"; error "$out"; }
mcopy -oi "$img" "${files[@]}" :: ||
fail "failed to copy user-data, meta-data to img"
;;
esac
[ "$output" = "-" ] && output="$TEMP_D/final"
if [ "${diskformat#tar}" != "$diskformat" -o "$diskformat" = "raw" ]; then
cp "$img" "$output" ||
fail "failed to copy image to $output"
else
qemu-img convert -f raw -O "$diskformat" "$img" "$output" ||
fail "failed to convert to disk format $diskformat"
fi
[ "$output" != "$TEMP_D/final" ] || { cat "$output" && output="-"; } ||
fail "failed to write to -"
debug 1 "wrote ${output} with filesystem=$filesystem and diskformat=$diskformat"
# vi: ts=4 noexpandtab

@ -7,12 +7,16 @@ publish = false
[dependencies]
anyhow = "1"
aya = { path = "../../aya" }
aya-obj = { path = "../../aya-obj" }
clap = { version = "4", features = ["derive"] }
env_logger = "0.10"
inventory = "0.2"
inventory = "0.3"
integration-test-macros = { path = "../integration-test-macros" }
lazy_static = "1"
libc = { version = "0.2.105" }
log = "0.4"
object = { version = "0.30", default-features = false, features = ["std", "read_core", "elf"] }
rbpf = "0.1.0"
regex = "1"
tempfile = "3.3.0"
libtest-mimic = "0.6.0"

@ -1,74 +1,21 @@
use log::info;
use libtest_mimic::{Arguments, Trial};
mod tests;
use tests::IntegrationTest;
use clap::Parser;
#[derive(Debug, Parser)]
#[clap(author, version, about, long_about = None)]
#[clap(propagate_version = true)]
pub struct RunOptions {
#[clap(short, long, value_parser)]
tests: Option<Vec<String>>,
}
#[derive(Debug, Parser)]
struct Cli {
#[clap(subcommand)]
command: Option<Command>,
}
#[derive(Debug, Parser)]
enum Command {
/// Run one or more tests: ... -- run -t test1 -t test2
Run(RunOptions),
/// List all the tests: ... -- list
List,
}
macro_rules! exec_test {
($test:expr) => {{
info!("Running {}", $test.name);
($test.test_fn)();
}};
}
macro_rules! exec_all_tests {
() => {{
for t in inventory::iter::<IntegrationTest> {
exec_test!(t)
}
}};
}
fn main() -> anyhow::Result<()> {
fn main() {
env_logger::init();
let cli = Cli::parse();
match &cli.command {
Some(Command::Run(opts)) => match &opts.tests {
Some(tests) => {
for t in inventory::iter::<IntegrationTest> {
if tests.contains(&t.name.into()) {
exec_test!(t)
}
}
}
None => {
exec_all_tests!()
}
},
Some(Command::List) => {
for t in inventory::iter::<IntegrationTest> {
info!("{}", t.name);
}
}
None => {
exec_all_tests!()
}
}
Ok(())
let mut args = Arguments::from_args();
// Force to run single-threaded
args.test_threads = Some(1);
let tests = inventory::iter::<IntegrationTest>
.into_iter()
.map(|test| {
Trial::test(test.name, move || {
(test.test_fn)();
Ok(())
})
})
.collect();
libtest_mimic::run(&args, tests).exit();
}

@ -6,6 +6,8 @@ use std::{ffi::CStr, mem};
pub mod elf;
pub mod load;
pub mod rbpf;
pub mod relocations;
pub mod smoke;
pub use integration_test_macros::integration_test;

@ -0,0 +1,114 @@
use core::{mem::size_of, ptr::null_mut, slice::from_raw_parts};
use std::collections::HashMap;
use aya::include_bytes_aligned;
use aya_obj::{generated::bpf_insn, Object, ProgramSection};
use super::{integration_test, IntegrationTest};
#[integration_test]
fn run_with_rbpf() {
let bytes = include_bytes_aligned!("../../../../target/bpfel-unknown-none/debug/pass");
let object = Object::parse(bytes).unwrap();
assert_eq!(object.programs.len(), 1);
assert!(matches!(
object.programs["pass"].section,
ProgramSection::Xdp { .. }
));
assert_eq!(object.programs["pass"].section.name(), "pass");
let instructions = &object.programs["pass"].function.instructions;
let data = unsafe {
from_raw_parts(
instructions.as_ptr() as *const u8,
instructions.len() * size_of::<bpf_insn>(),
)
};
// Use rbpf interpreter instead of JIT compiler to ensure platform compatibility.
let vm = rbpf::EbpfVmNoData::new(Some(data)).unwrap();
const XDP_PASS: u64 = 2;
assert_eq!(vm.execute_program().unwrap(), XDP_PASS);
}
static mut MULTIMAP_MAPS: [*mut Vec<u64>; 2] = [null_mut(), null_mut()];
#[integration_test]
fn use_map_with_rbpf() {
let bytes =
include_bytes_aligned!("../../../../target/bpfel-unknown-none/debug/multimap-btf.bpf.o");
let mut object = Object::parse(bytes).unwrap();
assert_eq!(object.programs.len(), 1);
assert!(matches!(
object.programs["tracepoint"].section,
ProgramSection::TracePoint { .. }
));
assert_eq!(object.programs["tracepoint"].section.name(), "tracepoint");
// Initialize maps:
// - fd: 0xCAFE00 or 0xCAFE01 (the 0xCAFE00 part is used to distinguish fds from indices),
// - Note that rbpf does not convert fds into real pointers,
// so we keeps the pointers to our maps in MULTIMAP_MAPS, to be used in helpers.
let mut maps = HashMap::new();
let mut map_instances = vec![vec![0u64], vec![0u64]];
for (name, map) in object.maps.iter() {
assert_eq!(map.key_size(), size_of::<u32>() as u32);
assert_eq!(map.value_size(), size_of::<u64>() as u32);
assert_eq!(
map.map_type(),
aya_obj::generated::bpf_map_type::BPF_MAP_TYPE_ARRAY as u32
);
let map_id = if name == "map_1" { 0 } else { 1 };
let fd = map_id as i32 | 0xCAFE00;
maps.insert(name.to_owned(), (fd, map.clone()));
unsafe {
MULTIMAP_MAPS[map_id] = &mut map_instances[map_id] as *mut _;
}
}
object
.relocate_maps(
maps.iter()
.map(|(s, (fd, map))| (s.as_ref() as &str, Some(*fd), map)),
)
.expect("Relocation failed");
// Actually there is no local function call involved.
object.relocate_calls().unwrap();
// Executes the program
assert_eq!(object.programs.len(), 1);
let instructions = &object.programs["tracepoint"].function.instructions;
let data = unsafe {
from_raw_parts(
instructions.as_ptr() as *const u8,
instructions.len() * size_of::<bpf_insn>(),
)
};
let mut vm = rbpf::EbpfVmNoData::new(Some(data)).unwrap();
vm.register_helper(2, bpf_map_update_elem_multimap)
.expect("Helper failed");
assert_eq!(vm.execute_program().unwrap(), 0);
assert_eq!(map_instances[0][0], 24);
assert_eq!(map_instances[1][0], 42);
unsafe {
MULTIMAP_MAPS[0] = null_mut();
MULTIMAP_MAPS[1] = null_mut();
}
}
fn bpf_map_update_elem_multimap(map: u64, key: u64, value: u64, _: u64, _: u64) -> u64 {
assert!(map == 0xCAFE00 || map == 0xCAFE01);
let key = *unsafe { (key as usize as *const u32).as_ref().unwrap() };
let value = *unsafe { (value as usize as *const u64).as_ref().unwrap() };
assert_eq!(key, 0);
unsafe {
let map_instance = MULTIMAP_MAPS[map as usize & 0xFF].as_mut().unwrap();
map_instance[0] = value;
}
0
}

@ -0,0 +1,313 @@
use anyhow::{Context, Result};
use std::{path::PathBuf, process::Command, thread::sleep, time::Duration};
use tempfile::TempDir;
use aya::{maps::Array, programs::TracePoint, BpfLoader, Btf, Endianness};
use super::{integration_test, IntegrationTest};
// In the tests below we often use values like 0xAAAAAAAA or -0x7AAAAAAA. Those values have no
// special meaning, they just have "nice" bit patterns that can be helpful while debugging.
#[integration_test]
fn relocate_field() {
let test = RelocationTest {
local_definition: r#"
struct foo {
__u8 a;
__u8 b;
__u8 c;
__u8 d;
};
"#,
target_btf: r#"
struct foo {
__u8 a;
__u8 c;
__u8 b;
__u8 d;
} s1;
"#,
relocation_code: r#"
__u8 memory[] = {1, 2, 3, 4};
struct foo *ptr = (struct foo *) &memory;
value = __builtin_preserve_access_index(ptr->c);
"#,
}
.build()
.unwrap();
assert_eq!(test.run().unwrap(), 2);
assert_eq!(test.run_no_btf().unwrap(), 3);
}
#[integration_test]
fn relocate_enum() {
let test = RelocationTest {
local_definition: r#"
enum foo { D = 0xAAAAAAAA };
"#,
target_btf: r#"
enum foo { D = 0xBBBBBBBB } e1;
"#,
relocation_code: r#"
#define BPF_ENUMVAL_VALUE 1
value = __builtin_preserve_enum_value(*(typeof(enum foo) *)D, BPF_ENUMVAL_VALUE);
"#,
}
.build()
.unwrap();
assert_eq!(test.run().unwrap(), 0xBBBBBBBB);
assert_eq!(test.run_no_btf().unwrap(), 0xAAAAAAAA);
}
#[integration_test]
fn relocate_enum_signed() {
let test = RelocationTest {
local_definition: r#"
enum foo { D = -0x7AAAAAAA };
"#,
target_btf: r#"
enum foo { D = -0x7BBBBBBB } e1;
"#,
relocation_code: r#"
#define BPF_ENUMVAL_VALUE 1
value = __builtin_preserve_enum_value(*(typeof(enum foo) *)D, BPF_ENUMVAL_VALUE);
"#,
}
.build()
.unwrap();
assert_eq!(test.run().unwrap() as i64, -0x7BBBBBBBi64);
assert_eq!(test.run_no_btf().unwrap() as i64, -0x7AAAAAAAi64);
}
#[integration_test]
fn relocate_enum64() {
let test = RelocationTest {
local_definition: r#"
enum foo { D = 0xAAAAAAAABBBBBBBB };
"#,
target_btf: r#"
enum foo { D = 0xCCCCCCCCDDDDDDDD } e1;
"#,
relocation_code: r#"
#define BPF_ENUMVAL_VALUE 1
value = __builtin_preserve_enum_value(*(typeof(enum foo) *)D, BPF_ENUMVAL_VALUE);
"#,
}
.build()
.unwrap();
assert_eq!(test.run().unwrap(), 0xCCCCCCCCDDDDDDDD);
assert_eq!(test.run_no_btf().unwrap(), 0xAAAAAAAABBBBBBBB);
}
#[integration_test]
fn relocate_enum64_signed() {
let test = RelocationTest {
local_definition: r#"
enum foo { D = -0xAAAAAAABBBBBBBB };
"#,
target_btf: r#"
enum foo { D = -0xCCCCCCCDDDDDDDD } e1;
"#,
relocation_code: r#"
#define BPF_ENUMVAL_VALUE 1
value = __builtin_preserve_enum_value(*(typeof(enum foo) *)D, BPF_ENUMVAL_VALUE);
"#,
}
.build()
.unwrap();
assert_eq!(test.run().unwrap() as i64, -0xCCCCCCCDDDDDDDDi64);
assert_eq!(test.run_no_btf().unwrap() as i64, -0xAAAAAAABBBBBBBBi64);
}
#[integration_test]
fn relocate_pointer() {
let test = RelocationTest {
local_definition: r#"
struct foo {};
struct bar { struct foo *f; };
"#,
target_btf: r#"
struct foo {};
struct bar { struct foo *f; };
"#,
relocation_code: r#"
__u8 memory[] = {42, 0, 0, 0, 0, 0, 0, 0};
struct bar* ptr = (struct bar *) &memory;
value = (__u64) __builtin_preserve_access_index(ptr->f);
"#,
}
.build()
.unwrap();
assert_eq!(test.run().unwrap(), 42);
assert_eq!(test.run_no_btf().unwrap(), 42);
}
/// Utility code for running relocation tests:
/// - Generates the eBPF program using probided local definition and relocation code
/// - Generates the BTF from the target btf code
struct RelocationTest {
/// Data structure definition, local to the eBPF program and embedded in the eBPF bytecode
local_definition: &'static str,
/// Target data structure definition. What the vmlinux would actually contain.
target_btf: &'static str,
/// Code executed by the eBPF program to test the relocation.
/// The format should be:
// __u8 memory[] = { ... };
// __u32 value = BPF_CORE_READ((struct foo *)&memory, ...);
//
// The generated code will be executed by attaching a tracepoint to sched_switch
// and emitting `__u32 value` an a map. See the code template below for more details.
relocation_code: &'static str,
}
impl RelocationTest {
/// Build a RelocationTestRunner
fn build(&self) -> Result<RelocationTestRunner> {
Ok(RelocationTestRunner {
ebpf: self.build_ebpf()?,
btf: self.build_btf()?,
})
}
/// - Generate the source eBPF filling a template
/// - Compile it with clang
fn build_ebpf(&self) -> Result<Vec<u8>> {
let local_definition = self.local_definition;
let relocation_code = self.relocation_code;
let (_tmp_dir, compiled_file) = compile(&format!(
r#"
#include <linux/bpf.h>
static long (*bpf_map_update_elem)(void *map, const void *key, const void *value, __u64 flags) = (void *) 2;
{local_definition}
struct {{
int (*type)[BPF_MAP_TYPE_ARRAY];
__u32 *key;
__u64 *value;
int (*max_entries)[1];
}} output_map
__attribute__((section(".maps"), used));
__attribute__((section("tracepoint/bpf_prog"), used))
int bpf_prog(void *ctx) {{
__u32 key = 0;
__u64 value = 0;
{relocation_code}
bpf_map_update_elem(&output_map, &key, &value, BPF_ANY);
return 0;
}}
char _license[] __attribute__((section("license"), used)) = "GPL";
"#
))
.context("Failed to compile eBPF program")?;
let bytecode =
std::fs::read(compiled_file).context("Error reading compiled eBPF program")?;
Ok(bytecode)
}
/// - Generate the target BTF source with a mock main()
/// - Compile it with clang
/// - Extract the BTF with llvm-objcopy
fn build_btf(&self) -> Result<Btf> {
let target_btf = self.target_btf;
let relocation_code = self.relocation_code;
// BTF files can be generated and inspected with these commands:
// $ clang -c -g -O2 -target bpf target.c
// $ pahole --btf_encode_detached=target.btf -V target.o
// $ bpftool btf dump file ./target.btf format c
let (tmp_dir, compiled_file) = compile(&format!(
r#"
#include <linux/bpf.h>
{target_btf}
int main() {{
__u64 value = 0;
// This is needed to make sure to emit BTF for the defined types,
// it could be dead code eliminated if we don't.
{relocation_code};
return value;
}}
"#
))
.context("Failed to compile BTF")?;
Command::new("llvm-objcopy")
.current_dir(tmp_dir.path())
.args(["--dump-section", ".BTF=target.btf"])
.arg(compiled_file)
.status()
.context("Failed to run llvm-objcopy")?
.success()
.then_some(())
.context("Failed to extract BTF")?;
let btf = Btf::parse_file(tmp_dir.path().join("target.btf"), Endianness::default())
.context("Error parsing generated BTF")?;
Ok(btf)
}
}
/// Compile an eBPF program and return the path of the compiled object.
/// Also returns a TempDir handler, dropping it will clear the created dicretory.
fn compile(source_code: &str) -> Result<(TempDir, PathBuf)> {
let tmp_dir = tempfile::tempdir().context("Error making temp dir")?;
let source = tmp_dir.path().join("source.c");
std::fs::write(&source, source_code).context("Writing bpf program failed")?;
Command::new("clang")
.current_dir(&tmp_dir)
.args(["-c", "-g", "-O2", "-target", "bpf"])
.arg(&source)
.status()
.context("Failed to run clang")?
.success()
.then_some(())
.context("Failed to compile eBPF source")?;
Ok((tmp_dir, source.with_extension("o")))
}
struct RelocationTestRunner {
ebpf: Vec<u8>,
btf: Btf,
}
impl RelocationTestRunner {
/// Run test and return the output value
fn run(&self) -> Result<u64> {
self.run_internal(true).context("Error running with BTF")
}
/// Run without loading btf
fn run_no_btf(&self) -> Result<u64> {
self.run_internal(false)
.context("Error running without BTF")
}
fn run_internal(&self, with_relocations: bool) -> Result<u64> {
let mut loader = BpfLoader::new();
if with_relocations {
loader.btf(Some(&self.btf));
} else {
loader.btf(None);
}
let mut bpf = loader.load(&self.ebpf).context("Loading eBPF failed")?;
let program: &mut TracePoint = bpf
.program_mut("bpf_prog")
.context("bpf_prog not found")?
.try_into()
.context("program not a tracepoint")?;
program.load().context("Loading tracepoint failed")?;
// Attach to sched_switch and wait some time to make sure it executed at least once
program
.attach("sched", "sched_switch")
.context("attach failed")?;
sleep(Duration::from_millis(1000));
// To inspect the loaded eBPF bytecode, increse the timeout and run:
// $ sudo bpftool prog dump xlated name bpf_prog
let output_map: Array<_, u64> = bpf.take_map("output_map").unwrap().try_into().unwrap();
let key = 0;
output_map.get(&key, 0).context("Getting key 0 failed")
}
}

@ -19,7 +19,7 @@ fn xdp() {
#[integration_test]
fn extension() {
let (major, minor, _) = kernel_version().unwrap();
if major < 5 || minor < 9 {
if major < 5 || (minor == 5 && minor < 9) {
info!(
"skipping as {}.{} does not meet version requirement of 5.9",
major, minor

@ -2,20 +2,45 @@
set -e
if [ "$(uname -s)" = "Darwin" ]; then
export PATH="$(dirname $(brew list gnu-getopt | grep "bin/getopt$")):$PATH"
fi
AYA_SOURCE_DIR="$(realpath $(dirname $0)/..)"
LIBBPF_DIR=$1
# Temporary directory for tests to use.
AYA_TMPDIR="$(pwd)/.tmp"
AYA_TMPDIR="${AYA_SOURCE_DIR}/.tmp"
# Directory for VM images
AYA_IMGDIR=${AYA_TMPDIR}
# Test Architecture
if [ -z "${AYA_TEST_ARCH}" ]; then
AYA_TEST_ARCH="$(uname -m)"
if [ -z "${AYA_BUILD_TARGET}" ]; then
AYA_BUILD_TARGET=$(rustc -vV | sed -n 's|host: ||p')
fi
AYA_HOST_ARCH=$(uname -m)
if [ "${AYA_HOST_ARCH}" = "arm64" ]; then
AYA_HOST_ARCH="aarch64"
fi
if [ -z "${AYA_GUEST_ARCH}" ]; then
AYA_GUEST_ARCH="${AYA_HOST_ARCH}"
fi
if [ "${AYA_GUEST_ARCH}" = "aarch64" ]; then
if [ -z "${AARCH64_UEFI}" ]; then
AARCH64_UEFI="$(brew list qemu -1 -v | grep edk2-aarch64-code.fd)"
fi
fi
if [ -z "$AYA_MUSL_TARGET" ]; then
AYA_MUSL_TARGET=${AYA_GUEST_ARCH}-unknown-linux-musl
fi
# Test Image
if [ -z "${AYA_TEST_IMAGE}" ]; then
AYA_TEST_IMAGE="fedora36"
AYA_TEST_IMAGE="fedora37"
fi
case "${AYA_TEST_IMAGE}" in
@ -26,20 +51,20 @@ esac
download_images() {
mkdir -p "${AYA_IMGDIR}"
case $1 in
fedora36)
if [ ! -f "${AYA_IMGDIR}/fedora36.${AYA_TEST_ARCH}.qcow2" ]; then
IMAGE="Fedora-Cloud-Base-36-1.5.${AYA_TEST_ARCH}.qcow2"
IMAGE_URL="https://download.fedoraproject.org/pub/fedora/linux/releases/36/Cloud/${AYA_TEST_ARCH}/images"
fedora37)
if [ ! -f "${AYA_IMGDIR}/fedora37.${AYA_GUEST_ARCH}.qcow2" ]; then
IMAGE="Fedora-Cloud-Base-37-1.7.${AYA_GUEST_ARCH}.qcow2"
IMAGE_URL="https://download.fedoraproject.org/pub/fedora/linux/releases/37/Cloud/${AYA_GUEST_ARCH}/images"
echo "Downloading: ${IMAGE}, this may take a while..."
curl -o "${AYA_IMGDIR}/fedora36.${AYA_TEST_ARCH}.qcow2" -sSL "${IMAGE_URL}/${IMAGE}"
curl -o "${AYA_IMGDIR}/fedora37.${AYA_GUEST_ARCH}.qcow2" -sSL "${IMAGE_URL}/${IMAGE}"
fi
;;
centos8)
if [ ! -f "${AYA_IMGDIR}/centos8.${AYA_TEST_ARCH}.qcow2" ]; then
IMAGE="CentOS-8-GenericCloud-8.4.2105-20210603.0.${AYA_TEST_ARCH}.qcow2"
IMAGE_URL="https://cloud.centos.org/centos/8/${AYA_TEST_ARCH}/images"
if [ ! -f "${AYA_IMGDIR}/centos8.${AYA_GUEST_ARCH}.qcow2" ]; then
IMAGE="CentOS-8-GenericCloud-8.4.2105-20210603.0.${AYA_GUEST_ARCH}.qcow2"
IMAGE_URL="https://cloud.centos.org/centos/8/${AYA_GUEST_ARCH}/images"
echo "Downloading: ${IMAGE}, this may take a while..."
curl -o "${AYA_IMGDIR}/centos8.${AYA_TEST_ARCH}.qcow2" -sSL "${IMAGE_URL}/${IMAGE}"
curl -o "${AYA_IMGDIR}/centos8.${AYA_GUEST_ARCH}.qcow2" -sSL "${IMAGE_URL}/${IMAGE}"
fi
;;
*)
@ -60,11 +85,6 @@ EOF
if [ ! -f "${AYA_TMPDIR}/test_rsa" ]; then
ssh-keygen -t rsa -b 4096 -f "${AYA_TMPDIR}/test_rsa" -N "" -C "" -q
pub_key=$(cat "${AYA_TMPDIR}/test_rsa.pub")
cat > "${AYA_TMPDIR}/user-data.yaml" <<EOF
#cloud-config
ssh_authorized_keys:
- ${pub_key}
EOF
fi
if [ ! -f "${AYA_TMPDIR}/ssh_config" ]; then
@ -75,14 +95,20 @@ GlobalKnownHostsFile=/dev/null
EOF
fi
cloud-localds "${AYA_TMPDIR}/seed.img" "${AYA_TMPDIR}/user-data.yaml" "${AYA_TMPDIR}/metadata.yaml"
cat > "${AYA_TMPDIR}/user-data.yaml" <<EOF
#cloud-config
ssh_authorized_keys:
- ${pub_key}
EOF
case "${AYA_TEST_ARCH}" in
$AYA_SOURCE_DIR/test/cloud-localds "${AYA_TMPDIR}/seed.img" "${AYA_TMPDIR}/user-data.yaml" "${AYA_TMPDIR}/metadata.yaml"
case "${AYA_GUEST_ARCH}" in
x86_64)
QEMU=qemu-system-x86_64
machine="q35"
cpu="qemu64"
if [ "$(uname -m)" = "${AYA_TEST_ARCH}" ]; then
nr_cpus="$(nproc --all)"
if [ "${AYA_HOST_ARCH}" = "${AYA_GUEST_ARCH}" ]; then
if [ -c /dev/kvm ]; then
machine="${machine},accel=kvm"
cpu="host"
@ -96,34 +122,48 @@ EOF
QEMU=qemu-system-aarch64
machine="virt"
cpu="cortex-a57"
if [ "$(uname -m)" = "${AYA_TEST_ARCH}" ]; then
uefi="-drive file=${AARCH64_UEFI},if=pflash,format=raw,readonly=on"
if [ "${AYA_HOST_ARCH}" = "${AYA_GUEST_ARCH}" ]; then
if [ -c /dev/kvm ]; then
machine="${machine},accel=kvm"
cpu="host"
nr_cpus="$(nproc --all)"
elif [ "$(uname -s)" = "Darwin" ]; then
machine="${machine},accel=hvf"
cpu="host"
machine="${machine},accel=hvf,highmem=off"
cpu="cortex-a72"
# nrpoc --all on apple silicon returns the two extra fancy
# cores and then qemu complains that nr_cpus > actual_cores
nr_cpus=8
fi
fi
;;
*)
echo "${AYA_TEST_ARCH} is not supported"
echo "${AYA_GUEST_ARCH} is not supported"
return 1
;;
esac
qemu-img create -F qcow2 -f qcow2 -o backing_file="${AYA_IMGDIR}/${AYA_TEST_IMAGE}.${AYA_TEST_ARCH}.qcow2" "${AYA_TMPDIR}/vm.qcow2" || return 1
if [ ! -f "${AYA_IMGDIR}/vm.qcow2" ]; then
echo "Creating VM image"
qemu-img create -F qcow2 -f qcow2 -o backing_file="${AYA_IMGDIR}/${AYA_TEST_IMAGE}.${AYA_GUEST_ARCH}.qcow2" "${AYA_IMGDIR}/vm.qcow2" || return 1
CACHED_VM=0
else
echo "Reusing existing VM image"
CACHED_VM=1
fi
$QEMU \
-machine "${machine}" \
-cpu "${cpu}" \
-m 2G \
-m 3G \
-smp "${nr_cpus}" \
-display none \
-monitor none \
-daemonize \
-pidfile "${AYA_TMPDIR}/vm.pid" \
-device virtio-net-pci,netdev=net0 \
-netdev user,id=net0,hostfwd=tcp::2222-:22 \
-drive if=virtio,format=qcow2,file="${AYA_TMPDIR}/vm.qcow2" \
$uefi \
-drive if=virtio,format=qcow2,file="${AYA_IMGDIR}/vm.qcow2" \
-drive if=virtio,format=raw,file="${AYA_TMPDIR}/seed.img" || return 1
trap cleanup_vm EXIT
@ -139,8 +179,14 @@ EOF
sleep 1
done
echo "VM launched, installing dependencies"
exec_vm sudo dnf install -qy bpftool
echo "VM launched"
exec_vm uname -a
echo "Installing dependencies"
exec_vm sudo dnf install -qy bpftool llvm llvm-devel clang clang-devel zlib-devel
exec_vm 'curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- \
-y --profile minimal --default-toolchain nightly --component rust-src --component clippy'
exec_vm 'echo source ~/.cargo/env >> ~/.bashrc'
exec_vm cargo install bpf-linker --no-default-features --features system-llvm
}
scp_vm() {
@ -152,6 +198,10 @@ scp_vm() {
"${AYA_SSH_USER}@localhost:${remote}"
}
rsync_vm() {
rsync -a -e "ssh -p 2222 -F ${AYA_TMPDIR}/ssh_config -i ${AYA_TMPDIR}/test_rsa" $1 $AYA_SSH_USER@localhost:
}
exec_vm() {
ssh -q -F "${AYA_TMPDIR}/ssh_config" \
-i "${AYA_TMPDIR}/test_rsa" \
@ -166,23 +216,34 @@ stop_vm() {
kill -9 "$(cat "${AYA_TMPDIR}/vm.pid")"
rm "${AYA_TMPDIR}/vm.pid"
fi
rm -f "${AYA_TMPDIR}/vm.qcow2"
}
cleanup_vm() {
stop_vm
if [ "$?" != "0" ]; then
stop_vm
rm -f "${AYA_IMGDIR}/vm.qcow2"
fi
}
if [ -z "$1" ]; then
if [ -z "$LIBBPF_DIR" ]; then
echo "path to libbpf required"
exit 1
fi
start_vm
trap stop_vm EXIT
cargo xtask build-integration-test --musl --libbpf-dir "$1"
scp_vm ../target/x86_64-unknown-linux-musl/debug/integration-test
exec_vm sudo ./integration-test
trap cleanup_vm EXIT
# make sure we always use fresh aya and libbpf (also see comment at the end)
exec_vm "rm -rf aya/* libbpf"
rsync_vm "--exclude=target --exclude=.tmp $AYA_SOURCE_DIR"
rsync_vm "$LIBBPF_DIR"
# need to build or linting will fail trying to include object files
exec_vm "cd aya; cargo xtask build-integration-test --libbpf-dir ~/libbpf"
exec_vm "cd aya; cargo clippy -p integration-test -- --deny warnings"
exec_vm "cd aya; cargo xtask integration-test --libbpf-dir ~/libbpf"
# we rm and sync but it doesn't seem to work reliably - I guess we could sleep a
# few seconds after but ain't nobody got time for that. Instead we also rm
# before rsyncing.
exec_vm "rm -rf aya/* libbpf; sync"

@ -11,6 +11,6 @@ anyhow = "1"
syn = "1"
quote = "1"
proc-macro2 = "1"
indoc = "1.0"
indoc = "2.0"
lazy_static = "1"
serde_json = "1"

@ -5,9 +5,9 @@ use crate::build_ebpf;
#[derive(Parser)]
pub struct Options {
/// Whether to compile for the musl libc target
#[clap(short, long)]
pub musl: bool,
/// Target triple for which the code is compiled
#[clap(long)]
pub musl_target: Option<String>,
#[clap(flatten)]
pub ebpf_options: build_ebpf::BuildEbpfOptions,
@ -16,9 +16,12 @@ pub struct Options {
pub fn build_test(opts: Options) -> anyhow::Result<()> {
build_ebpf::build_ebpf(opts.ebpf_options)?;
let mut args = vec!["build", "-p", "integration-test", "--verbose"];
if opts.musl {
args.push("--target=x86_64-unknown-linux-musl");
let mut args = ["build", "-p", "integration-test", "--verbose"]
.iter()
.map(|s| s.to_string())
.collect::<Vec<_>>();
if let Some(target) = opts.musl_target {
args.push(format!("--target={target}"));
}
let status = Command::new("cargo")
.args(&args)

@ -11,7 +11,7 @@ pub fn codegen(opts: &Options) -> Result<(), anyhow::Error> {
}
fn codegen_internal_btf_bindings(opts: &Options) -> Result<(), anyhow::Error> {
let dir = PathBuf::from("aya");
let dir = PathBuf::from("aya-obj");
let generated = dir.join("src/generated");
let mut bindgen = bindgen::user_builder()
.clang_arg(format!(
@ -154,7 +154,7 @@ fn codegen_bindings(opts: &Options) -> Result<(), anyhow::Error> {
"BPF_RINGBUF_.*",
];
let dir = PathBuf::from("aya");
let dir = PathBuf::from("aya-obj");
let generated = dir.join("src/generated");
let builder = || {

@ -72,7 +72,7 @@ fn build_docs(working_dir: &PathBuf, abs_header_path: &Path) -> Result<(), anyho
abs_header_path.to_str().unwrap()
),
)
.args(&args)
.args(args)
.status()
.expect("failed to build aya docs");
assert!(status.success());

Loading…
Cancel
Save