From c1b0feef7bd0822241bb991f339c81c2cf92c4e7 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 27 Nov 2024 15:33:28 -0500 Subject: [PATCH] Update for build scripts and aya-build --- docs/book/programs/cgroup-skb.md | 13 ++-- docs/book/programs/classifiers.md | 2 +- docs/book/programs/lsm.md | 2 +- docs/book/programs/probes.md | 2 +- docs/book/programs/xdp.md | 35 ++++----- docs/book/start/dropping-packets.md | 2 +- docs/book/start/hello-xdp.md | 18 ++--- examples/aya-tool/.cargo/config.toml | 2 - examples/aya-tool/Cargo.toml | 4 +- examples/aya-tool/README.md | 21 ++---- .../aya-tool/myapp-ebpf/.cargo/config.toml | 6 -- examples/aya-tool/myapp-ebpf/Cargo.toml | 3 + examples/aya-tool/myapp-ebpf/build.rs | 17 +++++ examples/aya-tool/myapp/Cargo.toml | 17 +++++ examples/aya-tool/myapp/build.rs | 15 ++++ examples/aya-tool/myapp/src/main.rs | 14 ++-- examples/aya-tool/xtask/Cargo.toml | 10 --- examples/aya-tool/xtask/src/build_ebpf.rs | 58 --------------- examples/aya-tool/xtask/src/main.rs | 33 --------- examples/aya-tool/xtask/src/run.rs | 71 ------------------- examples/cgroup-skb-egress/.cargo/config.toml | 2 - examples/cgroup-skb-egress/README.md | 21 ++---- .../cgroup-skb-egress-ebpf/.cargo/config.toml | 6 -- .../cgroup-skb-egress-ebpf/Cargo.toml | 3 + .../cgroup-skb-egress-ebpf/build.rs | 17 +++++ .../cgroup-skb-egress/Cargo.toml | 18 +++++ .../cgroup-skb-egress/build.rs | 17 +++++ .../cgroup-skb-egress/src/main.rs | 14 ++-- .../cgroup-skb-egress/xtask/src/build_ebpf.rs | 58 --------------- .../cgroup-skb-egress/xtask/src/codegen.rs | 16 ----- examples/cgroup-skb-egress/xtask/src/main.rs | 38 +++++----- examples/cgroup-skb-egress/xtask/src/run.rs | 71 ------------------- examples/kprobetcp/.cargo/config.toml | 2 - examples/kprobetcp/Cargo.toml | 4 +- examples/kprobetcp/README.md | 21 ++---- .../kprobetcp-ebpf/.cargo/config.toml | 6 -- examples/kprobetcp/kprobetcp-ebpf/Cargo.toml | 3 + examples/kprobetcp/kprobetcp-ebpf/build.rs | 17 +++++ examples/kprobetcp/kprobetcp/Cargo.toml | 18 +++++ examples/kprobetcp/kprobetcp/build.rs | 15 ++++ examples/kprobetcp/kprobetcp/src/main.rs | 14 ++-- examples/kprobetcp/xtask/Cargo.toml | 8 --- examples/kprobetcp/xtask/src/build_ebpf.rs | 58 --------------- examples/kprobetcp/xtask/src/main.rs | 33 --------- examples/kprobetcp/xtask/src/run.rs | 71 ------------------- examples/lsm-nice/.cargo/config.toml | 2 - examples/lsm-nice/Cargo.toml | 4 +- examples/lsm-nice/README.md | 21 ++---- .../lsm-nice/lsm-nice-ebpf/.cargo/config.toml | 6 -- examples/lsm-nice/lsm-nice-ebpf/Cargo.toml | 3 + examples/lsm-nice/lsm-nice-ebpf/build.rs | 17 +++++ examples/lsm-nice/lsm-nice/Cargo.toml | 17 +++++ examples/lsm-nice/lsm-nice/build.rs | 15 ++++ examples/lsm-nice/lsm-nice/src/main.rs | 16 +---- examples/lsm-nice/xtask/Cargo.toml | 10 --- examples/lsm-nice/xtask/src/build_ebpf.rs | 58 --------------- examples/lsm-nice/xtask/src/main.rs | 33 --------- examples/lsm-nice/xtask/src/run.rs | 71 ------------------- examples/tc-egress/.cargo/config.toml | 2 - examples/tc-egress/Cargo.toml | 4 +- examples/tc-egress/README.md | 21 ++---- .../tc-egress-ebpf/.cargo/config.toml | 6 -- examples/tc-egress/tc-egress-ebpf/Cargo.toml | 3 + examples/tc-egress/tc-egress-ebpf/build.rs | 17 +++++ examples/tc-egress/tc-egress/Cargo.toml | 17 +++++ examples/tc-egress/tc-egress/build.rs | 15 ++++ examples/tc-egress/tc-egress/src/main.rs | 14 ++-- examples/tc-egress/xtask/Cargo.toml | 9 --- examples/tc-egress/xtask/src/build_ebpf.rs | 58 --------------- examples/tc-egress/xtask/src/main.rs | 33 --------- examples/tc-egress/xtask/src/run.rs | 71 ------------------- examples/test.sh | 6 +- examples/xdp-drop/.cargo/config.toml | 2 - examples/xdp-drop/Cargo.toml | 4 +- examples/xdp-drop/README.md | 21 ++---- .../xdp-drop/xdp-drop-ebpf/.cargo/config.toml | 6 -- examples/xdp-drop/xdp-drop-ebpf/Cargo.toml | 3 + examples/xdp-drop/xdp-drop-ebpf/build.rs | 17 +++++ examples/xdp-drop/xdp-drop/Cargo.toml | 17 +++++ examples/xdp-drop/xdp-drop/build.rs | 15 ++++ examples/xdp-drop/xdp-drop/src/main.rs | 14 ++-- examples/xdp-drop/xtask/Cargo.toml | 10 --- examples/xdp-drop/xtask/src/build_ebpf.rs | 58 --------------- examples/xdp-drop/xtask/src/main.rs | 33 --------- examples/xdp-drop/xtask/src/run.rs | 71 ------------------- examples/xdp-hello/.cargo/config.toml | 2 - examples/xdp-hello/Cargo.toml | 4 +- examples/xdp-hello/README.md | 21 ++---- .../xdp-hello-ebpf/.cargo/config.toml | 6 -- examples/xdp-hello/xdp-hello-ebpf/Cargo.toml | 3 + examples/xdp-hello/xdp-hello-ebpf/build.rs | 17 +++++ examples/xdp-hello/xdp-hello/Cargo.toml | 17 +++++ examples/xdp-hello/xdp-hello/build.rs | 15 ++++ examples/xdp-hello/xdp-hello/src/main.rs | 18 ++--- examples/xdp-hello/xtask/Cargo.toml | 8 --- examples/xdp-hello/xtask/src/build_ebpf.rs | 58 --------------- examples/xdp-hello/xtask/src/main.rs | 33 --------- examples/xdp-hello/xtask/src/run.rs | 71 ------------------- examples/xdp-log/.cargo/config.toml | 2 - examples/xdp-log/Cargo.toml | 4 +- examples/xdp-log/README.md | 21 ++---- .../xdp-log/xdp-log-ebpf/.cargo/config.toml | 6 -- examples/xdp-log/xdp-log-ebpf/Cargo.toml | 3 + examples/xdp-log/xdp-log-ebpf/build.rs | 17 +++++ examples/xdp-log/xdp-log/Cargo.toml | 17 +++++ examples/xdp-log/xdp-log/build.rs | 15 ++++ examples/xdp-log/xdp-log/src/main.rs | 18 ++--- examples/xdp-log/xtask/Cargo.toml | 10 --- examples/xdp-log/xtask/src/build_ebpf.rs | 58 --------------- examples/xdp-log/xtask/src/main.rs | 33 --------- examples/xdp-log/xtask/src/run.rs | 71 ------------------- 111 files changed, 550 insertions(+), 1714 deletions(-) delete mode 100644 examples/aya-tool/.cargo/config.toml delete mode 100644 examples/aya-tool/myapp-ebpf/.cargo/config.toml create mode 100644 examples/aya-tool/myapp-ebpf/build.rs create mode 100644 examples/aya-tool/myapp/build.rs delete mode 100644 examples/aya-tool/xtask/Cargo.toml delete mode 100644 examples/aya-tool/xtask/src/build_ebpf.rs delete mode 100644 examples/aya-tool/xtask/src/main.rs delete mode 100644 examples/aya-tool/xtask/src/run.rs delete mode 100644 examples/cgroup-skb-egress/.cargo/config.toml delete mode 100644 examples/cgroup-skb-egress/cgroup-skb-egress-ebpf/.cargo/config.toml create mode 100644 examples/cgroup-skb-egress/cgroup-skb-egress-ebpf/build.rs create mode 100644 examples/cgroup-skb-egress/cgroup-skb-egress/build.rs delete mode 100644 examples/cgroup-skb-egress/xtask/src/build_ebpf.rs delete mode 100644 examples/cgroup-skb-egress/xtask/src/codegen.rs delete mode 100644 examples/cgroup-skb-egress/xtask/src/run.rs delete mode 100644 examples/kprobetcp/.cargo/config.toml delete mode 100644 examples/kprobetcp/kprobetcp-ebpf/.cargo/config.toml create mode 100644 examples/kprobetcp/kprobetcp-ebpf/build.rs create mode 100644 examples/kprobetcp/kprobetcp/build.rs delete mode 100644 examples/kprobetcp/xtask/Cargo.toml delete mode 100644 examples/kprobetcp/xtask/src/build_ebpf.rs delete mode 100644 examples/kprobetcp/xtask/src/main.rs delete mode 100644 examples/kprobetcp/xtask/src/run.rs delete mode 100644 examples/lsm-nice/.cargo/config.toml delete mode 100644 examples/lsm-nice/lsm-nice-ebpf/.cargo/config.toml create mode 100644 examples/lsm-nice/lsm-nice-ebpf/build.rs create mode 100644 examples/lsm-nice/lsm-nice/build.rs delete mode 100644 examples/lsm-nice/xtask/Cargo.toml delete mode 100644 examples/lsm-nice/xtask/src/build_ebpf.rs delete mode 100644 examples/lsm-nice/xtask/src/main.rs delete mode 100644 examples/lsm-nice/xtask/src/run.rs delete mode 100644 examples/tc-egress/.cargo/config.toml delete mode 100644 examples/tc-egress/tc-egress-ebpf/.cargo/config.toml create mode 100644 examples/tc-egress/tc-egress-ebpf/build.rs create mode 100644 examples/tc-egress/tc-egress/build.rs delete mode 100644 examples/tc-egress/xtask/Cargo.toml delete mode 100644 examples/tc-egress/xtask/src/build_ebpf.rs delete mode 100644 examples/tc-egress/xtask/src/main.rs delete mode 100644 examples/tc-egress/xtask/src/run.rs delete mode 100644 examples/xdp-drop/.cargo/config.toml delete mode 100644 examples/xdp-drop/xdp-drop-ebpf/.cargo/config.toml create mode 100644 examples/xdp-drop/xdp-drop-ebpf/build.rs create mode 100644 examples/xdp-drop/xdp-drop/build.rs delete mode 100644 examples/xdp-drop/xtask/Cargo.toml delete mode 100644 examples/xdp-drop/xtask/src/build_ebpf.rs delete mode 100644 examples/xdp-drop/xtask/src/main.rs delete mode 100644 examples/xdp-drop/xtask/src/run.rs delete mode 100644 examples/xdp-hello/.cargo/config.toml delete mode 100644 examples/xdp-hello/xdp-hello-ebpf/.cargo/config.toml create mode 100644 examples/xdp-hello/xdp-hello-ebpf/build.rs create mode 100644 examples/xdp-hello/xdp-hello/build.rs delete mode 100644 examples/xdp-hello/xtask/Cargo.toml delete mode 100644 examples/xdp-hello/xtask/src/build_ebpf.rs delete mode 100644 examples/xdp-hello/xtask/src/main.rs delete mode 100644 examples/xdp-hello/xtask/src/run.rs delete mode 100644 examples/xdp-log/.cargo/config.toml delete mode 100644 examples/xdp-log/xdp-log-ebpf/.cargo/config.toml create mode 100644 examples/xdp-log/xdp-log-ebpf/build.rs create mode 100644 examples/xdp-log/xdp-log/build.rs delete mode 100644 examples/xdp-log/xtask/Cargo.toml delete mode 100644 examples/xdp-log/xtask/src/build_ebpf.rs delete mode 100644 examples/xdp-log/xtask/src/main.rs delete mode 100644 examples/xdp-log/xtask/src/run.rs diff --git a/docs/book/programs/cgroup-skb.md b/docs/book/programs/cgroup-skb.md index 4210d329..d959f07c 100644 --- a/docs/book/programs/cgroup-skb.md +++ b/docs/book/programs/cgroup-skb.md @@ -48,12 +48,6 @@ easily reproduce it in the future by adding the following code: -=== "xtask/src/codegen.rs" - - ```rust linenums="1" - --8<-- "examples/cgroup-skb-egress/xtask/src/codegen.rs" - ``` - === "xtask/Cargo.toml" ```toml linenums="1" @@ -68,8 +62,9 @@ easily reproduce it in the future by adding the following code: -Once we've generated our file using `cargo xtask codegen` from the root of the -project, we can access it by including `mod bindings` from eBPF code. +Once we've generated our file using +`cargo xtask codegen cgroup-skb-egress-ebpf/src/bindings.rs` we can access it by +including `mod bindings` from eBPF code. ## eBPF code @@ -131,7 +126,7 @@ mkdir /sys/fs/cgroup/foo Then run the program with: ```console -RUST_LOG=info cargo xtask run +RUST_LOG=info cargo run --config 'target."cfg(all())".runner="sudo -E"' ``` And then, in a separate terminal, as root, try to access `1.1.1.1`: diff --git a/docs/book/programs/classifiers.md b/docs/book/programs/classifiers.md index 89e1e58a..1fdb8edf 100644 --- a/docs/book/programs/classifiers.md +++ b/docs/book/programs/classifiers.md @@ -88,7 +88,7 @@ is an appropriate type to use in eBPF maps. ## Running the program ```console -$ RUST_LOG=info cargo xtask run +$ RUST_LOG=info cargo run --config 'target."cfg(all())".runner="sudo -E"' LOG: SRC 1.1.1.1, ACTION 2 LOG: SRC 35.186.224.47, ACTION 3 LOG: SRC 35.186.224.47, ACTION 3 diff --git a/docs/book/programs/lsm.md b/docs/book/programs/lsm.md index 0b6802ef..34090454 100644 --- a/docs/book/programs/lsm.md +++ b/docs/book/programs/lsm.md @@ -174,7 +174,7 @@ The final result should look like: After that, we can build and run our project with: ```console -RUST_LOG=info cargo xtask run +RUST_LOG=info cargo run --config 'target."cfg(all())".runner="sudo -E"' ``` The output should contain our log line showing the PID of the userspace diff --git a/docs/book/programs/probes.md b/docs/book/programs/probes.md index c8c9e432..c701c9f9 100644 --- a/docs/book/programs/probes.md +++ b/docs/book/programs/probes.md @@ -56,7 +56,7 @@ Here's how the code looks like: ```console -$ RUST_LOG=info cargo xtask run --release +$ RUST_LOG=info cargo run --config 'target."cfg(all())".runner="sudo -E"' [2022-12-28T20:50:00Z INFO kprobetcp] Waiting for Ctrl-C... [2022-12-28T20:50:05Z INFO kprobetcp] AF_INET6 src addr: 2001:4998:efeb:282::249, dest addr: 2606:2800:220:1:248:1893:25c8:1946 [2022-12-28T20:50:11Z INFO kprobetcp] AF_INET src address: 10.53.149.148, dest address: 10.87.116.72 diff --git a/docs/book/programs/xdp.md b/docs/book/programs/xdp.md index c321e82d..d40539bc 100644 --- a/docs/book/programs/xdp.md +++ b/docs/book/programs/xdp.md @@ -429,10 +429,8 @@ Let's begin with writing the user-space code: ```rust use anyhow::Context; use aya::{ - include_bytes_aligned, maps::HashMap, programs::{Xdp, XdpFlags}, - Ebpf, }; use aya_log::EbpfLogger; use clap::Parser; @@ -482,14 +480,10 @@ async fn main() -> Result<(), anyhow::Error> { env_logger::init(); - #[cfg(debug_assertions)] - let mut bpf = Ebpf::load(include_bytes_aligned!( - "../../target/bpfel-unknown-none/debug/simple-xdp-program" - ))?; - #[cfg(not(debug_assertions))] - let mut bpf = Ebpf::load(include_bytes_aligned!( - "../../target/bpfel-unknown-none/release/xdp-simple-xdp-program" - ))?; + let mut bpf = aya::Ebpf::load(aya::include_bytes_aligned!(concat!( + env!("OUT_DIR"), + "/simple-xdp-program" + )))?; if let Err(e) = EbpfLogger::init(&mut bpf) { warn!("failed to initialize eBPF logger: {}", e); } @@ -552,10 +546,8 @@ The program awaits the `CTRL+C` signal asynchronously using ```rust use anyhow::Context; use aya::{ - include_bytes_aligned, maps::HashMap, programs::{Xdp, XdpFlags}, - Ebpf, }; use aya_log::EbpfLogger; use clap::Parser; @@ -575,14 +567,10 @@ async fn main() -> Result<(), anyhow::Error> { env_logger::init(); - #[cfg(debug_assertions)] - let mut bpf = Ebpf::load(include_bytes_aligned!( - "../../target/bpfel-unknown-none/debug/simple-xdp-program" - ))?; - #[cfg(not(debug_assertions))] - let mut bpf = Ebpf::load(include_bytes_aligned!( - "../../target/bpfel-unknown-none/release/xdp-simple-xdp-program" - ))?; + let mut bpf = aya::Ebpf::load(aya::include_bytes_aligned!(concat!( + env!("OUT_DIR"), + "/simple-xdp-program" + )))?; if let Err(e) = EbpfLogger::init(&mut bpf) { warn!("failed to initialize eBPF logger: {}", e); } @@ -614,17 +602,18 @@ async fn main() -> Result<(), anyhow::Error> { Now that we have all the pieces for our eBPF program, we can run it using: ```console -RUST_LOG=info cargo xtask run +RUST_LOG=info cargo run --config 'target."cfg(all())".runner="sudo -E"' ``` or ```console -RUST_LOG=info cargo xtask run -- --iface +RUST_LOG=info cargo run --config 'target."cfg(all())".runner="sudo -E"' -- \ + --iface ``` if you want to provide another network interface name. note that you can also -use `cargo xtask run` without the rest, but you won't get any logging. +omit `RUST_LOG=info`, but you won't get any logging. [source-code]: https://github.com/aya-rs/book/tree/main/examples/xdp-drop [af-xdp]: https://www.kernel.org/doc/html/latest/networking/af_xdp.html diff --git a/docs/book/start/dropping-packets.md b/docs/book/start/dropping-packets.md index 7d9090c8..26b8c0e4 100644 --- a/docs/book/start/dropping-packets.md +++ b/docs/book/start/dropping-packets.md @@ -69,7 +69,7 @@ Here's how the userspace code looks: ## Running the program ```console -$ RUST_LOG=info cargo xtask run +$ RUST_LOG=info cargo run --config 'target."cfg(all())".runner="sudo -E"' [2022-10-04T12:46:05Z INFO xdp_drop] SRC: 1.1.1.1, ACTION: 1 [2022-10-04T12:46:05Z INFO xdp_drop] SRC: 192.168.1.21, ACTION: 2 [2022-10-04T12:46:05Z INFO xdp_drop] SRC: 192.168.1.21, ACTION: 2 diff --git a/docs/book/start/hello-xdp.md b/docs/book/start/hello-xdp.md index 2e3d4dad..f12554f2 100644 --- a/docs/book/start/hello-xdp.md +++ b/docs/book/start/hello-xdp.md @@ -36,7 +36,7 @@ currently looks like this: 1. Write a log entry every time a packet is received. 1. This function returns a `Result` that permits all traffic. -Now we can compile this using `cargo xtask build-ebpf`. +Now we can compile this using `cargo build`. ### Verifying The Program @@ -141,10 +141,7 @@ Let's look at the details of our generated user-space application: Let's try it out! ```console -$ cargo xtask run -- -h - Finished dev [unoptimized + debuginfo] target(s) in 0.05s - Running `target/debug/xtask run -- -h` -: +$ cargo run -- -h Finished dev [optimized] target(s) in 0.90s Finished dev [unoptimized + debuginfo] target(s) in 0.60s xdp-hello @@ -160,11 +157,16 @@ OPTIONS: > [!NOTE] Interface Name > This command assumes the interface is `eth0` by default. If you wish to > attach to an interface with another name, use -> `RUST_LOG=info cargo xtask run -- --iface wlp2s0`, where `wlp2s0` is your -> interface. +> +> ```console +> RUST_LOG=info cargo run --config 'target."cfg(all())".runner="sudo -E"' -- \ +> --iface wlp2s0 +> ``` +> +> where `wlp2s0` is your interface. ```console -$ RUST_LOG=info cargo xtask run +$ RUST_LOG=info cargo run --config 'target."cfg(all())".runner="sudo -E"' [2022-12-21T18:03:09Z INFO xdp_hello] Waiting for Ctrl-C... [2022-12-21T18:03:11Z INFO xdp_hello] received a packet [2022-12-21T18:03:11Z INFO xdp_hello] received a packet diff --git a/examples/aya-tool/.cargo/config.toml b/examples/aya-tool/.cargo/config.toml deleted file mode 100644 index 35049cbc..00000000 --- a/examples/aya-tool/.cargo/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[alias] -xtask = "run --package xtask --" diff --git a/examples/aya-tool/Cargo.toml b/examples/aya-tool/Cargo.toml index 0a89a0df..da2a8496 100644 --- a/examples/aya-tool/Cargo.toml +++ b/examples/aya-tool/Cargo.toml @@ -1,9 +1,9 @@ [workspace] -members = ["xtask", "myapp", "myapp-common", "myapp-ebpf"] +members = ["myapp", "myapp-common", "myapp-ebpf"] resolver = "2" -default-members = ["xtask", "myapp", "myapp-common"] +default-members = ["myapp", "myapp-common"] [profile.release.package.myapp-ebpf] debug = 2 diff --git a/examples/aya-tool/README.md b/examples/aya-tool/README.md index 578140ca..dc573abf 100644 --- a/examples/aya-tool/README.md +++ b/examples/aya-tool/README.md @@ -6,23 +6,10 @@ 1. Install a rust nightly toolchain: `rustup install nightly` 1. Install bpf-linker: `cargo install bpf-linker` -## Build eBPF +## Build & Run -```console -cargo xtask build-ebpf -``` - -To perform a release build you can use the `--release` flag. -You may also change the target architecture with the `--target` flag - -## Build Userspace - -```console -cargo build -``` - -## Run +Use `cargo build`, `cargo check`, etc. as normal. Run your program with: -```console -cargo xtask run +```shell +RUST_LOG=info cargo run --config 'target."cfg(all())".runner="sudo -E"' ``` diff --git a/examples/aya-tool/myapp-ebpf/.cargo/config.toml b/examples/aya-tool/myapp-ebpf/.cargo/config.toml deleted file mode 100644 index 4302a7f1..00000000 --- a/examples/aya-tool/myapp-ebpf/.cargo/config.toml +++ /dev/null @@ -1,6 +0,0 @@ -[build] -target-dir = "../target" -target = "bpfel-unknown-none" - -[unstable] -build-std = ["core"] diff --git a/examples/aya-tool/myapp-ebpf/Cargo.toml b/examples/aya-tool/myapp-ebpf/Cargo.toml index 0cc9b41d..7a814da5 100644 --- a/examples/aya-tool/myapp-ebpf/Cargo.toml +++ b/examples/aya-tool/myapp-ebpf/Cargo.toml @@ -8,6 +8,9 @@ aya-ebpf = { git = "https://github.com/aya-rs/aya" } aya-log-ebpf = { git = "https://github.com/aya-rs/aya" } myapp-common = { path = "../myapp-common" } +[build-dependencies] +which = { version = "6.0.0", default-features = false } + [[bin]] name = "myapp" path = "src/main.rs" diff --git a/examples/aya-tool/myapp-ebpf/build.rs b/examples/aya-tool/myapp-ebpf/build.rs new file mode 100644 index 00000000..f83c317a --- /dev/null +++ b/examples/aya-tool/myapp-ebpf/build.rs @@ -0,0 +1,17 @@ +use which::which; + +/// Building this crate has an undeclared dependency on the `bpf-linker` binary. This would be +/// better expressed by [artifact-dependencies][bindeps] but issues such as +/// https://github.com/rust-lang/cargo/issues/12385 make their use impractical for the time being. +/// +/// This file implements an imperfect solution: it causes cargo to rebuild the crate whenever the +/// mtime of `which bpf-linker` changes. Note that possibility that a new bpf-linker is added to +/// $PATH ahead of the one used as the cache key still exists. Solving this in the general case +/// would require rebuild-if-changed-env=PATH *and* rebuild-if-changed={every-directory-in-PATH} +/// which would likely mean far too much cache invalidation. +/// +/// [bindeps]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html?highlight=feature#artifact-dependencies +fn main() { + let bpf_linker = which("bpf-linker").unwrap(); + println!("cargo:rerun-if-changed={}", bpf_linker.to_str().unwrap()); +} diff --git a/examples/aya-tool/myapp/Cargo.toml b/examples/aya-tool/myapp/Cargo.toml index 0e01e72d..0189e66e 100644 --- a/examples/aya-tool/myapp/Cargo.toml +++ b/examples/aya-tool/myapp/Cargo.toml @@ -20,6 +20,23 @@ tokio = { version = "1.25", features = [ env_logger = "0.11" log = "0.4" +[build-dependencies] +aya-build = { git = "https://github.com/aya-rs/aya" } +anyhow = "1" +# TODO(https://github.com/rust-lang/cargo/issues/12375): this should be an artifact dependency, but +# it's not possible to tell cargo to use `-Z build-std` to build it. We cargo-in-cargo in the build +# script to build this, but we want to teach cargo about the dependecy so that cache invalidation +# works properly. +# +# Note also that https://github.com/rust-lang/cargo/issues/10593 occurs when `target = ...` is added +# to an artifact dependency; it seems possible to work around that by setting `resolver = "1"` in +# Cargo.toml in the workspace root. +# +# Finally note that *any* usage of `artifact = ...` in *any* Cargo.toml in the workspace breaks +# workflows with stable cargo; stable cargo outright refuses to load manifests that use unstable +# features. +myapp-ebpf = { path = "../myapp-ebpf" } + [[bin]] name = "myapp" path = "src/main.rs" diff --git a/examples/aya-tool/myapp/build.rs b/examples/aya-tool/myapp/build.rs new file mode 100644 index 00000000..0f9bcbb4 --- /dev/null +++ b/examples/aya-tool/myapp/build.rs @@ -0,0 +1,15 @@ +use anyhow::{anyhow, Context as _}; +use aya_build::cargo_metadata; + +fn main() -> anyhow::Result<()> { + let cargo_metadata::Metadata { packages, .. } = + cargo_metadata::MetadataCommand::new() + .no_deps() + .exec() + .context("MetadataCommand::exec")?; + let ebpf_package = packages + .into_iter() + .find(|cargo_metadata::Package { name, .. }| name == "myapp-ebpf") + .ok_or_else(|| anyhow!("myapp-ebpf package not found"))?; + aya_build::build_ebpf([ebpf_package]) +} diff --git a/examples/aya-tool/myapp/src/main.rs b/examples/aya-tool/myapp/src/main.rs index 39fa1459..367a21c9 100644 --- a/examples/aya-tool/myapp/src/main.rs +++ b/examples/aya-tool/myapp/src/main.rs @@ -1,4 +1,4 @@ -use aya::{include_bytes_aligned, programs::Lsm, Btf, Ebpf}; +use aya::{programs::Lsm, Btf}; use log::info; use std::{ sync::{ @@ -22,14 +22,10 @@ fn try_main() -> Result<(), anyhow::Error> { // runtime. This approach is recommended for most real-world use cases. If you would // like to specify the eBPF program at runtime rather than at compile-time, you can // reach for `Ebpf::load_file` instead. - #[cfg(debug_assertions)] - let mut bpf = Ebpf::load(include_bytes_aligned!( - "../../target/bpfel-unknown-none/debug/myapp" - ))?; - #[cfg(not(debug_assertions))] - let mut bpf = Ebpf::load(include_bytes_aligned!( - "../../target/bpfel-unknown-none/release/myapp" - ))?; + let mut bpf = aya::Ebpf::load(aya::include_bytes_aligned!(concat!( + env!("OUT_DIR"), + "/myapp" + )))?; let btf = Btf::from_sys_fs()?; let program: &mut Lsm = diff --git a/examples/aya-tool/xtask/Cargo.toml b/examples/aya-tool/xtask/Cargo.toml deleted file mode 100644 index 06d009cd..00000000 --- a/examples/aya-tool/xtask/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "xtask" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -anyhow = "1" -clap = { version = "4.1", features = ["derive"] } diff --git a/examples/aya-tool/xtask/src/build_ebpf.rs b/examples/aya-tool/xtask/src/build_ebpf.rs deleted file mode 100644 index 938411d3..00000000 --- a/examples/aya-tool/xtask/src/build_ebpf.rs +++ /dev/null @@ -1,58 +0,0 @@ -use std::{path::PathBuf, process::Command}; - -use clap::Parser; - -#[derive(Debug, Copy, Clone)] -pub enum Architecture { - BpfEl, - BpfEb, -} - -impl std::str::FromStr for Architecture { - type Err = String; - - fn from_str(s: &str) -> Result { - Ok(match s { - "bpfel-unknown-none" => Architecture::BpfEl, - "bpfeb-unknown-none" => Architecture::BpfEb, - _ => return Err("invalid target".to_owned()), - }) - } -} - -impl std::fmt::Display for Architecture { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(match self { - Architecture::BpfEl => "bpfel-unknown-none", - Architecture::BpfEb => "bpfeb-unknown-none", - }) - } -} - -#[derive(Debug, Parser)] -pub struct Options { - /// Set the endianness of the BPF target - #[clap(default_value = "bpfel-unknown-none", long)] - pub target: Architecture, - /// Build the release target - #[clap(long)] - pub release: bool, -} - -pub fn build_ebpf(opts: Options) -> Result<(), anyhow::Error> { - let dir = PathBuf::from("myapp-ebpf"); - let target = format!("--target={}", opts.target); - let mut args = vec!["build", target.as_str(), "-Z", "build-std=core"]; - if opts.release { - args.push("--release") - } - - let status = Command::new("cargo") - .arg("+nightly") - .current_dir(dir) - .args(&args) - .status() - .expect("failed to build bpf program"); - assert!(status.success()); - Ok(()) -} diff --git a/examples/aya-tool/xtask/src/main.rs b/examples/aya-tool/xtask/src/main.rs deleted file mode 100644 index c1c594e0..00000000 --- a/examples/aya-tool/xtask/src/main.rs +++ /dev/null @@ -1,33 +0,0 @@ -mod build_ebpf; -mod run; - -use std::process::exit; - -use clap::Parser; - -#[derive(Debug, Parser)] -pub struct Options { - #[clap(subcommand)] - command: Command, -} - -#[derive(Debug, Parser)] -enum Command { - BuildEbpf(build_ebpf::Options), - Run(run::Options), -} - -fn main() { - let opts = Options::parse(); - - use Command::*; - let ret = match opts.command { - BuildEbpf(opts) => build_ebpf::build_ebpf(opts), - Run(opts) => run::run(opts), - }; - - if let Err(e) = ret { - eprintln!("{e:#}"); - exit(1); - } -} diff --git a/examples/aya-tool/xtask/src/run.rs b/examples/aya-tool/xtask/src/run.rs deleted file mode 100644 index 01019fd4..00000000 --- a/examples/aya-tool/xtask/src/run.rs +++ /dev/null @@ -1,71 +0,0 @@ -use std::process::Command; - -use anyhow::Context as _; -use clap::Parser; - -use crate::build_ebpf::{build_ebpf, Architecture, Options as BuildOptions}; - -#[derive(Debug, Parser)] -pub struct Options { - /// Set the endianness of the BPF target - #[clap(default_value = "bpfel-unknown-none", long)] - pub bpf_target: Architecture, - /// Build and run the release target - #[clap(long)] - pub release: bool, - /// The command used to wrap your application - #[clap(short, long, default_value = "sudo -E")] - pub runner: String, - /// Arguments to pass to your application - #[clap(name = "args", last = true)] - pub run_args: Vec, -} - -/// Build the project -fn build(opts: &Options) -> Result<(), anyhow::Error> { - let mut args = vec!["build"]; - if opts.release { - args.push("--release") - } - let status = Command::new("cargo") - .args(&args) - .status() - .expect("failed to build userspace"); - assert!(status.success()); - Ok(()) -} - -/// Build and run the project -pub fn run(opts: Options) -> Result<(), anyhow::Error> { - // build our ebpf program followed by our application - build_ebpf(BuildOptions { - target: opts.bpf_target, - release: opts.release, - }) - .context("Error while building eBPF program")?; - build(&opts).context("Error while building userspace application")?; - - // profile we are building (release or debug) - let profile = if opts.release { "release" } else { "debug" }; - let bin_path = format!("target/{profile}/myapp"); - - // arguments to pass to the application - let mut run_args: Vec<_> = - opts.run_args.iter().map(String::as_str).collect(); - - // configure args - let mut args: Vec<_> = opts.runner.trim().split_terminator(' ').collect(); - args.push(bin_path.as_str()); - args.append(&mut run_args); - - // run the command - let status = Command::new(args.first().expect("No first argument")) - .args(args.iter().skip(1)) - .status() - .expect("failed to run the command"); - - if !status.success() { - anyhow::bail!("Failed to run `{}`", args.join(" ")); - } - Ok(()) -} diff --git a/examples/cgroup-skb-egress/.cargo/config.toml b/examples/cgroup-skb-egress/.cargo/config.toml deleted file mode 100644 index 35049cbc..00000000 --- a/examples/cgroup-skb-egress/.cargo/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[alias] -xtask = "run --package xtask --" diff --git a/examples/cgroup-skb-egress/README.md b/examples/cgroup-skb-egress/README.md index ba2c3a7f..7be16335 100644 --- a/examples/cgroup-skb-egress/README.md +++ b/examples/cgroup-skb-egress/README.md @@ -6,23 +6,10 @@ 1. Install a rust nightly toolchain: `rustup install nightly` 1. Install bpf-linker: `cargo install bpf-linker` -## Build eBPF +## Build & Run -```console -cargo xtask build-ebpf -``` - -To perform a release build you can use the `--release` flag. -You may also change the target architecture with the `--target` flag - -## Build Userspace - -```console -cargo build -``` - -## Run +Use `cargo build`, `cargo check`, etc. as normal. Run your program with: -```console -cargo xtask run +```shell +RUST_LOG=info cargo run --config 'target."cfg(all())".runner="sudo -E"' ``` diff --git a/examples/cgroup-skb-egress/cgroup-skb-egress-ebpf/.cargo/config.toml b/examples/cgroup-skb-egress/cgroup-skb-egress-ebpf/.cargo/config.toml deleted file mode 100644 index 4302a7f1..00000000 --- a/examples/cgroup-skb-egress/cgroup-skb-egress-ebpf/.cargo/config.toml +++ /dev/null @@ -1,6 +0,0 @@ -[build] -target-dir = "../target" -target = "bpfel-unknown-none" - -[unstable] -build-std = ["core"] diff --git a/examples/cgroup-skb-egress/cgroup-skb-egress-ebpf/Cargo.toml b/examples/cgroup-skb-egress/cgroup-skb-egress-ebpf/Cargo.toml index d082083b..a722505b 100644 --- a/examples/cgroup-skb-egress/cgroup-skb-egress-ebpf/Cargo.toml +++ b/examples/cgroup-skb-egress/cgroup-skb-egress-ebpf/Cargo.toml @@ -9,6 +9,9 @@ aya-log-ebpf = { git = "https://github.com/aya-rs/aya" } cgroup-skb-egress-common = { path = "../cgroup-skb-egress-common" } memoffset = "0.9" +[build-dependencies] +which = { version = "6.0.0", default-features = false } + [[bin]] name = "cgroup-skb-egress" path = "src/main.rs" diff --git a/examples/cgroup-skb-egress/cgroup-skb-egress-ebpf/build.rs b/examples/cgroup-skb-egress/cgroup-skb-egress-ebpf/build.rs new file mode 100644 index 00000000..f83c317a --- /dev/null +++ b/examples/cgroup-skb-egress/cgroup-skb-egress-ebpf/build.rs @@ -0,0 +1,17 @@ +use which::which; + +/// Building this crate has an undeclared dependency on the `bpf-linker` binary. This would be +/// better expressed by [artifact-dependencies][bindeps] but issues such as +/// https://github.com/rust-lang/cargo/issues/12385 make their use impractical for the time being. +/// +/// This file implements an imperfect solution: it causes cargo to rebuild the crate whenever the +/// mtime of `which bpf-linker` changes. Note that possibility that a new bpf-linker is added to +/// $PATH ahead of the one used as the cache key still exists. Solving this in the general case +/// would require rebuild-if-changed-env=PATH *and* rebuild-if-changed={every-directory-in-PATH} +/// which would likely mean far too much cache invalidation. +/// +/// [bindeps]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html?highlight=feature#artifact-dependencies +fn main() { + let bpf_linker = which("bpf-linker").unwrap(); + println!("cargo:rerun-if-changed={}", bpf_linker.to_str().unwrap()); +} diff --git a/examples/cgroup-skb-egress/cgroup-skb-egress/Cargo.toml b/examples/cgroup-skb-egress/cgroup-skb-egress/Cargo.toml index fab9d5a6..9a8f210a 100644 --- a/examples/cgroup-skb-egress/cgroup-skb-egress/Cargo.toml +++ b/examples/cgroup-skb-egress/cgroup-skb-egress/Cargo.toml @@ -23,6 +23,24 @@ tokio = { version = "1.25", features = [ ] } bytes = "1" + +[build-dependencies] +aya-build = { git = "https://github.com/aya-rs/aya" } +anyhow = "1" +# TODO(https://github.com/rust-lang/cargo/issues/12375): this should be an artifact dependency, but +# it's not possible to tell cargo to use `-Z build-std` to build it. We cargo-in-cargo in the build +# script to build this, but we want to teach cargo about the dependecy so that cache invalidation +# works properly. +# +# Note also that https://github.com/rust-lang/cargo/issues/10593 occurs when `target = ...` is added +# to an artifact dependency; it seems possible to work around that by setting `resolver = "1"` in +# Cargo.toml in the workspace root. +# +# Finally note that *any* usage of `artifact = ...` in *any* Cargo.toml in the workspace breaks +# workflows with stable cargo; stable cargo outright refuses to load manifests that use unstable +# features. +cgroup-skb-egress-ebpf = { path = "../cgroup-skb-egress-ebpf" } + [[bin]] name = "cgroup-skb-egress" path = "src/main.rs" diff --git a/examples/cgroup-skb-egress/cgroup-skb-egress/build.rs b/examples/cgroup-skb-egress/cgroup-skb-egress/build.rs new file mode 100644 index 00000000..4d0815b5 --- /dev/null +++ b/examples/cgroup-skb-egress/cgroup-skb-egress/build.rs @@ -0,0 +1,17 @@ +use anyhow::{anyhow, Context as _}; +use aya_build::cargo_metadata; + +fn main() -> anyhow::Result<()> { + let cargo_metadata::Metadata { packages, .. } = + cargo_metadata::MetadataCommand::new() + .no_deps() + .exec() + .context("MetadataCommand::exec")?; + let ebpf_package = packages + .into_iter() + .find(|cargo_metadata::Package { name, .. }| { + name == "cgroup-skb-egress-ebpf" + }) + .ok_or_else(|| anyhow!("cgroup-skb-egress-ebpf package not found"))?; + aya_build::build_ebpf([ebpf_package]) +} diff --git a/examples/cgroup-skb-egress/cgroup-skb-egress/src/main.rs b/examples/cgroup-skb-egress/cgroup-skb-egress/src/main.rs index 8200d760..bbe41ae6 100644 --- a/examples/cgroup-skb-egress/cgroup-skb-egress/src/main.rs +++ b/examples/cgroup-skb-egress/cgroup-skb-egress/src/main.rs @@ -1,11 +1,9 @@ use std::net::Ipv4Addr; use aya::{ - include_bytes_aligned, maps::{perf::AsyncPerfEventArray, HashMap}, programs::{CgroupAttachMode, CgroupSkb, CgroupSkbAttachType}, util::online_cpus, - Ebpf, }; use bytes::BytesMut; use clap::Parser; @@ -30,14 +28,10 @@ async fn main() -> Result<(), anyhow::Error> { // runtime. This approach is recommended for most real-world use cases. If you would // like to specify the eBPF program at runtime rather than at compile-time, you can // reach for `Ebpf::load_file` instead. - #[cfg(debug_assertions)] - let mut bpf = Ebpf::load(include_bytes_aligned!( - "../../target/bpfel-unknown-none/debug/cgroup-skb-egress" - ))?; - #[cfg(not(debug_assertions))] - let mut bpf = Ebpf::load(include_bytes_aligned!( - "../../target/bpfel-unknown-none/release/cgroup-skb-egress" - ))?; + let mut bpf = aya::Ebpf::load(aya::include_bytes_aligned!(concat!( + env!("OUT_DIR"), + "/cgroup-skb-egress" + )))?; let program: &mut CgroupSkb = bpf.program_mut("cgroup_skb_egress").unwrap().try_into()?; let cgroup = std::fs::File::open(opt.cgroup_path)?; diff --git a/examples/cgroup-skb-egress/xtask/src/build_ebpf.rs b/examples/cgroup-skb-egress/xtask/src/build_ebpf.rs deleted file mode 100644 index 79eb4c16..00000000 --- a/examples/cgroup-skb-egress/xtask/src/build_ebpf.rs +++ /dev/null @@ -1,58 +0,0 @@ -use std::{path::PathBuf, process::Command}; - -use clap::Parser; - -#[derive(Debug, Copy, Clone)] -pub enum Architecture { - BpfEl, - BpfEb, -} - -impl std::str::FromStr for Architecture { - type Err = String; - - fn from_str(s: &str) -> Result { - Ok(match s { - "bpfel-unknown-none" => Architecture::BpfEl, - "bpfeb-unknown-none" => Architecture::BpfEb, - _ => return Err("invalid target".to_owned()), - }) - } -} - -impl std::fmt::Display for Architecture { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(match self { - Architecture::BpfEl => "bpfel-unknown-none", - Architecture::BpfEb => "bpfeb-unknown-none", - }) - } -} - -#[derive(Debug, Parser)] -pub struct Options { - /// Set the endianness of the BPF target - #[clap(default_value = "bpfel-unknown-none", long)] - pub target: Architecture, - /// Build the release target - #[clap(long)] - pub release: bool, -} - -pub fn build_ebpf(opts: Options) -> Result<(), anyhow::Error> { - let dir = PathBuf::from("cgroup-skb-egress-ebpf"); - let target = format!("--target={}", opts.target); - let mut args = vec!["build", target.as_str(), "-Z", "build-std=core"]; - if opts.release { - args.push("--release") - } - - let status = Command::new("cargo") - .arg("+nightly") - .current_dir(&dir) - .args(&args) - .status() - .expect("failed to build bpf program"); - assert!(status.success()); - Ok(()) -} diff --git a/examples/cgroup-skb-egress/xtask/src/codegen.rs b/examples/cgroup-skb-egress/xtask/src/codegen.rs deleted file mode 100644 index 0b4bc60c..00000000 --- a/examples/cgroup-skb-egress/xtask/src/codegen.rs +++ /dev/null @@ -1,16 +0,0 @@ -use aya_tool::generate::InputFile; -use std::{fs::File, io::Write, path::PathBuf}; - -pub fn generate() -> Result<(), anyhow::Error> { - let dir = PathBuf::from("cgroup-skb-egress-ebpf/src"); - let names: Vec<&str> = vec!["iphdr"]; - let bindings = aya_tool::generate( - InputFile::Btf(PathBuf::from("/sys/kernel/btf/vmlinux")), - &names, - &[], - )?; - // Write the bindings to the $OUT_DIR/bindings.rs file. - let mut out = File::create(dir.join("bindings.rs"))?; - write!(out, "{bindings}")?; - Ok(()) -} diff --git a/examples/cgroup-skb-egress/xtask/src/main.rs b/examples/cgroup-skb-egress/xtask/src/main.rs index c3dd6601..c7f39e1a 100644 --- a/examples/cgroup-skb-egress/xtask/src/main.rs +++ b/examples/cgroup-skb-egress/xtask/src/main.rs @@ -1,9 +1,4 @@ -mod build_ebpf; -mod codegen; -mod run; - -use std::process::exit; - +use anyhow::{Context as _, Result}; use clap::Parser; #[derive(Debug, Parser)] @@ -14,23 +9,22 @@ pub struct Options { #[derive(Debug, Parser)] enum Command { - BuildEbpf(build_ebpf::Options), - Run(run::Options), - Codegen, + Codegen { output: std::path::PathBuf }, } -fn main() { - let opts = Options::parse(); - - use Command::*; - let ret = match opts.command { - BuildEbpf(opts) => build_ebpf::build_ebpf(opts), - Run(opts) => run::run(opts), - Codegen => codegen::generate(), - }; - - if let Err(e) = ret { - eprintln!("{e:#}"); - exit(1); +fn main() -> Result<()> { + match Parser::parse() { + Command::Codegen { output } => { + let bindings = aya_tool::generate( + aya_tool::generate::InputFile::Btf(std::path::PathBuf::from( + "/sys/kernel/btf/vmlinux", + )), + &["iphdr"], + &[], + ) + .context("generate")?; + std::fs::write(&output, &bindings).context("write")?; + } } + Ok(()) } diff --git a/examples/cgroup-skb-egress/xtask/src/run.rs b/examples/cgroup-skb-egress/xtask/src/run.rs deleted file mode 100644 index 8bfe9f98..00000000 --- a/examples/cgroup-skb-egress/xtask/src/run.rs +++ /dev/null @@ -1,71 +0,0 @@ -use std::process::Command; - -use anyhow::Context as _; -use clap::Parser; - -use crate::build_ebpf::{build_ebpf, Architecture, Options as BuildOptions}; - -#[derive(Debug, Parser)] -pub struct Options { - /// Set the endianness of the BPF target - #[clap(default_value = "bpfel-unknown-none", long)] - pub bpf_target: Architecture, - /// Build and run the release target - #[clap(long)] - pub release: bool, - /// The command used to wrap your application - #[clap(short, long, default_value = "sudo -E")] - pub runner: String, - /// Arguments to pass to your application - #[clap(name = "args", last = true)] - pub run_args: Vec, -} - -/// Build the project -fn build(opts: &Options) -> Result<(), anyhow::Error> { - let mut args = vec!["build"]; - if opts.release { - args.push("--release") - } - let status = Command::new("cargo") - .args(&args) - .status() - .expect("failed to build userspace"); - assert!(status.success()); - Ok(()) -} - -/// Build and run the project -pub fn run(opts: Options) -> Result<(), anyhow::Error> { - // build our ebpf program followed by our application - build_ebpf(BuildOptions { - target: opts.bpf_target, - release: opts.release, - }) - .context("Error while building eBPF program")?; - build(&opts).context("Error while building userspace application")?; - - // profile we are building (release or debug) - let profile = if opts.release { "release" } else { "debug" }; - let bin_path = format!("target/{profile}/cgroup-skb-egress"); - - // arguments to pass to the application - let mut run_args: Vec<_> = - opts.run_args.iter().map(String::as_str).collect(); - - // configure args - let mut args: Vec<_> = opts.runner.trim().split_terminator(' ').collect(); - args.push(bin_path.as_str()); - args.append(&mut run_args); - - // run the command - let status = Command::new(args.first().expect("No first argument")) - .args(args.iter().skip(1)) - .status() - .expect("failed to run the command"); - - if !status.success() { - anyhow::bail!("Failed to run `{}`", args.join(" ")); - } - Ok(()) -} diff --git a/examples/kprobetcp/.cargo/config.toml b/examples/kprobetcp/.cargo/config.toml deleted file mode 100644 index 35049cbc..00000000 --- a/examples/kprobetcp/.cargo/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[alias] -xtask = "run --package xtask --" diff --git a/examples/kprobetcp/Cargo.toml b/examples/kprobetcp/Cargo.toml index a104f1c1..1d36aa2f 100644 --- a/examples/kprobetcp/Cargo.toml +++ b/examples/kprobetcp/Cargo.toml @@ -1,9 +1,9 @@ [workspace] -members = ["xtask", "kprobetcp", "kprobetcp-common", "kprobetcp-ebpf"] +members = ["kprobetcp", "kprobetcp-common", "kprobetcp-ebpf"] resolver = "2" -default-members = ["xtask", "kprobetcp", "kprobetcp-common"] +default-members = ["kprobetcp", "kprobetcp-common"] [profile.release.package.kprobetcp-ebpf] diff --git a/examples/kprobetcp/README.md b/examples/kprobetcp/README.md index 12c83248..f62ec3f2 100644 --- a/examples/kprobetcp/README.md +++ b/examples/kprobetcp/README.md @@ -10,25 +10,12 @@ sockets for the TCP connections (IPv4 and IPv6). 1. Install a rust nightly toolchain: `rustup install nightly` 1. Install bpf-linker: `cargo install bpf-linker` -## Build eBPF +## Build & Run -```console -cargo xtask build-ebpf -``` - -To perform a release build you can use the `--release` flag. -You may also change the target architecture with the `--target` flag. +Use `cargo build`, `cargo check`, etc. as normal. Run your program with: -## Build Userspace - -```console -cargo build -``` - -## Run - -```console -RUST_LOG=info cargo xtask run +```shell +RUST_LOG=info cargo run --config 'target."cfg(all())".runner="sudo -E"' ``` Execute some TCP connection in a different terminal, such as diff --git a/examples/kprobetcp/kprobetcp-ebpf/.cargo/config.toml b/examples/kprobetcp/kprobetcp-ebpf/.cargo/config.toml deleted file mode 100644 index 4302a7f1..00000000 --- a/examples/kprobetcp/kprobetcp-ebpf/.cargo/config.toml +++ /dev/null @@ -1,6 +0,0 @@ -[build] -target-dir = "../target" -target = "bpfel-unknown-none" - -[unstable] -build-std = ["core"] diff --git a/examples/kprobetcp/kprobetcp-ebpf/Cargo.toml b/examples/kprobetcp/kprobetcp-ebpf/Cargo.toml index 67b89c2b..1156837a 100644 --- a/examples/kprobetcp/kprobetcp-ebpf/Cargo.toml +++ b/examples/kprobetcp/kprobetcp-ebpf/Cargo.toml @@ -8,6 +8,9 @@ aya-ebpf = { git = "https://github.com/aya-rs/aya" } aya-log-ebpf = { git = "https://github.com/aya-rs/aya" } kprobetcp-common = { path = "../kprobetcp-common" } +[build-dependencies] +which = { version = "6.0.0", default-features = false } + [[bin]] name = "kprobetcp" path = "src/main.rs" diff --git a/examples/kprobetcp/kprobetcp-ebpf/build.rs b/examples/kprobetcp/kprobetcp-ebpf/build.rs new file mode 100644 index 00000000..f83c317a --- /dev/null +++ b/examples/kprobetcp/kprobetcp-ebpf/build.rs @@ -0,0 +1,17 @@ +use which::which; + +/// Building this crate has an undeclared dependency on the `bpf-linker` binary. This would be +/// better expressed by [artifact-dependencies][bindeps] but issues such as +/// https://github.com/rust-lang/cargo/issues/12385 make their use impractical for the time being. +/// +/// This file implements an imperfect solution: it causes cargo to rebuild the crate whenever the +/// mtime of `which bpf-linker` changes. Note that possibility that a new bpf-linker is added to +/// $PATH ahead of the one used as the cache key still exists. Solving this in the general case +/// would require rebuild-if-changed-env=PATH *and* rebuild-if-changed={every-directory-in-PATH} +/// which would likely mean far too much cache invalidation. +/// +/// [bindeps]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html?highlight=feature#artifact-dependencies +fn main() { + let bpf_linker = which("bpf-linker").unwrap(); + println!("cargo:rerun-if-changed={}", bpf_linker.to_str().unwrap()); +} diff --git a/examples/kprobetcp/kprobetcp/Cargo.toml b/examples/kprobetcp/kprobetcp/Cargo.toml index 11eb22aa..868d676b 100644 --- a/examples/kprobetcp/kprobetcp/Cargo.toml +++ b/examples/kprobetcp/kprobetcp/Cargo.toml @@ -21,6 +21,24 @@ tokio = { version = "1.25", features = [ "signal", ] } + +[build-dependencies] +aya-build = { git = "https://github.com/aya-rs/aya" } +anyhow = "1" +# TODO(https://github.com/rust-lang/cargo/issues/12375): this should be an artifact dependency, but +# it's not possible to tell cargo to use `-Z build-std` to build it. We cargo-in-cargo in the build +# script to build this, but we want to teach cargo about the dependecy so that cache invalidation +# works properly. +# +# Note also that https://github.com/rust-lang/cargo/issues/10593 occurs when `target = ...` is added +# to an artifact dependency; it seems possible to work around that by setting `resolver = "1"` in +# Cargo.toml in the workspace root. +# +# Finally note that *any* usage of `artifact = ...` in *any* Cargo.toml in the workspace breaks +# workflows with stable cargo; stable cargo outright refuses to load manifests that use unstable +# features. +kprobetcp-ebpf = { path = "../kprobetcp-ebpf" } + [[bin]] name = "kprobetcp" path = "src/main.rs" diff --git a/examples/kprobetcp/kprobetcp/build.rs b/examples/kprobetcp/kprobetcp/build.rs new file mode 100644 index 00000000..605b7807 --- /dev/null +++ b/examples/kprobetcp/kprobetcp/build.rs @@ -0,0 +1,15 @@ +use anyhow::{anyhow, Context as _}; +use aya_build::cargo_metadata; + +fn main() -> anyhow::Result<()> { + let cargo_metadata::Metadata { packages, .. } = + cargo_metadata::MetadataCommand::new() + .no_deps() + .exec() + .context("MetadataCommand::exec")?; + let ebpf_package = packages + .into_iter() + .find(|cargo_metadata::Package { name, .. }| name == "kprobetcp-ebpf") + .ok_or_else(|| anyhow!("kprobetcp-ebpf package not found"))?; + aya_build::build_ebpf([ebpf_package]) +} diff --git a/examples/kprobetcp/kprobetcp/src/main.rs b/examples/kprobetcp/kprobetcp/src/main.rs index dfd48fff..f8cc25e0 100644 --- a/examples/kprobetcp/kprobetcp/src/main.rs +++ b/examples/kprobetcp/kprobetcp/src/main.rs @@ -1,4 +1,4 @@ -use aya::{include_bytes_aligned, programs::KProbe, Ebpf}; +use aya::programs::KProbe; use aya_log::EbpfLogger; use clap::Parser; use log::{info, warn}; @@ -17,14 +17,10 @@ async fn main() -> Result<(), anyhow::Error> { // runtime. This approach is recommended for most real-world use cases. If you would // like to specify the eBPF program at runtime rather than at compile-time, you can // reach for `Ebpf::load_file` instead. - #[cfg(debug_assertions)] - let mut bpf = Ebpf::load(include_bytes_aligned!( - "../../target/bpfel-unknown-none/debug/kprobetcp" - ))?; - #[cfg(not(debug_assertions))] - let mut bpf = Ebpf::load(include_bytes_aligned!( - "../../target/bpfel-unknown-none/release/kprobetcp" - ))?; + let mut bpf = aya::Ebpf::load(aya::include_bytes_aligned!(concat!( + env!("OUT_DIR"), + "/kprobetcp" + )))?; if let Err(e) = EbpfLogger::init(&mut bpf) { // This can happen if you remove all log statements from your eBPF program. warn!("failed to initialize eBPF logger: {e}"); diff --git a/examples/kprobetcp/xtask/Cargo.toml b/examples/kprobetcp/xtask/Cargo.toml deleted file mode 100644 index c4dea5d1..00000000 --- a/examples/kprobetcp/xtask/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "xtask" -version = "0.1.0" -edition = "2021" - -[dependencies] -anyhow = "1" -clap = { version = "4.1", features = ["derive"] } diff --git a/examples/kprobetcp/xtask/src/build_ebpf.rs b/examples/kprobetcp/xtask/src/build_ebpf.rs deleted file mode 100644 index c54e1c7b..00000000 --- a/examples/kprobetcp/xtask/src/build_ebpf.rs +++ /dev/null @@ -1,58 +0,0 @@ -use std::{path::PathBuf, process::Command}; - -use clap::Parser; - -#[derive(Debug, Copy, Clone)] -pub enum Architecture { - BpfEl, - BpfEb, -} - -impl std::str::FromStr for Architecture { - type Err = String; - - fn from_str(s: &str) -> Result { - Ok(match s { - "bpfel-unknown-none" => Architecture::BpfEl, - "bpfeb-unknown-none" => Architecture::BpfEb, - _ => return Err("invalid target".to_owned()), - }) - } -} - -impl std::fmt::Display for Architecture { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(match self { - Architecture::BpfEl => "bpfel-unknown-none", - Architecture::BpfEb => "bpfeb-unknown-none", - }) - } -} - -#[derive(Debug, Parser)] -pub struct Options { - /// Set the endianness of the BPF target - #[clap(default_value = "bpfel-unknown-none", long)] - pub target: Architecture, - /// Build the release target - #[clap(long)] - pub release: bool, -} - -pub fn build_ebpf(opts: Options) -> Result<(), anyhow::Error> { - let dir = PathBuf::from("kprobetcp-ebpf"); - let target = format!("--target={}", opts.target); - let mut args = vec!["build", target.as_str(), "-Z", "build-std=core"]; - if opts.release { - args.push("--release") - } - - let status = Command::new("cargo") - .arg("+nightly") - .current_dir(&dir) - .args(&args) - .status() - .expect("failed to build bpf program"); - assert!(status.success()); - Ok(()) -} diff --git a/examples/kprobetcp/xtask/src/main.rs b/examples/kprobetcp/xtask/src/main.rs deleted file mode 100644 index c1c594e0..00000000 --- a/examples/kprobetcp/xtask/src/main.rs +++ /dev/null @@ -1,33 +0,0 @@ -mod build_ebpf; -mod run; - -use std::process::exit; - -use clap::Parser; - -#[derive(Debug, Parser)] -pub struct Options { - #[clap(subcommand)] - command: Command, -} - -#[derive(Debug, Parser)] -enum Command { - BuildEbpf(build_ebpf::Options), - Run(run::Options), -} - -fn main() { - let opts = Options::parse(); - - use Command::*; - let ret = match opts.command { - BuildEbpf(opts) => build_ebpf::build_ebpf(opts), - Run(opts) => run::run(opts), - }; - - if let Err(e) = ret { - eprintln!("{e:#}"); - exit(1); - } -} diff --git a/examples/kprobetcp/xtask/src/run.rs b/examples/kprobetcp/xtask/src/run.rs deleted file mode 100644 index d63e323e..00000000 --- a/examples/kprobetcp/xtask/src/run.rs +++ /dev/null @@ -1,71 +0,0 @@ -use std::process::Command; - -use anyhow::Context as _; -use clap::Parser; - -use crate::build_ebpf::{build_ebpf, Architecture, Options as BuildOptions}; - -#[derive(Debug, Parser)] -pub struct Options { - /// Set the endianness of the BPF target - #[clap(default_value = "bpfel-unknown-none", long)] - pub bpf_target: Architecture, - /// Build and run the release target - #[clap(long)] - pub release: bool, - /// The command used to wrap your application - #[clap(short, long, default_value = "sudo -E")] - pub runner: String, - /// Arguments to pass to your application - #[clap(name = "args", last = true)] - pub run_args: Vec, -} - -/// Build the project -fn build(opts: &Options) -> Result<(), anyhow::Error> { - let mut args = vec!["build"]; - if opts.release { - args.push("--release") - } - let status = Command::new("cargo") - .args(&args) - .status() - .expect("failed to build userspace"); - assert!(status.success()); - Ok(()) -} - -/// Build and run the project -pub fn run(opts: Options) -> Result<(), anyhow::Error> { - // build our ebpf program followed by our application - build_ebpf(BuildOptions { - target: opts.bpf_target, - release: opts.release, - }) - .context("Error while building eBPF program")?; - build(&opts).context("Error while building userspace application")?; - - // profile we are building (release or debug) - let profile = if opts.release { "release" } else { "debug" }; - let bin_path = format!("target/{profile}/kprobetcp"); - - // arguments to pass to the application - let mut run_args: Vec<_> = - opts.run_args.iter().map(String::as_str).collect(); - - // configure args - let mut args: Vec<_> = opts.runner.trim().split_terminator(' ').collect(); - args.push(bin_path.as_str()); - args.append(&mut run_args); - - // run the command - let status = Command::new(args.first().expect("No first argument")) - .args(args.iter().skip(1)) - .status() - .expect("failed to run the command"); - - if !status.success() { - anyhow::bail!("Failed to run `{}`", args.join(" ")); - } - Ok(()) -} diff --git a/examples/lsm-nice/.cargo/config.toml b/examples/lsm-nice/.cargo/config.toml deleted file mode 100644 index 35049cbc..00000000 --- a/examples/lsm-nice/.cargo/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[alias] -xtask = "run --package xtask --" diff --git a/examples/lsm-nice/Cargo.toml b/examples/lsm-nice/Cargo.toml index 2c64da3e..0df384ba 100644 --- a/examples/lsm-nice/Cargo.toml +++ b/examples/lsm-nice/Cargo.toml @@ -1,9 +1,9 @@ [workspace] -members = ["xtask", "lsm-nice", "lsm-nice-common", "lsm-nice-ebpf"] +members = ["lsm-nice", "lsm-nice-common", "lsm-nice-ebpf"] resolver = "2" -default-members = ["xtask", "lsm-nice", "lsm-nice-common"] +default-members = ["lsm-nice", "lsm-nice-common"] [profile.release.package.lsm-nice-ebpf] diff --git a/examples/lsm-nice/README.md b/examples/lsm-nice/README.md index c31f5104..289c3cf0 100644 --- a/examples/lsm-nice/README.md +++ b/examples/lsm-nice/README.md @@ -6,23 +6,10 @@ 1. Install a rust nightly toolchain: `rustup install nightly` 1. Install bpf-linker: `cargo install bpf-linker` -## Build eBPF +## Build & Run -```console -cargo xtask build-ebpf -``` - -To perform a release build you can use the `--release` flag. -You may also change the target architecture with the `--target` flag - -## Build Userspace - -```console -cargo build -``` - -## Run +Use `cargo build`, `cargo check`, etc. as normal. Run your program with: -```console -cargo xtask run +```shell +RUST_LOG=info cargo run --config 'target."cfg(all())".runner="sudo -E"' ``` diff --git a/examples/lsm-nice/lsm-nice-ebpf/.cargo/config.toml b/examples/lsm-nice/lsm-nice-ebpf/.cargo/config.toml deleted file mode 100644 index 4302a7f1..00000000 --- a/examples/lsm-nice/lsm-nice-ebpf/.cargo/config.toml +++ /dev/null @@ -1,6 +0,0 @@ -[build] -target-dir = "../target" -target = "bpfel-unknown-none" - -[unstable] -build-std = ["core"] diff --git a/examples/lsm-nice/lsm-nice-ebpf/Cargo.toml b/examples/lsm-nice/lsm-nice-ebpf/Cargo.toml index 89d47773..7209a9c2 100644 --- a/examples/lsm-nice/lsm-nice-ebpf/Cargo.toml +++ b/examples/lsm-nice/lsm-nice-ebpf/Cargo.toml @@ -8,6 +8,9 @@ aya-ebpf = { git = "http://github.com/aya-rs/aya" } aya-log-ebpf = { git = "https://github.com/aya-rs/aya" } lsm-nice-common = { path = "../lsm-nice-common" } +[build-dependencies] +which = { version = "6.0.0", default-features = false } + [[bin]] name = "lsm-nice" path = "src/main.rs" diff --git a/examples/lsm-nice/lsm-nice-ebpf/build.rs b/examples/lsm-nice/lsm-nice-ebpf/build.rs new file mode 100644 index 00000000..f83c317a --- /dev/null +++ b/examples/lsm-nice/lsm-nice-ebpf/build.rs @@ -0,0 +1,17 @@ +use which::which; + +/// Building this crate has an undeclared dependency on the `bpf-linker` binary. This would be +/// better expressed by [artifact-dependencies][bindeps] but issues such as +/// https://github.com/rust-lang/cargo/issues/12385 make their use impractical for the time being. +/// +/// This file implements an imperfect solution: it causes cargo to rebuild the crate whenever the +/// mtime of `which bpf-linker` changes. Note that possibility that a new bpf-linker is added to +/// $PATH ahead of the one used as the cache key still exists. Solving this in the general case +/// would require rebuild-if-changed-env=PATH *and* rebuild-if-changed={every-directory-in-PATH} +/// which would likely mean far too much cache invalidation. +/// +/// [bindeps]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html?highlight=feature#artifact-dependencies +fn main() { + let bpf_linker = which("bpf-linker").unwrap(); + println!("cargo:rerun-if-changed={}", bpf_linker.to_str().unwrap()); +} diff --git a/examples/lsm-nice/lsm-nice/Cargo.toml b/examples/lsm-nice/lsm-nice/Cargo.toml index 78ea8ee9..e8e008cf 100644 --- a/examples/lsm-nice/lsm-nice/Cargo.toml +++ b/examples/lsm-nice/lsm-nice/Cargo.toml @@ -20,6 +20,23 @@ tokio = { version = "1.25", features = [ ] } env_logger = "0.11" +[build-dependencies] +aya-build = { git = "https://github.com/aya-rs/aya" } +anyhow = "1" +# TODO(https://github.com/rust-lang/cargo/issues/12375): this should be an artifact dependency, but +# it's not possible to tell cargo to use `-Z build-std` to build it. We cargo-in-cargo in the build +# script to build this, but we want to teach cargo about the dependecy so that cache invalidation +# works properly. +# +# Note also that https://github.com/rust-lang/cargo/issues/10593 occurs when `target = ...` is added +# to an artifact dependency; it seems possible to work around that by setting `resolver = "1"` in +# Cargo.toml in the workspace root. +# +# Finally note that *any* usage of `artifact = ...` in *any* Cargo.toml in the workspace breaks +# workflows with stable cargo; stable cargo outright refuses to load manifests that use unstable +# features. +lsm-nice-ebpf = { path = "../lsm-nice-ebpf" } + [[bin]] name = "lsm-nice" path = "src/main.rs" diff --git a/examples/lsm-nice/lsm-nice/build.rs b/examples/lsm-nice/lsm-nice/build.rs new file mode 100644 index 00000000..7f54a9e9 --- /dev/null +++ b/examples/lsm-nice/lsm-nice/build.rs @@ -0,0 +1,15 @@ +use anyhow::{anyhow, Context as _}; +use aya_build::cargo_metadata; + +fn main() -> anyhow::Result<()> { + let cargo_metadata::Metadata { packages, .. } = + cargo_metadata::MetadataCommand::new() + .no_deps() + .exec() + .context("MetadataCommand::exec")?; + let ebpf_package = packages + .into_iter() + .find(|cargo_metadata::Package { name, .. }| name == "lsm-nice-ebpf") + .ok_or_else(|| anyhow!("lsm-nice-ebpf package not found"))?; + aya_build::build_ebpf([ebpf_package]) +} diff --git a/examples/lsm-nice/lsm-nice/src/main.rs b/examples/lsm-nice/lsm-nice/src/main.rs index eedf2000..d2addeab 100644 --- a/examples/lsm-nice/lsm-nice/src/main.rs +++ b/examples/lsm-nice/lsm-nice/src/main.rs @@ -1,6 +1,6 @@ use std::process; -use aya::{include_bytes_aligned, programs::Lsm, Btf, EbpfLoader}; +use aya::{programs::Lsm, Btf}; use aya_log::EbpfLogger; use log::{info, warn}; use tokio::signal; @@ -17,18 +17,8 @@ async fn main() -> Result<(), anyhow::Error> { // runtime. This approach is recommended for most real-world use cases. If you would // like to specify the eBPF program at runtime rather than at compile-time, you can // reach for `Ebpf::load_file` instead. - #[cfg(debug_assertions)] - let mut bpf = EbpfLoader::new().set_global("PID", &pid, true).load( - include_bytes_aligned!( - "../../target/bpfel-unknown-none/debug/lsm-nice" - ), - )?; - - #[cfg(not(debug_assertions))] - let mut bpf = EbpfLoader::new().set_global("PID", &pid, true).load( - include_bytes_aligned!( - "../../target/bpfel-unknown-none/release/lsm-nice" - ), + let mut bpf = aya::EbpfLoader::new().set_global("PID", &pid, true).load( + aya::include_bytes_aligned!(concat!(env!("OUT_DIR"), "/lsm-nice")), )?; if let Err(e) = EbpfLogger::init(&mut bpf) { // This can happen if you remove all log statements from your eBPF program. diff --git a/examples/lsm-nice/xtask/Cargo.toml b/examples/lsm-nice/xtask/Cargo.toml deleted file mode 100644 index 06d009cd..00000000 --- a/examples/lsm-nice/xtask/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "xtask" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -anyhow = "1" -clap = { version = "4.1", features = ["derive"] } diff --git a/examples/lsm-nice/xtask/src/build_ebpf.rs b/examples/lsm-nice/xtask/src/build_ebpf.rs deleted file mode 100644 index 90f90010..00000000 --- a/examples/lsm-nice/xtask/src/build_ebpf.rs +++ /dev/null @@ -1,58 +0,0 @@ -use std::{path::PathBuf, process::Command}; - -use clap::Parser; - -#[derive(Debug, Copy, Clone)] -pub enum Architecture { - BpfEl, - BpfEb, -} - -impl std::str::FromStr for Architecture { - type Err = String; - - fn from_str(s: &str) -> Result { - Ok(match s { - "bpfel-unknown-none" => Architecture::BpfEl, - "bpfeb-unknown-none" => Architecture::BpfEb, - _ => return Err("invalid target".to_owned()), - }) - } -} - -impl std::fmt::Display for Architecture { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(match self { - Architecture::BpfEl => "bpfel-unknown-none", - Architecture::BpfEb => "bpfeb-unknown-none", - }) - } -} - -#[derive(Debug, Parser)] -pub struct Options { - /// Set the endianness of the BPF target - #[clap(default_value = "bpfel-unknown-none", long)] - pub target: Architecture, - /// Build the release target - #[clap(long)] - pub release: bool, -} - -pub fn build_ebpf(opts: Options) -> Result<(), anyhow::Error> { - let dir = PathBuf::from("lsm-nice-ebpf"); - let target = format!("--target={}", opts.target); - let mut args = vec!["build", target.as_str(), "-Z", "build-std=core"]; - if opts.release { - args.push("--release") - } - - let status = Command::new("cargo") - .arg("+nightly") - .current_dir(dir) - .args(&args) - .status() - .expect("failed to build bpf program"); - assert!(status.success()); - Ok(()) -} diff --git a/examples/lsm-nice/xtask/src/main.rs b/examples/lsm-nice/xtask/src/main.rs deleted file mode 100644 index c1c594e0..00000000 --- a/examples/lsm-nice/xtask/src/main.rs +++ /dev/null @@ -1,33 +0,0 @@ -mod build_ebpf; -mod run; - -use std::process::exit; - -use clap::Parser; - -#[derive(Debug, Parser)] -pub struct Options { - #[clap(subcommand)] - command: Command, -} - -#[derive(Debug, Parser)] -enum Command { - BuildEbpf(build_ebpf::Options), - Run(run::Options), -} - -fn main() { - let opts = Options::parse(); - - use Command::*; - let ret = match opts.command { - BuildEbpf(opts) => build_ebpf::build_ebpf(opts), - Run(opts) => run::run(opts), - }; - - if let Err(e) = ret { - eprintln!("{e:#}"); - exit(1); - } -} diff --git a/examples/lsm-nice/xtask/src/run.rs b/examples/lsm-nice/xtask/src/run.rs deleted file mode 100644 index 2722a8c5..00000000 --- a/examples/lsm-nice/xtask/src/run.rs +++ /dev/null @@ -1,71 +0,0 @@ -use std::process::Command; - -use anyhow::Context as _; -use clap::Parser; - -use crate::build_ebpf::{build_ebpf, Architecture, Options as BuildOptions}; - -#[derive(Debug, Parser)] -pub struct Options { - /// Set the endianness of the BPF target - #[clap(default_value = "bpfel-unknown-none", long)] - pub bpf_target: Architecture, - /// Build and run the release target - #[clap(long)] - pub release: bool, - /// The command used to wrap your application - #[clap(short, long, default_value = "sudo -E")] - pub runner: String, - /// Arguments to pass to your application - #[clap(name = "args", last = true)] - pub run_args: Vec, -} - -/// Build the project -fn build(opts: &Options) -> Result<(), anyhow::Error> { - let mut args = vec!["build"]; - if opts.release { - args.push("--release") - } - let status = Command::new("cargo") - .args(&args) - .status() - .expect("failed to build userspace"); - assert!(status.success()); - Ok(()) -} - -/// Build and run the project -pub fn run(opts: Options) -> Result<(), anyhow::Error> { - // build our ebpf program followed by our application - build_ebpf(BuildOptions { - target: opts.bpf_target, - release: opts.release, - }) - .context("Error while building eBPF program")?; - build(&opts).context("Error while building userspace application")?; - - // profile we are building (release or debug) - let profile = if opts.release { "release" } else { "debug" }; - let bin_path = format!("target/{profile}/lsm-nice"); - - // arguments to pass to the application - let mut run_args: Vec<_> = - opts.run_args.iter().map(String::as_str).collect(); - - // configure args - let mut args: Vec<_> = opts.runner.trim().split_terminator(' ').collect(); - args.push(bin_path.as_str()); - args.append(&mut run_args); - - // run the command - let status = Command::new(args.first().expect("No first argument")) - .args(args.iter().skip(1)) - .status() - .expect("failed to run the command"); - - if !status.success() { - anyhow::bail!("Failed to run `{}`", args.join(" ")); - } - Ok(()) -} diff --git a/examples/tc-egress/.cargo/config.toml b/examples/tc-egress/.cargo/config.toml deleted file mode 100644 index 35049cbc..00000000 --- a/examples/tc-egress/.cargo/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[alias] -xtask = "run --package xtask --" diff --git a/examples/tc-egress/Cargo.toml b/examples/tc-egress/Cargo.toml index 3bbc18ee..980b2b73 100644 --- a/examples/tc-egress/Cargo.toml +++ b/examples/tc-egress/Cargo.toml @@ -1,9 +1,9 @@ [workspace] -members = ["xtask", "tc-egress", "tc-egress-common", "tc-egress-ebpf"] +members = ["tc-egress", "tc-egress-common", "tc-egress-ebpf"] resolver = "2" -default-members = ["xtask", "tc-egress", "tc-egress-common"] +default-members = ["tc-egress", "tc-egress-common"] [profile.release.package.tc-egress-ebpf] diff --git a/examples/tc-egress/README.md b/examples/tc-egress/README.md index 9d2818cc..88080af2 100644 --- a/examples/tc-egress/README.md +++ b/examples/tc-egress/README.md @@ -6,23 +6,10 @@ 1. Install a rust nightly toolchain: `rustup install nightly` 1. Install bpf-linker: `cargo install bpf-linker` -## Build eBPF +## Build & Run -```console -cargo xtask build-ebpf -``` - -To perform a release build you can use the `--release` flag. -You may also change the target architecture with the `--target` flag - -## Build Userspace - -```console -cargo build -``` - -## Run +Use `cargo build`, `cargo check`, etc. as normal. Run your program with: -```console -cargo xtask run +```shell +RUST_LOG=info cargo run --config 'target."cfg(all())".runner="sudo -E"' ``` diff --git a/examples/tc-egress/tc-egress-ebpf/.cargo/config.toml b/examples/tc-egress/tc-egress-ebpf/.cargo/config.toml deleted file mode 100644 index 4302a7f1..00000000 --- a/examples/tc-egress/tc-egress-ebpf/.cargo/config.toml +++ /dev/null @@ -1,6 +0,0 @@ -[build] -target-dir = "../target" -target = "bpfel-unknown-none" - -[unstable] -build-std = ["core"] diff --git a/examples/tc-egress/tc-egress-ebpf/Cargo.toml b/examples/tc-egress/tc-egress-ebpf/Cargo.toml index c3806ebf..b67e3d65 100644 --- a/examples/tc-egress/tc-egress-ebpf/Cargo.toml +++ b/examples/tc-egress/tc-egress-ebpf/Cargo.toml @@ -10,6 +10,9 @@ tc-egress-common = { path = "../tc-egress-common" } memoffset = "0.9" network-types = "0.0.7" +[build-dependencies] +which = { version = "6.0.0", default-features = false } + [[bin]] name = "tc-egress" path = "src/main.rs" diff --git a/examples/tc-egress/tc-egress-ebpf/build.rs b/examples/tc-egress/tc-egress-ebpf/build.rs new file mode 100644 index 00000000..f83c317a --- /dev/null +++ b/examples/tc-egress/tc-egress-ebpf/build.rs @@ -0,0 +1,17 @@ +use which::which; + +/// Building this crate has an undeclared dependency on the `bpf-linker` binary. This would be +/// better expressed by [artifact-dependencies][bindeps] but issues such as +/// https://github.com/rust-lang/cargo/issues/12385 make their use impractical for the time being. +/// +/// This file implements an imperfect solution: it causes cargo to rebuild the crate whenever the +/// mtime of `which bpf-linker` changes. Note that possibility that a new bpf-linker is added to +/// $PATH ahead of the one used as the cache key still exists. Solving this in the general case +/// would require rebuild-if-changed-env=PATH *and* rebuild-if-changed={every-directory-in-PATH} +/// which would likely mean far too much cache invalidation. +/// +/// [bindeps]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html?highlight=feature#artifact-dependencies +fn main() { + let bpf_linker = which("bpf-linker").unwrap(); + println!("cargo:rerun-if-changed={}", bpf_linker.to_str().unwrap()); +} diff --git a/examples/tc-egress/tc-egress/Cargo.toml b/examples/tc-egress/tc-egress/Cargo.toml index 8d06bbb7..d645f142 100644 --- a/examples/tc-egress/tc-egress/Cargo.toml +++ b/examples/tc-egress/tc-egress/Cargo.toml @@ -21,6 +21,23 @@ tokio = { version = "1.25", features = [ bytes = "1" env_logger = "0.11" +[build-dependencies] +aya-build = { git = "https://github.com/aya-rs/aya" } +anyhow = "1" +# TODO(https://github.com/rust-lang/cargo/issues/12375): this should be an artifact dependency, but +# it's not possible to tell cargo to use `-Z build-std` to build it. We cargo-in-cargo in the build +# script to build this, but we want to teach cargo about the dependecy so that cache invalidation +# works properly. +# +# Note also that https://github.com/rust-lang/cargo/issues/10593 occurs when `target = ...` is added +# to an artifact dependency; it seems possible to work around that by setting `resolver = "1"` in +# Cargo.toml in the workspace root. +# +# Finally note that *any* usage of `artifact = ...` in *any* Cargo.toml in the workspace breaks +# workflows with stable cargo; stable cargo outright refuses to load manifests that use unstable +# features. +tc-egress-ebpf = { path = "../tc-egress-ebpf" } + [[bin]] name = "tc-egress" path = "src/main.rs" diff --git a/examples/tc-egress/tc-egress/build.rs b/examples/tc-egress/tc-egress/build.rs new file mode 100644 index 00000000..f9b6054f --- /dev/null +++ b/examples/tc-egress/tc-egress/build.rs @@ -0,0 +1,15 @@ +use anyhow::{anyhow, Context as _}; +use aya_build::cargo_metadata; + +fn main() -> anyhow::Result<()> { + let cargo_metadata::Metadata { packages, .. } = + cargo_metadata::MetadataCommand::new() + .no_deps() + .exec() + .context("MetadataCommand::exec")?; + let ebpf_package = packages + .into_iter() + .find(|cargo_metadata::Package { name, .. }| name == "tc-egress-ebpf") + .ok_or_else(|| anyhow!("tc-egress-ebpf package not found"))?; + aya_build::build_ebpf([ebpf_package]) +} diff --git a/examples/tc-egress/tc-egress/src/main.rs b/examples/tc-egress/tc-egress/src/main.rs index 267c071e..ac1c4e33 100644 --- a/examples/tc-egress/tc-egress/src/main.rs +++ b/examples/tc-egress/tc-egress/src/main.rs @@ -1,10 +1,8 @@ use std::net::Ipv4Addr; use aya::{ - include_bytes_aligned, maps::HashMap, programs::{tc, SchedClassifier, TcAttachType}, - Ebpf, }; use aya_log::EbpfLogger; use clap::Parser; @@ -27,14 +25,10 @@ async fn main() -> Result<(), anyhow::Error> { // runtime. This approach is recommended for most real-world use cases. If you would // like to specify the eBPF program at runtime rather than at compile-time, you can // reach for `Ebpf::load_file` instead. - #[cfg(debug_assertions)] - let mut bpf = Ebpf::load(include_bytes_aligned!( - "../../target/bpfel-unknown-none/debug/tc-egress" - ))?; - #[cfg(not(debug_assertions))] - let mut bpf = Ebpf::load(include_bytes_aligned!( - "../../target/bpfel-unknown-none/release/tc-egress" - ))?; + let mut bpf = aya::Ebpf::load(aya::include_bytes_aligned!(concat!( + env!("OUT_DIR"), + "/tc-egress" + )))?; if let Err(e) = EbpfLogger::init(&mut bpf) { // This can happen if you remove all log statements from your eBPF program. warn!("failed to initialize eBPF logger: {}", e); diff --git a/examples/tc-egress/xtask/Cargo.toml b/examples/tc-egress/xtask/Cargo.toml deleted file mode 100644 index 9ea3688a..00000000 --- a/examples/tc-egress/xtask/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "xtask" -version = "0.1.0" -edition = "2021" - -[dependencies] -anyhow = "1" -clap = { version = "4.1", features = ["derive"] } -aya-tool = { git = "https://github.com/aya-rs/aya" } diff --git a/examples/tc-egress/xtask/src/build_ebpf.rs b/examples/tc-egress/xtask/src/build_ebpf.rs deleted file mode 100644 index 2f98b1d1..00000000 --- a/examples/tc-egress/xtask/src/build_ebpf.rs +++ /dev/null @@ -1,58 +0,0 @@ -use std::{path::PathBuf, process::Command}; - -use clap::Parser; - -#[derive(Debug, Copy, Clone)] -pub enum Architecture { - BpfEl, - BpfEb, -} - -impl std::str::FromStr for Architecture { - type Err = String; - - fn from_str(s: &str) -> Result { - Ok(match s { - "bpfel-unknown-none" => Architecture::BpfEl, - "bpfeb-unknown-none" => Architecture::BpfEb, - _ => return Err("invalid target".to_owned()), - }) - } -} - -impl std::fmt::Display for Architecture { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(match self { - Architecture::BpfEl => "bpfel-unknown-none", - Architecture::BpfEb => "bpfeb-unknown-none", - }) - } -} - -#[derive(Debug, Parser)] -pub struct Options { - /// Set the endianness of the BPF target - #[clap(default_value = "bpfel-unknown-none", long)] - pub target: Architecture, - /// Build the release target - #[clap(long)] - pub release: bool, -} - -pub fn build_ebpf(opts: Options) -> Result<(), anyhow::Error> { - let dir = PathBuf::from("tc-egress-ebpf"); - let target = format!("--target={}", opts.target); - let mut args = vec!["build", target.as_str(), "-Z", "build-std=core"]; - if opts.release { - args.push("--release") - } - - let status = Command::new("cargo") - .arg("+nightly") - .current_dir(&dir) - .args(&args) - .status() - .expect("failed to build bpf program"); - assert!(status.success()); - Ok(()) -} diff --git a/examples/tc-egress/xtask/src/main.rs b/examples/tc-egress/xtask/src/main.rs deleted file mode 100644 index c1c594e0..00000000 --- a/examples/tc-egress/xtask/src/main.rs +++ /dev/null @@ -1,33 +0,0 @@ -mod build_ebpf; -mod run; - -use std::process::exit; - -use clap::Parser; - -#[derive(Debug, Parser)] -pub struct Options { - #[clap(subcommand)] - command: Command, -} - -#[derive(Debug, Parser)] -enum Command { - BuildEbpf(build_ebpf::Options), - Run(run::Options), -} - -fn main() { - let opts = Options::parse(); - - use Command::*; - let ret = match opts.command { - BuildEbpf(opts) => build_ebpf::build_ebpf(opts), - Run(opts) => run::run(opts), - }; - - if let Err(e) = ret { - eprintln!("{e:#}"); - exit(1); - } -} diff --git a/examples/tc-egress/xtask/src/run.rs b/examples/tc-egress/xtask/src/run.rs deleted file mode 100644 index 26872e34..00000000 --- a/examples/tc-egress/xtask/src/run.rs +++ /dev/null @@ -1,71 +0,0 @@ -use std::process::Command; - -use anyhow::Context as _; -use clap::Parser; - -use crate::build_ebpf::{build_ebpf, Architecture, Options as BuildOptions}; - -#[derive(Debug, Parser)] -pub struct Options { - /// Set the endianness of the BPF target - #[clap(default_value = "bpfel-unknown-none", long)] - pub bpf_target: Architecture, - /// Build and run the release target - #[clap(long)] - pub release: bool, - /// The command used to wrap your application - #[clap(short, long, default_value = "sudo -E")] - pub runner: String, - /// Arguments to pass to your application - #[clap(name = "args", last = true)] - pub run_args: Vec, -} - -/// Build the project -fn build(opts: &Options) -> Result<(), anyhow::Error> { - let mut args = vec!["build"]; - if opts.release { - args.push("--release") - } - let status = Command::new("cargo") - .args(&args) - .status() - .expect("failed to build userspace"); - assert!(status.success()); - Ok(()) -} - -/// Build and run the project -pub fn run(opts: Options) -> Result<(), anyhow::Error> { - // build our ebpf program followed by our application - build_ebpf(BuildOptions { - target: opts.bpf_target, - release: opts.release, - }) - .context("Error while building eBPF program")?; - build(&opts).context("Error while building userspace application")?; - - // profile we are building (release or debug) - let profile = if opts.release { "release" } else { "debug" }; - let bin_path = format!("target/{profile}/tc-egress"); - - // arguments to pass to the application - let mut run_args: Vec<_> = - opts.run_args.iter().map(String::as_str).collect(); - - // configure args - let mut args: Vec<_> = opts.runner.trim().split_terminator(' ').collect(); - args.push(bin_path.as_str()); - args.append(&mut run_args); - - // run the command - let status = Command::new(args.first().expect("No first argument")) - .args(args.iter().skip(1)) - .status() - .expect("failed to run the command"); - - if !status.success() { - anyhow::bail!("Failed to run `{}`", args.join(" ")); - } - Ok(()) -} diff --git a/examples/test.sh b/examples/test.sh index 5e6ad592..21d0f014 100755 --- a/examples/test.sh +++ b/examples/test.sh @@ -10,7 +10,7 @@ for dir in *; do pushd "${dir}" cargo +nightly fmt --check - cargo xtask build-ebpf --release + cargo build cargo build --release bpf_crate=$dir-ebpf if [ "${dir}" == "aya-tool" ]; then @@ -22,8 +22,8 @@ for dir in *; do # # We can't use --all-targets on ${bpf_crate} because building tests with panic=abort isn't # supported without -Zpanic_abort_tests. - cargo clippy --release --exclude "${bpf_crate}" --all-targets --workspace -- --deny warnings - cargo clippy --release --package "${bpf_crate}" -- --deny warnings -C panic=abort + cargo clippy --exclude "${bpf_crate}" --all-targets --workspace -- --deny warnings + cargo clippy --package "${bpf_crate}" -- --deny warnings -C panic=abort popd done diff --git a/examples/xdp-drop/.cargo/config.toml b/examples/xdp-drop/.cargo/config.toml deleted file mode 100644 index 35049cbc..00000000 --- a/examples/xdp-drop/.cargo/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[alias] -xtask = "run --package xtask --" diff --git a/examples/xdp-drop/Cargo.toml b/examples/xdp-drop/Cargo.toml index 3bcc4715..7c730d42 100644 --- a/examples/xdp-drop/Cargo.toml +++ b/examples/xdp-drop/Cargo.toml @@ -1,9 +1,9 @@ [workspace] -members = ["xtask", "xdp-drop", "xdp-drop-common", "xdp-drop-ebpf"] +members = ["xdp-drop", "xdp-drop-common", "xdp-drop-ebpf"] resolver = "2" -default-members = ["xtask", "xdp-drop", "xdp-drop-common"] +default-members = ["xdp-drop", "xdp-drop-common"] [profile.release.package.xdp-drop-ebpf] diff --git a/examples/xdp-drop/README.md b/examples/xdp-drop/README.md index 80e02d8a..2c8bdcf0 100644 --- a/examples/xdp-drop/README.md +++ b/examples/xdp-drop/README.md @@ -6,23 +6,10 @@ 1. Install a rust nightly toolchain: `rustup install nightly` 1. Install bpf-linker: `cargo install bpf-linker` -## Build eBPF +## Build & Run -```console -cargo xtask build-ebpf -``` - -To perform a release build you can use the `--release` flag. -You may also change the target architecture with the `--target` flag - -## Build Userspace - -```console -cargo build -``` - -## Run +Use `cargo build`, `cargo check`, etc. as normal. Run your program with: -```console -cargo xtask run +```shell +RUST_LOG=info cargo run --config 'target."cfg(all())".runner="sudo -E"' ``` diff --git a/examples/xdp-drop/xdp-drop-ebpf/.cargo/config.toml b/examples/xdp-drop/xdp-drop-ebpf/.cargo/config.toml deleted file mode 100644 index 4302a7f1..00000000 --- a/examples/xdp-drop/xdp-drop-ebpf/.cargo/config.toml +++ /dev/null @@ -1,6 +0,0 @@ -[build] -target-dir = "../target" -target = "bpfel-unknown-none" - -[unstable] -build-std = ["core"] diff --git a/examples/xdp-drop/xdp-drop-ebpf/Cargo.toml b/examples/xdp-drop/xdp-drop-ebpf/Cargo.toml index dbb6696d..42ca9a59 100644 --- a/examples/xdp-drop/xdp-drop-ebpf/Cargo.toml +++ b/examples/xdp-drop/xdp-drop-ebpf/Cargo.toml @@ -9,6 +9,9 @@ aya-log-ebpf = { git = "https://github.com/aya-rs/aya" } xdp-drop-common = { path = "../xdp-drop-common" } network-types = "0.0.7" +[build-dependencies] +which = { version = "6.0.0", default-features = false } + [[bin]] name = "xdp-drop" path = "src/main.rs" diff --git a/examples/xdp-drop/xdp-drop-ebpf/build.rs b/examples/xdp-drop/xdp-drop-ebpf/build.rs new file mode 100644 index 00000000..f83c317a --- /dev/null +++ b/examples/xdp-drop/xdp-drop-ebpf/build.rs @@ -0,0 +1,17 @@ +use which::which; + +/// Building this crate has an undeclared dependency on the `bpf-linker` binary. This would be +/// better expressed by [artifact-dependencies][bindeps] but issues such as +/// https://github.com/rust-lang/cargo/issues/12385 make their use impractical for the time being. +/// +/// This file implements an imperfect solution: it causes cargo to rebuild the crate whenever the +/// mtime of `which bpf-linker` changes. Note that possibility that a new bpf-linker is added to +/// $PATH ahead of the one used as the cache key still exists. Solving this in the general case +/// would require rebuild-if-changed-env=PATH *and* rebuild-if-changed={every-directory-in-PATH} +/// which would likely mean far too much cache invalidation. +/// +/// [bindeps]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html?highlight=feature#artifact-dependencies +fn main() { + let bpf_linker = which("bpf-linker").unwrap(); + println!("cargo:rerun-if-changed={}", bpf_linker.to_str().unwrap()); +} diff --git a/examples/xdp-drop/xdp-drop/Cargo.toml b/examples/xdp-drop/xdp-drop/Cargo.toml index e77a5ebe..3f9f8398 100644 --- a/examples/xdp-drop/xdp-drop/Cargo.toml +++ b/examples/xdp-drop/xdp-drop/Cargo.toml @@ -21,6 +21,23 @@ tokio = { version = "1.25", features = [ bytes = "1" env_logger = "0.11" +[build-dependencies] +aya-build = { git = "https://github.com/aya-rs/aya" } +anyhow = "1" +# TODO(https://github.com/rust-lang/cargo/issues/12375): this should be an artifact dependency, but +# it's not possible to tell cargo to use `-Z build-std` to build it. We cargo-in-cargo in the build +# script to build this, but we want to teach cargo about the dependecy so that cache invalidation +# works properly. +# +# Note also that https://github.com/rust-lang/cargo/issues/10593 occurs when `target = ...` is added +# to an artifact dependency; it seems possible to work around that by setting `resolver = "1"` in +# Cargo.toml in the workspace root. +# +# Finally note that *any* usage of `artifact = ...` in *any* Cargo.toml in the workspace breaks +# workflows with stable cargo; stable cargo outright refuses to load manifests that use unstable +# features. +xdp-drop-ebpf = { path = "../xdp-drop-ebpf" } + [[bin]] name = "xdp-drop" path = "src/main.rs" diff --git a/examples/xdp-drop/xdp-drop/build.rs b/examples/xdp-drop/xdp-drop/build.rs new file mode 100644 index 00000000..17d7332e --- /dev/null +++ b/examples/xdp-drop/xdp-drop/build.rs @@ -0,0 +1,15 @@ +use anyhow::{anyhow, Context as _}; +use aya_build::cargo_metadata; + +fn main() -> anyhow::Result<()> { + let cargo_metadata::Metadata { packages, .. } = + cargo_metadata::MetadataCommand::new() + .no_deps() + .exec() + .context("MetadataCommand::exec")?; + let ebpf_package = packages + .into_iter() + .find(|cargo_metadata::Package { name, .. }| name == "xdp-drop-ebpf") + .ok_or_else(|| anyhow!("xdp-drop-ebpf package not found"))?; + aya_build::build_ebpf([ebpf_package]) +} diff --git a/examples/xdp-drop/xdp-drop/src/main.rs b/examples/xdp-drop/xdp-drop/src/main.rs index fee678f2..96a4c490 100644 --- a/examples/xdp-drop/xdp-drop/src/main.rs +++ b/examples/xdp-drop/xdp-drop/src/main.rs @@ -1,9 +1,7 @@ use anyhow::Context; use aya::{ - include_bytes_aligned, maps::HashMap, programs::{Xdp, XdpFlags}, - Ebpf, }; use aya_log::EbpfLogger; use clap::Parser; @@ -27,14 +25,10 @@ async fn main() -> Result<(), anyhow::Error> { // runtime. This approach is recommended for most real-world use cases. If you would // like to specify the eBPF program at runtime rather than at compile-time, you can // reach for `Ebpf::load_file` instead. - #[cfg(debug_assertions)] - let mut bpf = Ebpf::load(include_bytes_aligned!( - "../../target/bpfel-unknown-none/debug/xdp-drop" - ))?; - #[cfg(not(debug_assertions))] - let mut bpf = Ebpf::load(include_bytes_aligned!( - "../../target/bpfel-unknown-none/release/xdp-drop" - ))?; + let mut bpf = aya::Ebpf::load(aya::include_bytes_aligned!(concat!( + env!("OUT_DIR"), + "/xdp-drop" + )))?; if let Err(e) = EbpfLogger::init(&mut bpf) { // This can happen if you remove all log statements from your eBPF program. warn!("failed to initialize eBPF logger: {}", e); diff --git a/examples/xdp-drop/xtask/Cargo.toml b/examples/xdp-drop/xtask/Cargo.toml deleted file mode 100644 index 9ed32318..00000000 --- a/examples/xdp-drop/xtask/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "xtask" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[dependencies] -anyhow = "1" -clap = { version = "4.1", features = ["derive"] } -aya-tool = { git = "https://github.com/aya-rs/aya" } diff --git a/examples/xdp-drop/xtask/src/build_ebpf.rs b/examples/xdp-drop/xtask/src/build_ebpf.rs deleted file mode 100644 index 9f345820..00000000 --- a/examples/xdp-drop/xtask/src/build_ebpf.rs +++ /dev/null @@ -1,58 +0,0 @@ -use std::{path::PathBuf, process::Command}; - -use clap::Parser; - -#[derive(Debug, Copy, Clone)] -pub enum Architecture { - BpfEl, - BpfEb, -} - -impl std::str::FromStr for Architecture { - type Err = String; - - fn from_str(s: &str) -> Result { - Ok(match s { - "bpfel-unknown-none" => Architecture::BpfEl, - "bpfeb-unknown-none" => Architecture::BpfEb, - _ => return Err("invalid target".to_owned()), - }) - } -} - -impl std::fmt::Display for Architecture { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(match self { - Architecture::BpfEl => "bpfel-unknown-none", - Architecture::BpfEb => "bpfeb-unknown-none", - }) - } -} - -#[derive(Debug, Parser)] -pub struct Options { - /// Set the endianness of the BPF target - #[clap(default_value = "bpfel-unknown-none", long)] - pub target: Architecture, - /// Build the release target - #[clap(long)] - pub release: bool, -} - -pub fn build_ebpf(opts: Options) -> Result<(), anyhow::Error> { - let dir = PathBuf::from("xdp-drop-ebpf"); - let target = format!("--target={}", opts.target); - let mut args = vec!["build", target.as_str(), "-Z", "build-std=core"]; - if opts.release { - args.push("--release") - } - - let status = Command::new("cargo") - .arg("+nightly") - .current_dir(&dir) - .args(&args) - .status() - .expect("failed to build bpf program"); - assert!(status.success()); - Ok(()) -} diff --git a/examples/xdp-drop/xtask/src/main.rs b/examples/xdp-drop/xtask/src/main.rs deleted file mode 100644 index c1c594e0..00000000 --- a/examples/xdp-drop/xtask/src/main.rs +++ /dev/null @@ -1,33 +0,0 @@ -mod build_ebpf; -mod run; - -use std::process::exit; - -use clap::Parser; - -#[derive(Debug, Parser)] -pub struct Options { - #[clap(subcommand)] - command: Command, -} - -#[derive(Debug, Parser)] -enum Command { - BuildEbpf(build_ebpf::Options), - Run(run::Options), -} - -fn main() { - let opts = Options::parse(); - - use Command::*; - let ret = match opts.command { - BuildEbpf(opts) => build_ebpf::build_ebpf(opts), - Run(opts) => run::run(opts), - }; - - if let Err(e) = ret { - eprintln!("{e:#}"); - exit(1); - } -} diff --git a/examples/xdp-drop/xtask/src/run.rs b/examples/xdp-drop/xtask/src/run.rs deleted file mode 100644 index 33af0af0..00000000 --- a/examples/xdp-drop/xtask/src/run.rs +++ /dev/null @@ -1,71 +0,0 @@ -use std::process::Command; - -use anyhow::Context as _; -use clap::Parser; - -use crate::build_ebpf::{build_ebpf, Architecture, Options as BuildOptions}; - -#[derive(Debug, Parser)] -pub struct Options { - /// Set the endianness of the BPF target - #[clap(default_value = "bpfel-unknown-none", long)] - pub bpf_target: Architecture, - /// Build and run the release target - #[clap(long)] - pub release: bool, - /// The command used to wrap your application - #[clap(short, long, default_value = "sudo -E")] - pub runner: String, - /// Arguments to pass to your application - #[clap(name = "args", last = true)] - pub run_args: Vec, -} - -/// Build the project -fn build(opts: &Options) -> Result<(), anyhow::Error> { - let mut args = vec!["build"]; - if opts.release { - args.push("--release") - } - let status = Command::new("cargo") - .args(&args) - .status() - .expect("failed to build userspace"); - assert!(status.success()); - Ok(()) -} - -/// Build and run the project -pub fn run(opts: Options) -> Result<(), anyhow::Error> { - // build our ebpf program followed by our application - build_ebpf(BuildOptions { - target: opts.bpf_target, - release: opts.release, - }) - .context("Error while building eBPF program")?; - build(&opts).context("Error while building userspace application")?; - - // profile we are building (release or debug) - let profile = if opts.release { "release" } else { "debug" }; - let bin_path = format!("target/{profile}/xdp-drop"); - - // arguments to pass to the application - let mut run_args: Vec<_> = - opts.run_args.iter().map(String::as_str).collect(); - - // configure args - let mut args: Vec<_> = opts.runner.trim().split_terminator(' ').collect(); - args.push(bin_path.as_str()); - args.append(&mut run_args); - - // run the command - let status = Command::new(args.first().expect("No first argument")) - .args(args.iter().skip(1)) - .status() - .expect("failed to run the command"); - - if !status.success() { - anyhow::bail!("Failed to run `{}`", args.join(" ")); - } - Ok(()) -} diff --git a/examples/xdp-hello/.cargo/config.toml b/examples/xdp-hello/.cargo/config.toml deleted file mode 100644 index 35049cbc..00000000 --- a/examples/xdp-hello/.cargo/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[alias] -xtask = "run --package xtask --" diff --git a/examples/xdp-hello/Cargo.toml b/examples/xdp-hello/Cargo.toml index 2697aafe..898da36f 100644 --- a/examples/xdp-hello/Cargo.toml +++ b/examples/xdp-hello/Cargo.toml @@ -1,9 +1,9 @@ [workspace] -members = ["xtask", "xdp-hello", "xdp-hello-common", "xdp-hello-ebpf"] +members = ["xdp-hello", "xdp-hello-common", "xdp-hello-ebpf"] resolver = "2" -default-members = ["xtask", "xdp-hello", "xdp-hello-common"] +default-members = ["xdp-hello", "xdp-hello-common"] [profile.release.package.xdp-hello-ebpf] debug = 2 diff --git a/examples/xdp-hello/README.md b/examples/xdp-hello/README.md index 3d347486..ffef4b3f 100644 --- a/examples/xdp-hello/README.md +++ b/examples/xdp-hello/README.md @@ -6,23 +6,10 @@ 1. Install a rust nightly toolchain: `rustup install nightly` 1. Install bpf-linker: `cargo install bpf-linker` -## Build eBPF +## Build & Run -```console -cargo xtask build-ebpf -``` - -To perform a release build you can use the `--release` flag. -You may also change the target architecture with the `--target` flag - -## Build Userspace - -```console -cargo build -``` - -## Run +Use `cargo build`, `cargo check`, etc. as normal. Run your program with: -```console -cargo xtask run +```shell +RUST_LOG=info cargo run --config 'target."cfg(all())".runner="sudo -E"' ``` diff --git a/examples/xdp-hello/xdp-hello-ebpf/.cargo/config.toml b/examples/xdp-hello/xdp-hello-ebpf/.cargo/config.toml deleted file mode 100644 index 4302a7f1..00000000 --- a/examples/xdp-hello/xdp-hello-ebpf/.cargo/config.toml +++ /dev/null @@ -1,6 +0,0 @@ -[build] -target-dir = "../target" -target = "bpfel-unknown-none" - -[unstable] -build-std = ["core"] diff --git a/examples/xdp-hello/xdp-hello-ebpf/Cargo.toml b/examples/xdp-hello/xdp-hello-ebpf/Cargo.toml index 75f2d66d..7ac40736 100644 --- a/examples/xdp-hello/xdp-hello-ebpf/Cargo.toml +++ b/examples/xdp-hello/xdp-hello-ebpf/Cargo.toml @@ -8,6 +8,9 @@ aya-ebpf = { git = "https://github.com/aya-rs/aya" } aya-log-ebpf = { git = "https://github.com/aya-rs/aya" } xdp-hello-common = { path = "../xdp-hello-common" } +[build-dependencies] +which = { version = "6.0.0", default-features = false } + [[bin]] name = "xdp-hello" path = "src/main.rs" diff --git a/examples/xdp-hello/xdp-hello-ebpf/build.rs b/examples/xdp-hello/xdp-hello-ebpf/build.rs new file mode 100644 index 00000000..f83c317a --- /dev/null +++ b/examples/xdp-hello/xdp-hello-ebpf/build.rs @@ -0,0 +1,17 @@ +use which::which; + +/// Building this crate has an undeclared dependency on the `bpf-linker` binary. This would be +/// better expressed by [artifact-dependencies][bindeps] but issues such as +/// https://github.com/rust-lang/cargo/issues/12385 make their use impractical for the time being. +/// +/// This file implements an imperfect solution: it causes cargo to rebuild the crate whenever the +/// mtime of `which bpf-linker` changes. Note that possibility that a new bpf-linker is added to +/// $PATH ahead of the one used as the cache key still exists. Solving this in the general case +/// would require rebuild-if-changed-env=PATH *and* rebuild-if-changed={every-directory-in-PATH} +/// which would likely mean far too much cache invalidation. +/// +/// [bindeps]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html?highlight=feature#artifact-dependencies +fn main() { + let bpf_linker = which("bpf-linker").unwrap(); + println!("cargo:rerun-if-changed={}", bpf_linker.to_str().unwrap()); +} diff --git a/examples/xdp-hello/xdp-hello/Cargo.toml b/examples/xdp-hello/xdp-hello/Cargo.toml index 98a236da..dc14dbb2 100644 --- a/examples/xdp-hello/xdp-hello/Cargo.toml +++ b/examples/xdp-hello/xdp-hello/Cargo.toml @@ -20,6 +20,23 @@ tokio = { version = "1.25", features = [ ] } env_logger = "0.11" +[build-dependencies] +aya-build = { git = "https://github.com/aya-rs/aya" } +anyhow = "1" +# TODO(https://github.com/rust-lang/cargo/issues/12375): this should be an artifact dependency, but +# it's not possible to tell cargo to use `-Z build-std` to build it. We cargo-in-cargo in the build +# script to build this, but we want to teach cargo about the dependecy so that cache invalidation +# works properly. +# +# Note also that https://github.com/rust-lang/cargo/issues/10593 occurs when `target = ...` is added +# to an artifact dependency; it seems possible to work around that by setting `resolver = "1"` in +# Cargo.toml in the workspace root. +# +# Finally note that *any* usage of `artifact = ...` in *any* Cargo.toml in the workspace breaks +# workflows with stable cargo; stable cargo outright refuses to load manifests that use unstable +# features. +xdp-hello-ebpf = { path = "../xdp-hello-ebpf" } + [[bin]] name = "xdp-hello" path = "src/main.rs" diff --git a/examples/xdp-hello/xdp-hello/build.rs b/examples/xdp-hello/xdp-hello/build.rs new file mode 100644 index 00000000..7547dff8 --- /dev/null +++ b/examples/xdp-hello/xdp-hello/build.rs @@ -0,0 +1,15 @@ +use anyhow::{anyhow, Context as _}; +use aya_build::cargo_metadata; + +fn main() -> anyhow::Result<()> { + let cargo_metadata::Metadata { packages, .. } = + cargo_metadata::MetadataCommand::new() + .no_deps() + .exec() + .context("MetadataCommand::exec")?; + let ebpf_package = packages + .into_iter() + .find(|cargo_metadata::Package { name, .. }| name == "xdp-hello-ebpf") + .ok_or_else(|| anyhow!("xdp-hello-ebpf package not found"))?; + aya_build::build_ebpf([ebpf_package]) +} diff --git a/examples/xdp-hello/xdp-hello/src/main.rs b/examples/xdp-hello/xdp-hello/src/main.rs index 92dc5e59..21d7afa6 100644 --- a/examples/xdp-hello/xdp-hello/src/main.rs +++ b/examples/xdp-hello/xdp-hello/src/main.rs @@ -1,9 +1,5 @@ use anyhow::Context; -use aya::{ - include_bytes_aligned, - programs::{Xdp, XdpFlags}, - Ebpf, -}; +use aya::programs::{Xdp, XdpFlags}; use aya_log::EbpfLogger; use clap::Parser; use log::info; @@ -27,14 +23,10 @@ async fn main() -> Result<(), anyhow::Error> { // reach for `Ebpf::load_file` instead. // (4) // (5) - #[cfg(debug_assertions)] - let mut bpf = Ebpf::load(include_bytes_aligned!( - "../../target/bpfel-unknown-none/debug/xdp-hello" - ))?; - #[cfg(not(debug_assertions))] - let mut bpf = Ebpf::load(include_bytes_aligned!( - "../../target/bpfel-unknown-none/release/xdp-hello" - ))?; + let mut bpf = aya::Ebpf::load(aya::include_bytes_aligned!(concat!( + env!("OUT_DIR"), + "/xdp-hello" + )))?; EbpfLogger::init(&mut bpf)?; // (6) let program: &mut Xdp = bpf.program_mut("xdp_hello").unwrap().try_into()?; diff --git a/examples/xdp-hello/xtask/Cargo.toml b/examples/xdp-hello/xtask/Cargo.toml deleted file mode 100644 index c4dea5d1..00000000 --- a/examples/xdp-hello/xtask/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "xtask" -version = "0.1.0" -edition = "2021" - -[dependencies] -anyhow = "1" -clap = { version = "4.1", features = ["derive"] } diff --git a/examples/xdp-hello/xtask/src/build_ebpf.rs b/examples/xdp-hello/xtask/src/build_ebpf.rs deleted file mode 100644 index fe1a69bb..00000000 --- a/examples/xdp-hello/xtask/src/build_ebpf.rs +++ /dev/null @@ -1,58 +0,0 @@ -use std::{path::PathBuf, process::Command}; - -use clap::Parser; - -#[derive(Debug, Copy, Clone)] -pub enum Architecture { - BpfEl, - BpfEb, -} - -impl std::str::FromStr for Architecture { - type Err = String; - - fn from_str(s: &str) -> Result { - Ok(match s { - "bpfel-unknown-none" => Architecture::BpfEl, - "bpfeb-unknown-none" => Architecture::BpfEb, - _ => return Err("invalid target".to_owned()), - }) - } -} - -impl std::fmt::Display for Architecture { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(match self { - Architecture::BpfEl => "bpfel-unknown-none", - Architecture::BpfEb => "bpfeb-unknown-none", - }) - } -} - -#[derive(Debug, Parser)] -pub struct Options { - /// Set the endianness of the BPF target - #[clap(default_value = "bpfel-unknown-none", long)] - pub target: Architecture, - /// Build the release target - #[clap(long)] - pub release: bool, -} - -pub fn build_ebpf(opts: Options) -> Result<(), anyhow::Error> { - let dir = PathBuf::from("xdp-hello-ebpf"); - let target = format!("--target={}", opts.target); - let mut args = vec!["build", target.as_str(), "-Z", "build-std=core"]; - if opts.release { - args.push("--release") - } - - let status = Command::new("cargo") - .arg("+nightly") - .current_dir(&dir) - .args(&args) - .status() - .expect("failed to build bpf program"); - assert!(status.success()); - Ok(()) -} diff --git a/examples/xdp-hello/xtask/src/main.rs b/examples/xdp-hello/xtask/src/main.rs deleted file mode 100644 index c1c594e0..00000000 --- a/examples/xdp-hello/xtask/src/main.rs +++ /dev/null @@ -1,33 +0,0 @@ -mod build_ebpf; -mod run; - -use std::process::exit; - -use clap::Parser; - -#[derive(Debug, Parser)] -pub struct Options { - #[clap(subcommand)] - command: Command, -} - -#[derive(Debug, Parser)] -enum Command { - BuildEbpf(build_ebpf::Options), - Run(run::Options), -} - -fn main() { - let opts = Options::parse(); - - use Command::*; - let ret = match opts.command { - BuildEbpf(opts) => build_ebpf::build_ebpf(opts), - Run(opts) => run::run(opts), - }; - - if let Err(e) = ret { - eprintln!("{e:#}"); - exit(1); - } -} diff --git a/examples/xdp-hello/xtask/src/run.rs b/examples/xdp-hello/xtask/src/run.rs deleted file mode 100644 index 459a1cbf..00000000 --- a/examples/xdp-hello/xtask/src/run.rs +++ /dev/null @@ -1,71 +0,0 @@ -use std::process::Command; - -use anyhow::Context as _; -use clap::Parser; - -use crate::build_ebpf::{build_ebpf, Architecture, Options as BuildOptions}; - -#[derive(Debug, Parser)] -pub struct Options { - /// Set the endianness of the BPF target - #[clap(default_value = "bpfel-unknown-none", long)] - pub bpf_target: Architecture, - /// Build and run the release target - #[clap(long)] - pub release: bool, - /// The command used to wrap your application - #[clap(short, long, default_value = "sudo -E")] - pub runner: String, - /// Arguments to pass to your application - #[clap(name = "args", last = true)] - pub run_args: Vec, -} - -/// Build the project -fn build(opts: &Options) -> Result<(), anyhow::Error> { - let mut args = vec!["build"]; - if opts.release { - args.push("--release") - } - let status = Command::new("cargo") - .args(&args) - .status() - .expect("failed to build userspace"); - assert!(status.success()); - Ok(()) -} - -/// Build and run the project -pub fn run(opts: Options) -> Result<(), anyhow::Error> { - // build our ebpf program followed by our application - build_ebpf(BuildOptions { - target: opts.bpf_target, - release: opts.release, - }) - .context("Error while building eBPF program")?; - build(&opts).context("Error while building userspace application")?; - - // profile we are building (release or debug) - let profile = if opts.release { "release" } else { "debug" }; - let bin_path = format!("target/{profile}/xdp-hello"); - - // arguments to pass to the application - let mut run_args: Vec<_> = - opts.run_args.iter().map(String::as_str).collect(); - - // configure args - let mut args: Vec<_> = opts.runner.trim().split_terminator(' ').collect(); - args.push(bin_path.as_str()); - args.append(&mut run_args); - - // run the command - let status = Command::new(args.first().expect("No first argument")) - .args(args.iter().skip(1)) - .status() - .expect("failed to run the command"); - - if !status.success() { - anyhow::bail!("Failed to run `{}`", args.join(" ")); - } - Ok(()) -} diff --git a/examples/xdp-log/.cargo/config.toml b/examples/xdp-log/.cargo/config.toml deleted file mode 100644 index 35049cbc..00000000 --- a/examples/xdp-log/.cargo/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[alias] -xtask = "run --package xtask --" diff --git a/examples/xdp-log/Cargo.toml b/examples/xdp-log/Cargo.toml index cd237798..b23fca7d 100644 --- a/examples/xdp-log/Cargo.toml +++ b/examples/xdp-log/Cargo.toml @@ -1,9 +1,9 @@ [workspace] -members = ["xtask", "xdp-log", "xdp-log-common", "xdp-log-ebpf"] +members = ["xdp-log", "xdp-log-common", "xdp-log-ebpf"] resolver = "2" -default-members = ["xtask", "xdp-log", "xdp-log-common"] +default-members = ["xdp-log", "xdp-log-common"] [profile.release.package.xdp-log-ebpf] debug = 2 diff --git a/examples/xdp-log/README.md b/examples/xdp-log/README.md index c3a865d6..ecc2529b 100644 --- a/examples/xdp-log/README.md +++ b/examples/xdp-log/README.md @@ -6,23 +6,10 @@ 1. Install a rust nightly toolchain: `rustup install nightly` 1. Install bpf-linker: `cargo install bpf-linker` -## Build eBPF +## Build & Run -```console -cargo xtask build-ebpf -``` - -To perform a release build you can use the `--release` flag. -You may also change the target architecture with the `--target` flag - -## Build Userspace - -```console -cargo build -``` - -## Run +Use `cargo build`, `cargo check`, etc. as normal. Run your program with: -```console -cargo xtask run +```shell +RUST_LOG=info cargo run --config 'target."cfg(all())".runner="sudo -E"' ``` diff --git a/examples/xdp-log/xdp-log-ebpf/.cargo/config.toml b/examples/xdp-log/xdp-log-ebpf/.cargo/config.toml deleted file mode 100644 index 4302a7f1..00000000 --- a/examples/xdp-log/xdp-log-ebpf/.cargo/config.toml +++ /dev/null @@ -1,6 +0,0 @@ -[build] -target-dir = "../target" -target = "bpfel-unknown-none" - -[unstable] -build-std = ["core"] diff --git a/examples/xdp-log/xdp-log-ebpf/Cargo.toml b/examples/xdp-log/xdp-log-ebpf/Cargo.toml index fca36a36..afc0dad9 100644 --- a/examples/xdp-log/xdp-log-ebpf/Cargo.toml +++ b/examples/xdp-log/xdp-log-ebpf/Cargo.toml @@ -9,6 +9,9 @@ aya-log-ebpf = { git = "https://github.com/aya-rs/aya" } xdp-log-common = { path = "../xdp-log-common" } network-types = "0.0.7" +[build-dependencies] +which = { version = "6.0.0", default-features = false } + [[bin]] name = "xdp-log" path = "src/main.rs" diff --git a/examples/xdp-log/xdp-log-ebpf/build.rs b/examples/xdp-log/xdp-log-ebpf/build.rs new file mode 100644 index 00000000..f83c317a --- /dev/null +++ b/examples/xdp-log/xdp-log-ebpf/build.rs @@ -0,0 +1,17 @@ +use which::which; + +/// Building this crate has an undeclared dependency on the `bpf-linker` binary. This would be +/// better expressed by [artifact-dependencies][bindeps] but issues such as +/// https://github.com/rust-lang/cargo/issues/12385 make their use impractical for the time being. +/// +/// This file implements an imperfect solution: it causes cargo to rebuild the crate whenever the +/// mtime of `which bpf-linker` changes. Note that possibility that a new bpf-linker is added to +/// $PATH ahead of the one used as the cache key still exists. Solving this in the general case +/// would require rebuild-if-changed-env=PATH *and* rebuild-if-changed={every-directory-in-PATH} +/// which would likely mean far too much cache invalidation. +/// +/// [bindeps]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html?highlight=feature#artifact-dependencies +fn main() { + let bpf_linker = which("bpf-linker").unwrap(); + println!("cargo:rerun-if-changed={}", bpf_linker.to_str().unwrap()); +} diff --git a/examples/xdp-log/xdp-log/Cargo.toml b/examples/xdp-log/xdp-log/Cargo.toml index 2db09569..1e06939e 100644 --- a/examples/xdp-log/xdp-log/Cargo.toml +++ b/examples/xdp-log/xdp-log/Cargo.toml @@ -21,6 +21,23 @@ tokio = { version = "1.25", features = [ bytes = "1" env_logger = "0.11" +[build-dependencies] +aya-build = { git = "https://github.com/aya-rs/aya" } +anyhow = "1" +# TODO(https://github.com/rust-lang/cargo/issues/12375): this should be an artifact dependency, but +# it's not possible to tell cargo to use `-Z build-std` to build it. We cargo-in-cargo in the build +# script to build this, but we want to teach cargo about the dependecy so that cache invalidation +# works properly. +# +# Note also that https://github.com/rust-lang/cargo/issues/10593 occurs when `target = ...` is added +# to an artifact dependency; it seems possible to work around that by setting `resolver = "1"` in +# Cargo.toml in the workspace root. +# +# Finally note that *any* usage of `artifact = ...` in *any* Cargo.toml in the workspace breaks +# workflows with stable cargo; stable cargo outright refuses to load manifests that use unstable +# features. +xdp-log-ebpf = { path = "../xdp-log-ebpf" } + [[bin]] name = "xdp-log" path = "src/main.rs" diff --git a/examples/xdp-log/xdp-log/build.rs b/examples/xdp-log/xdp-log/build.rs new file mode 100644 index 00000000..d2145a9e --- /dev/null +++ b/examples/xdp-log/xdp-log/build.rs @@ -0,0 +1,15 @@ +use anyhow::{anyhow, Context as _}; +use aya_build::cargo_metadata; + +fn main() -> anyhow::Result<()> { + let cargo_metadata::Metadata { packages, .. } = + cargo_metadata::MetadataCommand::new() + .no_deps() + .exec() + .context("MetadataCommand::exec")?; + let ebpf_package = packages + .into_iter() + .find(|cargo_metadata::Package { name, .. }| name == "xdp-log-ebpf") + .ok_or_else(|| anyhow!("xdp-log-ebpf package not found"))?; + aya_build::build_ebpf([ebpf_package]) +} diff --git a/examples/xdp-log/xdp-log/src/main.rs b/examples/xdp-log/xdp-log/src/main.rs index 071bbe17..9c5ffd7f 100644 --- a/examples/xdp-log/xdp-log/src/main.rs +++ b/examples/xdp-log/xdp-log/src/main.rs @@ -1,9 +1,5 @@ use anyhow::Context; -use aya::{ - include_bytes_aligned, - programs::{Xdp, XdpFlags}, - Ebpf, -}; +use aya::programs::{Xdp, XdpFlags}; use aya_log::EbpfLogger; use clap::Parser; use log::{info, warn}; @@ -25,14 +21,10 @@ async fn main() -> Result<(), anyhow::Error> { // runtime. This approach is recommended for most real-world use cases. If you would // like to specify the eBPF program at runtime rather than at compile-time, you can // reach for `Ebpf::load_file` instead. - #[cfg(debug_assertions)] - let mut bpf = Ebpf::load(include_bytes_aligned!( - "../../target/bpfel-unknown-none/debug/xdp-log" - ))?; - #[cfg(not(debug_assertions))] - let mut bpf = Ebpf::load(include_bytes_aligned!( - "../../target/bpfel-unknown-none/release/xdp-log" - ))?; + let mut bpf = aya::Ebpf::load(aya::include_bytes_aligned!(concat!( + env!("OUT_DIR"), + "/xdp-log" + )))?; if let Err(e) = EbpfLogger::init(&mut bpf) { // This can happen if you remove all log statements from your eBPF program. warn!("failed to initialize eBPF logger: {}", e); diff --git a/examples/xdp-log/xtask/Cargo.toml b/examples/xdp-log/xtask/Cargo.toml deleted file mode 100644 index 9ed32318..00000000 --- a/examples/xdp-log/xtask/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "xtask" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[dependencies] -anyhow = "1" -clap = { version = "4.1", features = ["derive"] } -aya-tool = { git = "https://github.com/aya-rs/aya" } diff --git a/examples/xdp-log/xtask/src/build_ebpf.rs b/examples/xdp-log/xtask/src/build_ebpf.rs deleted file mode 100644 index 09beefc6..00000000 --- a/examples/xdp-log/xtask/src/build_ebpf.rs +++ /dev/null @@ -1,58 +0,0 @@ -use std::{path::PathBuf, process::Command}; - -use clap::Parser; - -#[derive(Debug, Copy, Clone)] -pub enum Architecture { - BpfEl, - BpfEb, -} - -impl std::str::FromStr for Architecture { - type Err = String; - - fn from_str(s: &str) -> Result { - Ok(match s { - "bpfel-unknown-none" => Architecture::BpfEl, - "bpfeb-unknown-none" => Architecture::BpfEb, - _ => return Err("invalid target".to_owned()), - }) - } -} - -impl std::fmt::Display for Architecture { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(match self { - Architecture::BpfEl => "bpfel-unknown-none", - Architecture::BpfEb => "bpfeb-unknown-none", - }) - } -} - -#[derive(Debug, Parser)] -pub struct Options { - /// Set the endianness of the BPF target - #[clap(default_value = "bpfel-unknown-none", long)] - pub target: Architecture, - /// Build the release target - #[clap(long)] - pub release: bool, -} - -pub fn build_ebpf(opts: Options) -> Result<(), anyhow::Error> { - let dir = PathBuf::from("xdp-log-ebpf"); - let target = format!("--target={}", opts.target); - let mut args = vec!["build", target.as_str(), "-Z", "build-std=core"]; - if opts.release { - args.push("--release") - } - - let status = Command::new("cargo") - .arg("+nightly") - .current_dir(&dir) - .args(&args) - .status() - .expect("failed to build bpf program"); - assert!(status.success()); - Ok(()) -} diff --git a/examples/xdp-log/xtask/src/main.rs b/examples/xdp-log/xtask/src/main.rs deleted file mode 100644 index c1c594e0..00000000 --- a/examples/xdp-log/xtask/src/main.rs +++ /dev/null @@ -1,33 +0,0 @@ -mod build_ebpf; -mod run; - -use std::process::exit; - -use clap::Parser; - -#[derive(Debug, Parser)] -pub struct Options { - #[clap(subcommand)] - command: Command, -} - -#[derive(Debug, Parser)] -enum Command { - BuildEbpf(build_ebpf::Options), - Run(run::Options), -} - -fn main() { - let opts = Options::parse(); - - use Command::*; - let ret = match opts.command { - BuildEbpf(opts) => build_ebpf::build_ebpf(opts), - Run(opts) => run::run(opts), - }; - - if let Err(e) = ret { - eprintln!("{e:#}"); - exit(1); - } -} diff --git a/examples/xdp-log/xtask/src/run.rs b/examples/xdp-log/xtask/src/run.rs deleted file mode 100644 index d7021fc6..00000000 --- a/examples/xdp-log/xtask/src/run.rs +++ /dev/null @@ -1,71 +0,0 @@ -use std::process::Command; - -use anyhow::Context as _; -use clap::Parser; - -use crate::build_ebpf::{build_ebpf, Architecture, Options as BuildOptions}; - -#[derive(Debug, Parser)] -pub struct Options { - /// Set the endianness of the BPF target - #[clap(default_value = "bpfel-unknown-none", long)] - pub bpf_target: Architecture, - /// Build and run the release target - #[clap(long)] - pub release: bool, - /// The command used to wrap your application - #[clap(short, long, default_value = "sudo -E")] - pub runner: String, - /// Arguments to pass to your application - #[clap(name = "args", last = true)] - pub run_args: Vec, -} - -/// Build the project -fn build(opts: &Options) -> Result<(), anyhow::Error> { - let mut args = vec!["build"]; - if opts.release { - args.push("--release") - } - let status = Command::new("cargo") - .args(&args) - .status() - .expect("failed to build userspace"); - assert!(status.success()); - Ok(()) -} - -/// Build and run the project -pub fn run(opts: Options) -> Result<(), anyhow::Error> { - // build our ebpf program followed by our application - build_ebpf(BuildOptions { - target: opts.bpf_target, - release: opts.release, - }) - .context("Error while building eBPF program")?; - build(&opts).context("Error while building userspace application")?; - - // profile we are building (release or debug) - let profile = if opts.release { "release" } else { "debug" }; - let bin_path = format!("target/{}/xdp-log", profile); - - // arguments to pass to the application - let mut run_args: Vec<_> = - opts.run_args.iter().map(String::as_str).collect(); - - // configure args - let mut args: Vec<_> = opts.runner.trim().split_terminator(' ').collect(); - args.push(bin_path.as_str()); - args.append(&mut run_args); - - // run the command - let status = Command::new(args.first().expect("No first argument")) - .args(args.iter().skip(1)) - .status() - .expect("failed to run the command"); - - if !status.success() { - anyhow::bail!("Failed to run `{}`", args.join(" ")); - } - Ok(()) -}