Skip to content

Commit

Permalink
feat: Autogenerate all eBPF feature combinations
Browse files Browse the repository at this point in the history
* Add `bpf-features` crate which contains only the `BpfFeatures` struct
  with a static method `all_combinations`, which is then used both by
  `bpf-builder` (to build programs with all feature combinations) and
  and `bpf-common` (to pick the correct program based on detected
  features).
* Add `bpf-feature-autodetect` crate and move feature probes there.
* Add `bpf-features-macros` crate for with the `ebpf_programs_map`
  macro which autogenerates mapping of features to program bytes. The
  program bytes (for all feature sets) are still embedded in the final
  binary.
  • Loading branch information
vadorovsky committed May 13, 2024
1 parent 8e678f3 commit 7e6dbed
Show file tree
Hide file tree
Showing 23 changed files with 417 additions and 255 deletions.
98 changes: 78 additions & 20 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,12 @@ env_logger = { workspace = true }
futures-util = { workspace = true }
log = { workspace = true }
nix = { workspace = true }
quote = "1.0"
proc-macro2 = "1.0"
rust-ini = { workspace = true }
serde = { workspace = true }
semver = { workspace = true, features = ["serde"] }
syn = { version = "1.0", features = ["full"] }
tokio = { workspace = true, features = ["full"] }

[features]
Expand Down Expand Up @@ -65,6 +68,9 @@ members = [
"crates/engine-api",
"crates/validatron",
"crates/bpf-filtering",
"crates/bpf-features",
"crates/bpf-feature-autodetect",
"crates/bpf-features-macros",
"xtask",
"test-suite",
]
Expand All @@ -82,6 +88,9 @@ bpf-common = { path = "crates/bpf-common", features = [
"test-utils",
"test-suite",
] }
bpf-features = { path = "crates/bpf-features" }
bpf-feature-autodetect = { path = "crates/bpf-feature-autodetect" }
bpf-features-macros = { path = "crates/bpf-features-macros" }
bpf-filtering = { path = "crates/bpf-filtering", features = ["test-suite"] }
engine-api = { path = "crates/engine-api" }
pulsar-core = { path = "crates/pulsar-core" }
Expand Down
1 change: 1 addition & 0 deletions crates/bpf-builder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ repository.workspace = true

[dependencies]
anyhow = { workspace = true }
bpf-features = { workspace = true }
30 changes: 5 additions & 25 deletions crates/bpf-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::{
};

use anyhow::{bail, Context};
use bpf_features::BpfFeatures;

static CLANG_DEFAULT: &str = "clang";
static LLVM_STRIP: &str = "llvm-strip";
Expand All @@ -24,35 +25,14 @@ pub fn build(name: &str, source: &str) -> Result<(), Box<dyn std::error::Error>>
println!("cargo:rerun-if-changed={INCLUDE_PATH}/get_path.bpf.h");
println!("cargo:rerun-if-changed={INCLUDE_PATH}/task.bpf.h");

let features = [
("FEATURE_ATOMICS", "a"),
("FEATURE_CGROUP_TASK_BTF", "c"),
("FEATURE_FN_POINTERS", "f"),
("FEATURE_LSM", "l"),
];

let out_dir = env::var("OUT_DIR").context("OUT_DIR not set")?;
let out_path = Path::new(&out_dir).join(name);

for bits in 0..(1 << features.len()) {
let mut feature_args = Vec::new();
let mut suffix = String::new();

for (i, (feature, code)) in features.iter().enumerate() {
if bits & (1 << i) != 0 {
feature_args.push(format!("-D{}", feature));
suffix.push_str(code);
}
}

if suffix.is_empty() {
suffix.push_str("none");
}

let filename = format!("{}.{}.bpf.o", name, suffix);
for (_, (bpf_objfile_suffix, build_args)) in BpfFeatures::all_combinations() {
let filename = format!("{name}.{bpf_objfile_suffix}");
let full_path = out_path.with_file_name(filename);
compile(source, full_path, &feature_args)
.context("Error compiling programs with features: {feature_args:?}")?;
compile(source, full_path, &build_args)
.context("Error compiling programs with features: {build_args:?}")?;
}

Ok(())
Expand Down
5 changes: 3 additions & 2 deletions crates/bpf-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ sqlite3-vendored = ["libsqlite3-sys/bundled"]

[dependencies]
aya = { workspace = true, features = ["async_tokio"] }
aya-ebpf-bindings = { workspace = true }
aya-obj = { workspace = true }
bpf-features = { workspace = true }
bpf-feature-autodetect = { workspace = true }
bpf-features-macros = { workspace = true }
bytes = { workspace = true }
thiserror = { workspace = true }
tokio = { workspace = true, features = ["full"] }
Expand Down
3 changes: 0 additions & 3 deletions crates/bpf-common/build.rs

This file was deleted.

7 changes: 3 additions & 4 deletions crates/bpf-common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
mod bpf_sender;
pub mod containers;
pub mod insn;
pub mod program;
#[cfg(feature = "test-utils")]
pub mod test_runner;
Expand All @@ -14,16 +13,16 @@ mod bump_memlock_rlimit;
pub mod parsing;
pub mod time;

pub use bpf_feature_autodetect;
pub use bpf_features::BpfFeatures;
pub use bpf_features_macros::ebpf_programs_map;
pub use bpf_sender::{BpfSender, BpfSenderWrapper};
pub use bump_memlock_rlimit::bump_memlock_rlimit;
pub use program::{Program, ProgramBuilder, ProgramError};

pub use aya;

pub use aya_obj::generated::bpf_prog_type as BpfProgType;

pub mod bpf_fs;
pub mod feature_autodetect;

/// Utility function to pretty print an error with its sources.
///
Expand Down
Loading

0 comments on commit 7e6dbed

Please sign in to comment.