RustPCAPrune is a native Rust implementation of the pcap-slim algorithm: stream through a libpcap file, preserve every packet's timestamp and headers, and truncate only encrypted L4 payloads to the first 24 bytes.
The crate and binary are named pcap-slim to match the algorithm and keep CLI invocations identical to the Python reference predecessor.
cargo build --releaseBinary: target/release/pcap-slim
The default build enables mmap input (--features mmap). Disable with cargo build --release --no-default-features.
Wait for downstream indexers (e.g. Arkime offline) to finish, then slim in place:
pcap-slim --dir /home/sensor/Malcolm/pcap/processed \
--age-minutes 15 \
--workers 2 \
--output json--age-minutes: only files whose mtime is at least N minutes old (--dironly).--workers 2: recommended for typical sensor deployments; mmap is used automatically for ≤2 workers.- For
--workers 4, bufferedread()is used automatically (avoids cold-cache mmap page-fault contention). Force mmap with--mmapif you accept the trade-off.
pcap-slim --single /path/to/capture.pcap
pcap-slim --single /path/to/large.pcap --mmap # optional mmap for single filepcap-slim --dir /path --age-minutes 15 --dry-run
pcap-slim --single capture.pcap --check-only
pcap-slim --dir /path --check-only --output jsonpcap-slim --dir /path --age-minutes 15 --workers 2 \
--max-io-mbps 50 \
--cpu-backoff-above 70pcap-slim --dir /path --age-minutes 15 --output json | jq .| Flag | Purpose |
|---|---|
--dir PATH |
Slim all pending .pcap files in directory (in place) |
--single PATH |
Slim one file in place |
--workers N |
Parallel files (--dir only; does not split one pcap) |
--age-minutes N |
Skip files newer than N minutes (--dir only) |
--dry-run |
List eligible files, no writes |
--check-only |
Analyze only; no writes or markers |
--output human|json |
Per-file report format |
--max-io-mbps N |
Shared read+write throughput cap |
--max-cpu-percent N |
Process CPU cap (1–100) |
--cpu-backoff-above N |
Reduce target when host load is high |
--cpu-backoff-strength F |
Backoff aggressiveness (0.0–1.0, default 0.5) |
--mmap |
Force mmap reads |
--no-mmap |
Force buffered reads (overrides auto selection) |
| Workers | Default I/O |
|---|---|
| 1–2 | mmap |
| 3+ | buffered read() (override with --mmap) |
For each capture.pcap:
- Skip if
.slim_markers/capture.pcapexists - Write
capture.pcap.tmp, verify packet count matches slim pass - Atomically rename tmp over original
- Create marker file (
sensor:sensorwhen that user exists; else calling user)
On startup, delete stale *.pcap.tmp files older than 5 minutes in --dir.
Production budgets (cold cache) are documented in benches/budgets.txt.
cargo run --release --bin budget_checkMeasure locally:
cargo build --release
time target/release/pcap-slim --single large.pcapRelease profile: thin LTO, codegen-units = 1, stripped binary.
python3 scripts/gen_fixtures.py # synthetic fixtures
python3 scripts/gen_expected_hashes.py # after: cargo build --release
cargo testfixtures/expected.json: per-fileanalyzestats (Rust source of truth).fixtures/expected_hashes.json: SHA-256 of Rust slim output per fixture (not Python/scapy).- Scapy parity (optional):
cargo test --test golden --test golden_fixtures -- --ignored
- snaplen: Rust preserves the input global header verbatim (spec). Scapy writes
snaplen = 65535. Body bytes match when comparing from offset 24; golden hashes use full Rust output files. - pcapng: Rejected with exit 1 and a clear message; file unchanged.
- IPv4 LSRR/SSRR: TCP/UDP pseudo-header uses source-route address (matches Scapy).
See pcap-slim-algorithm.md. Python reference: ../PCAP_External_Cleaner/pcap_slim_lib.py.