diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..8392d159 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..e968eee9 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,144 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Aya is a pure-Rust eBPF library built without dependencies on libbpf or bcc. It provides a complete eBPF development stack with both userspace and kernel-space components, supporting BTF (BPF Type Format) for portable "compile once, run everywhere" eBPF programs. + +## Key Components + +### Crate Structure +- **aya**: Main userspace library for loading and managing eBPF programs +- **aya-obj**: BPF object file parsing and manipulation +- **aya-build**: Build-time utilities for eBPF program compilation +- **aya-log**: Logging infrastructure for eBPF programs +- **aya-tool**: Command-line tools for eBPF development +- **aya-ebpf**: Kernel-space eBPF program development library (no_std) +- **aya-ebpf-bindings**: Low-level kernel bindings for eBPF programs +- **test-distro**: Testing infrastructure for different kernel versions + +### Program Types +The library supports all major eBPF program types: +- **Probes**: KProbe, UProbe, TracePoint, RawTracePoint, BtfTracePoint +- **Network**: XDP, TC (traffic control), SocketFilter, SkMsg, SkSkb, SockOps +- **Cgroup**: CgroupSkb, CgroupSock, CgroupSockAddr, CgroupSockopt, CgroupSysctl, CgroupDevice +- **Security**: LSM (Linux Security Module), FEntry, FExit +- **Specialized**: PerfEvent, LircMode2, FlowDissector, SkLookup, Extension, Iter + +### Map Types +Comprehensive map support including: +- Basic: Array, HashMap, LruHashMap, PerCpuArray, PerCpuHashMap +- Advanced: RingBuf, PerfEventArray, BloomFilter, LpmTrie, Stack, Queue +- Specialized: SockMap, SockHash, CpuMap, DevMap, XskMap, ProgramArray + +## Common Development Commands + +### Building +```bash +# Build all workspace members +cargo build + +# Build specific crate +cargo build -p aya +``` + +### Testing +```bash +# Run unit tests +cargo test + +# Run integration tests (requires special setup) +cargo xtask integration-test local + +# Run virtualized integration tests +cargo xtask integration-test vm +``` + +### Linting and Formatting +```bash +# Format code +cargo +nightly fmt --all + +# Run clippy with project-specific configuration +./clippy.sh + +# Run clippy with arguments +./clippy.sh --fix +``` + +### eBPF-specific Commands +```bash +# Generate code from kernel headers +cargo xtask codegen + +# Check public API compatibility +cargo xtask public-api + +# Build documentation +cargo xtask docs +``` + +### Architecture-specific Building +```bash +# Build eBPF programs for specific target +cargo +nightly build --target bpfel-unknown-none -Z build-std=core + +# Build for specific BPF architecture +CARGO_CFG_BPF_TARGET_ARCH=x86_64 cargo +nightly build --target bpfel-unknown-none +``` + +## Key Architecture Patterns + +### EbpfLoader Pattern +The main loading mechanism uses a builder pattern: +```rust +let mut bpf = EbpfLoader::new() + .btf(Btf::from_sys_fs().ok().as_ref()) + .map_pin_path("/sys/fs/bpf/my-program") + .set_global("CONFIG_VALUE", &42u32, true) + .load_file("program.o")?; +``` + +### Program Lifecycle +1. Parse object file with `Object::parse()` +2. Apply relocations (BTF, maps, calls) +3. Load into kernel with appropriate program type +4. Attach to hook points + +### Map Management +- Maps are created during object loading +- Support for pinning in `/sys/fs/bpf/` +- Automatic BTF integration when available +- Per-CPU variants for performance + +## Development Notes + +### Feature Detection +The library automatically detects kernel BPF features at runtime through `detect_features()` and stores them in a global `FEATURES` static. + +### Cross-compilation +- Uses `bpf-linker` for linking eBPF programs +- Requires nightly Rust for eBPF target compilation +- Supports multiple architectures: x86_64, aarch64, arm, riscv64, powerpc64, s390x, mips + +### Testing Infrastructure +- `test-distro` provides a minimal Linux distribution for testing +- Integration tests run against multiple kernel versions +- Virtualized testing with QEMU for different architectures + +### Workspace Configuration +- Uses Rust 2024 edition +- Minimum supported Rust version: 1.85.0 +- Shared dependencies managed through `workspace.dependencies` +- Default members exclude integration tests (built separately) + +## Important File Locations + +- **Build configuration**: `Cargo.toml` (workspace root) +- **CI configuration**: `.github/workflows/ci.yml` +- **Rust toolchain**: `ebpf/rust-toolchain.toml` +- **Format configuration**: `rustfmt.toml` +- **eBPF programs**: `ebpf/` directory +- **Integration tests**: `test/integration-test/` and `test/integration-ebpf/` +- **Test kernels**: `test/.tmp/` (downloaded during CI) \ No newline at end of file diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..43dfa819 --- /dev/null +++ b/flake.lock @@ -0,0 +1,96 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1751792365, + "narHash": "sha256-J1kI6oAj25IG4EdVlg2hQz8NZTBNYvIS0l4wpr9KcUo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1fd8bada0b6117e6c7eb54aad5813023eed37ccb", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1744536153, + "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1751942411, + "narHash": "sha256-01uMHCt2U9tP4f24DGch145tT8YQppLY5TC9mWK7O0A=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "c587235f892930a61c9e415f0d9792a1b27a41a2", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..c949b79f --- /dev/null +++ b/flake.nix @@ -0,0 +1,144 @@ +{ + description = "Aya eBPF development environment"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + rust-overlay.url = "github:oxalica/rust-overlay"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, rust-overlay, flake-utils }: + flake-utils.lib.eachDefaultSystem (system: + let + overlays = [ (import rust-overlay) ]; + pkgs = import nixpkgs { + inherit system overlays; + }; + + # Rust toolchain with stable for general development + rustToolchain = pkgs.rust-bin.stable.latest.default.override { + extensions = [ "rust-src" "clippy" "rustfmt" ]; + }; + + # Nightly Rust for eBPF compilation (when on Linux) + rustNightly = pkgs.rust-bin.nightly.latest.default.override { + extensions = [ "rust-src" ]; + }; + + in + { + devShells.default = pkgs.mkShell { + buildInputs = with pkgs; [ + # Rust toolchains + rustToolchain + rustNightly + + # Development tools + cargo-watch + cargo-edit + cargo-audit + cargo-deny + cargo-expand + + # System tools + git + curl + wget + + # JSON processing + jq + + # Documentation + mdbook + + # Testing and CI tools + taplo-cli # TOML formatter + + # Additional useful tools + fd + ripgrep + bat + eza + + # Optional eBPF tools (available on some platforms) + pkg-config + + ] ++ lib.optionals stdenv.isLinux [ + # Linux-specific eBPF tools + llvm_15 + clang_15 + libbpf + bpftools + iproute2 + nettools + tcpdump + strace + ltrace + gdb + ] ++ lib.optionals stdenv.isDarwin [ + # macOS-specific tools + darwin.apple_sdk.frameworks.Security + darwin.apple_sdk.frameworks.CoreFoundation + ]; + + shellHook = '' + echo "🦀 Aya eBPF Development Environment" + echo "==================================" + echo + echo "Available Rust toolchains:" + echo " - Stable: $(rustc --version)" + echo " - Nightly: $(rustc +nightly --version 2>/dev/null || echo 'Available for eBPF targets')" + echo + echo "Traffic Monitor:" + echo " cd traffic-monitor" + echo " cargo build --release" + echo " cargo run --example macos-demo # Demo on macOS" + echo " cargo test # Run tests" + echo + echo "System info:" + echo " OS: $(uname -s)" + echo " Arch: $(uname -m)" + echo + + # Set up environment variables for development + export RUST_BACKTRACE="1" + export RUST_LOG="debug" + + # Add cargo tools to PATH if not already there + export PATH="$HOME/.cargo/bin:$PATH" + + # Platform-specific setup + if [[ "$(uname -s)" == "Linux" ]]; then + echo "🐧 Running on Linux - eBPF programs can be loaded!" + if command -v ip >/dev/null 2>&1; then + echo " Available interfaces: $(ip link show | grep -E '^[0-9]+:' | cut -d: -f2 | tr -d ' ' | head -5 | tr '\n' ' ')" + fi + # Set up for eBPF compilation + export CARGO_TARGET_BPFEL_UNKNOWN_NONE_LINKER="bpf-linker" + export CARGO_TARGET_BPFEB_UNKNOWN_NONE_LINKER="bpf-linker" + export CARGO_CFG_BPF_TARGET_ARCH="x86_64" + else + echo "🍎 Running on $(uname -s) - eBPF demo mode available" + echo " For full eBPF testing, use a Linux container or VM" + fi + echo + echo "Ready to start developing! 🚀" + echo + ''; + }; + + # Minimal shell for quick access + devShells.minimal = pkgs.mkShell { + buildInputs = with pkgs; [ + rustToolchain + pkg-config + git + jq + ]; + shellHook = '' + echo "🦀 Minimal Rust environment for Aya" + ''; + }; + } + ); +} \ No newline at end of file diff --git a/traffic-monitor/Cargo.toml b/traffic-monitor/Cargo.toml new file mode 100644 index 00000000..53d07ee4 --- /dev/null +++ b/traffic-monitor/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "traffic-monitor" +version = "0.1.0" +edition = "2021" + +[[bin]] +name = "traffic-monitor" +path = "src/main.rs" + +[dependencies] +aya = { path = "../aya", features = ["async_tokio"] } +aya-log = { path = "../aya-log" } +clap = { version = "4.0", features = ["derive"] } +env_logger = "0.11" +log = "0.4" +tokio = { version = "1.0", features = ["macros", "rt", "rt-multi-thread", "signal"] } +anyhow = "1.0" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +cidr = "0.2" +ipnet = "2.9" +chrono = { version = "0.4", features = ["serde"] } +tempfile = "3.0" + +[build-dependencies] +aya-build = { path = "../aya-build" } + +[workspace] +members = [] + +[[example]] +name = "test-traffic" +path = "examples/test-traffic.rs" \ No newline at end of file diff --git a/traffic-monitor/build.rs b/traffic-monitor/build.rs new file mode 100644 index 00000000..e1d811eb --- /dev/null +++ b/traffic-monitor/build.rs @@ -0,0 +1,8 @@ +use aya_build::EbpfBuilder; + +fn main() { + EbpfBuilder::new() + .file("src/traffic_monitor.bpf.rs") + .build() + .unwrap(); +} \ No newline at end of file