Files
tcptop/.planning/research/STACK.md
2026-03-21 18:08:55 -04:00

14 KiB

Stack Research

Domain: Rust eBPF-based network monitoring TUI tool (cross-platform: Linux + macOS) Researched: 2026-03-21 Confidence: MEDIUM-HIGH (eBPF/Linux stack is well-established; macOS backend strategy has more uncertainty)

Core Technologies

Technology Version Purpose Why Recommended
Rust (nightly) nightly-2026-xx Language + eBPF compilation Nightly required for eBPF target (bpfel-unknown-none, -Z build-std=core). Pin a specific nightly via rust-toolchain.toml for reproducibility.
Aya 0.13.x eBPF library (userspace loader + kernel program SDK) Pure Rust eBPF, no libbpf/bcc dependency. BTF support for kernel portability. Async tokio integration via AsyncPerfEventArray and RingBufAsync. The standard choice for Rust eBPF -- no real competitor in the Rust ecosystem.
aya-ebpf 0.1.x eBPF kernel-side program macros Companion to aya. Provides #[kprobe], #[tracepoint], #[cgroup_skb] macros for writing eBPF programs in Rust.
Ratatui 0.30.x Terminal UI framework Undisputed standard for Rust TUIs. Immediate-mode rendering, sub-millisecond performance, huge widget library. Table, sparklines, and layout primitives are exactly what a top-like tool needs.
Crossterm 0.28.x+ Terminal backend for Ratatui Default backend for ratatui. Cross-platform (Linux, macOS). Pure Rust, no ncurses dependency.
Tokio 1.43+ (LTS) Async runtime Required by Aya's async features (AsyncPerfEventArray, RingBufAsync). Handles concurrent event processing from eBPF maps and TUI rendering loop. Use the LTS release for stability.
clap 4.6.x CLI argument parsing De facto standard. Derive macros for zero-boilerplate argument definitions. Supports --port, --log, --pid flags naturally.

Platform-Specific Backend (Data Collection)

This is the most architecturally significant decision. eBPF only works on Linux. macOS needs a different backend behind a shared trait interface.

Technology Platform Purpose Why Recommended
Aya (eBPF kprobes/tracepoints) Linux Kernel-level connection tracing Lowest overhead. Attach to tcp_connect, tcp_close, tcp_sendmsg, udp_sendmsg etc. Data flows via RingBuf or PerfEventArray to userspace.
pcap (libpcap bindings) macOS (primary) Packet capture with PKTAP macOS PKTAP embeds PID and process name directly in packet headers. The pcap crate (v2.3.x) wraps libpcap which is pre-installed on macOS. PKTAP is the closest macOS equivalent to eBPF for network monitoring.
sysinfo Both Process name/metadata enrichment Cross-platform process information (PID to name mapping, etc.). Supplements both backends.
procfs Linux only /proc/net/* parsing (fallback) Fallback for connection state when eBPF data is incomplete. Parse /proc/net/tcp, /proc/net/udp for socket-to-PID mapping.

Supporting Libraries

Library Version Purpose When to Use
csv 1.4.x CSV log file writing --log output.csv mode. BurntSushi's csv crate is the only sensible choice -- fast, serde-integrated, battle-tested (129M+ downloads).
serde + serde_json 1.x Serialization framework Derive Serialize for connection records. Used by csv crate for struct-to-row mapping.
anyhow 1.x Error handling (application) Ergonomic error handling in the binary crate. Use thiserror in library code if you extract one.
thiserror 2.x Error handling (library) Typed errors for the platform abstraction layer and data collection backends.
nix 0.29.x Unix system calls Low-level syscall access (socket options, process info, privilege checking). Cross-platform Unix support.
libc 0.2.x FFI type definitions Required by aya and nix. Transitive dependency but worth pinning.
log + env_logger 0.4.x / 0.11.x Logging Debug logging during development. Not for the TUI output -- for internal diagnostics.
signal-hook 0.3.x Signal handling Graceful shutdown on SIGINT/SIGTERM. Important for root-privilege tools that manipulate kernel state.

Build and Development Tools

Tool Purpose Notes
bpf-linker Links eBPF object files cargo install bpf-linker. On macOS, install with --no-default-features and ensure LLVM 21+ is available.
cargo-generate Project scaffolding Use aya-template for initial project structure. Optional after initial setup.
rust-toolchain.toml Pin nightly version Critical for reproducible eBPF builds. Pin both nightly channel and bpfel-unknown-none target.
cargo xtask Build orchestration Aya projects use an xtask pattern: a workspace member that builds the eBPF program and embeds it in the userspace binary. Standard pattern -- follow it.
cross Cross-compilation For building Linux binaries from macOS (CI/CD). Not needed for local dev if targeting native platform.

Project Structure (Aya Convention)

tcptop/
  Cargo.toml              # Workspace root
  xtask/                  # Build tool (compiles eBPF, embeds in binary)
    Cargo.toml
    src/main.rs
  tcptop-ebpf/            # eBPF kernel programs (no_std, nightly)
    Cargo.toml
    src/main.rs           # kprobes, tracepoints
  tcptop/                 # Userspace binary
    Cargo.toml
    src/
      main.rs             # CLI parsing, TUI loop
      collector/          # Platform abstraction trait
        mod.rs            # trait NetworkCollector
        linux.rs          # Aya eBPF implementation
        macos.rs          # PKTAP/libpcap implementation
      tui/                # Ratatui rendering
      model/              # Connection state, aggregation

Installation

# Prerequisites (Linux)
rustup toolchain install nightly
rustup target add bpfel-unknown-none --toolchain nightly
cargo install bpf-linker

# Prerequisites (macOS -- for cross-compiling eBPF or developing userspace)
brew install llvm
cargo install bpf-linker --no-default-features

# Project dependencies (in workspace Cargo.toml for userspace crate)
cargo add aya tokio --features tokio/full
cargo add ratatui crossterm
cargo add clap --features derive
cargo add csv serde --features serde/derive
cargo add anyhow thiserror
cargo add sysinfo nix --features nix/net,nix/process
cargo add pcap           # macOS backend
cargo add signal-hook
cargo add log env_logger

# eBPF crate dependencies (tcptop-ebpf/Cargo.toml)
# aya-ebpf = "0.1"
# aya-log-ebpf = "0.1"

Alternatives Considered

Recommended Alternative When to Use Alternative
Aya libbpf-rs (Rust bindings for libbpf) If you need C-based eBPF programs or have existing .bpf.c code to integrate. Aya is better for pure-Rust projects.
Aya RedBPF Never -- RedBPF is largely unmaintained and has been superseded by Aya in the Rust ecosystem.
Ratatui cursive If you want a callback-based (retained mode) TUI instead of immediate mode. Ratatui is better for data-heavy dashboards that redraw frequently.
Crossterm termion If you want a simpler API and only target Unix. Crossterm is better because it already works on both platforms and is ratatui's default.
Tokio async-std Aya supports both, but tokio has far more ecosystem support and is the standard async runtime. No reason to choose async-std.
clap argh (Google) Only if you need minimal binary size and don't need rich help text. clap is better for user-facing CLI tools.
pcap (macOS) DTrace via FFI DTrace is powerful but the Rust FFI story is poor, scripting interface is awkward from Rust, and PKTAP via libpcap is simpler and provides process attribution natively.
pcap (macOS) Network Extension Framework Requires app sandbox, provisioning profiles, and Apple Developer account. Massive overkill for a CLI tool.

What NOT to Use

Avoid Why Use Instead
RedBPF Largely abandoned, last meaningful update 2022. Aya has won the Rust eBPF space. Aya
tui-rs (original) Deprecated. Ratatui is the maintained fork that the community migrated to in 2023. Ratatui
termion Doesn't support Windows (not relevant here), but more importantly crossterm is ratatui's default and better maintained. Crossterm
ncurses / pancurses C dependency, complex linking, less Rust-idiomatic. Ratatui + Crossterm (pure Rust)
raw /proc parsing for all data Fragile, slow (polling), and misses short-lived connections. eBPF (event-driven, kernel-level) with /proc as fallback only
npcap / WinPcap Windows only. Out of scope. pcap (libpcap) for macOS
pnet (Rust networking) Lower-level than needed, doesn't provide PKTAP integration, would require reimplementing what libpcap gives you. pcap crate

Stack Patterns by Variant

If Linux-only (no macOS support needed):

  • Skip the pcap dependency entirely
  • Skip the platform abstraction trait (simplifies architecture)
  • Use Aya directly in the main collector module
  • This significantly reduces complexity

If macOS is a first-class target:

  • Must implement the NetworkCollector trait with two backends
  • macOS backend uses pcap with PKTAP for packet capture + process attribution
  • Connection state tracking (TCP states, byte counts) must be done in userspace on macOS since PKTAP gives raw packets, not connection events
  • Consider shipping macOS as "monitoring mode" (less kernel integration) vs Linux as "full mode"

If you want to develop eBPF programs from macOS:

  • bpf-linker compiles eBPF bytecode on macOS (cross-compilation works)
  • But you cannot load/test eBPF programs on macOS -- need a Linux VM or remote machine
  • Use Lima or OrbStack for local Linux VM testing on Apple Silicon

Version Compatibility

Package Compatible With Notes
aya 0.13.x tokio 1.x Use features = ["async_tokio"] on aya
aya-ebpf 0.1.x Rust nightly Must use nightly toolchain with bpfel-unknown-none target
ratatui 0.30.x crossterm 0.28.x+ Ratatui re-exports crossterm types; check ratatui's Cargo.toml for exact pin
bpf-linker LLVM 21+ On macOS, brew install llvm and set LLVM_SYS_210_PREFIX
pcap 2.3.x libpcap (system) Pre-installed on macOS. On Linux, apt install libpcap-dev.
clap 4.6.x serde 1.x Optional serde integration for config file parsing
Rust nightly aya-ebpf, bpf-linker Only the eBPF crate needs nightly. Userspace crate can use stable Rust via workspace toolchain override.

Key Architecture Decisions Driven by Stack

  1. Workspace with xtask pattern: Aya projects conventionally split into workspace members (ebpf crate, userspace crate, xtask build tool). Follow this convention -- it is well-documented and the community expects it.

  2. Nightly only for eBPF crate: Use rust-toolchain.toml at workspace root with nightly, but the userspace code should be written to compile on stable (future-proofing for when aya-ebpf stabilizes).

  3. Platform abstraction is mandatory: The NetworkCollector trait is the most important architectural boundary. Define it early. Linux backend (Aya) produces connection events; macOS backend (pcap/PKTAP) produces raw packets that must be assembled into connection events.

  4. Async everywhere in userspace: Tokio runtime drives both the eBPF event loop (RingBuf/PerfEventArray polling) and the TUI tick loop. Use tokio::select! to multiplex between data events and TUI input events.

  5. Root privilege handling: Both eBPF loading and libpcap capture require elevated privileges. Check at startup, provide clear error message, fail fast.

Confidence Assessment

Component Confidence Rationale
Aya for eBPF HIGH Undisputed leader in Rust eBPF. Active development (0.13.x released recently). No viable alternative.
Ratatui for TUI HIGH Community standard since tui-rs deprecation. 0.30.x is mature.
clap for CLI HIGH De facto standard, v4.6 actively maintained.
Tokio async runtime HIGH Standard async runtime, LTS releases, Aya integration proven.
csv crate HIGH BurntSushi's csv is the only real option. Mature and stable.
pcap + PKTAP for macOS MEDIUM PKTAP approach is proven (RustNet uses it), but the pcap crate's PKTAP-specific support is less documented. May need raw header parsing. Needs validation during implementation.
bpf-linker on macOS MEDIUM Cross-compilation works per docs, but LLVM version pinning can be fragile. CI may need Linux runners for eBPF compilation.
Overall macOS parity MEDIUM-LOW macOS backend will inherently provide less data than eBPF (no kernel-level TCP state machine hooks). Feature parity is not fully achievable -- must design the abstraction to handle this gracefully.

Sources


Stack research for: tcptop -- Rust eBPF network monitoring TUI Researched: 2026-03-21