Transfer independently black-box-verified server behavior from a source-assisted research phase conducted outside this repository. Only a sanitizer-candidate report of black-box findings and the packet captures it referenced were admitted; no upstream source, tests, history, harnesses, build trees, result files or source-assisted analysis crossed the boundary. Provenance and the boundary discipline are recorded in docs/clean-room/CLEANROOM_NOTES.md. New upstream robustness defect (Section 22.5). An open selecting timestamps while omitting the Clock parameter is accepted with a valid token and no Clock echoed, and the first echo on that session is fatal to the server process, taking unrelated sessions on the same process with it. An explicit Clock=0 is instead rejected at open, so parameter presence is externally meaningful. Recorded as an observed defect with a must-not-crash recommendation; the clean server's resolution is deliberately left to the implementation work. Also established or strengthened: - the idle grace and maximum-duration grace are fixed additive margins across the settings swept, and the maximum-duration clock starts at the first echo that is actually served; - a rate-limited request is the only tested drop class that keeps a session alive, and in one documented configuration a conforming client can observe the difference; - a post-deadline packet of several tested classes consumes an expired session's one remaining reply, including packets that are themselves dropped; - the reply-length cap is the bind interface's MTU on the interfaces where it was reachable, and a length the host cannot transmit ends the process; - DSCP marking follows the session, with unmarked open replies and no cross-session leakage across interleaved sessions; - repeated tags are last-valid-wins, with invalid-duplicate handling scoped to the orders actually tested, and unknown tag values are consumed as varints. Three captures were admitted, each rewritten to the container convention already used here and verified byte-identical in packet data and timestamps: server-clock-absent (3 packets), server-expiry-consumption (14) and server-dscp-interleaved (32). Two further captures were reviewed and rejected as redundant or unsupporting; their textual results were kept instead. Host-specific figures are labelled as such throughout, upstream defects are not promoted to protocol requirements, observations are separated from inferences and from recommendations, and no implementation policy is chosen here. The client specification gains matching refinements where the two compatibility baselines would otherwise state a lifecycle or marking rule differently. Documentation and evidence only; no production code changed.
irtt-rs
irtt-rs is a Rust implementation of an IRTT-compatible client.
It provides both a command-line client and a reusable Rust library for finite or continuous latency probing. It is intended for interactive diagnostics, scripting, monitoring, and integration into applications such as network autorate controllers.
This is not the upstream IRTT project. For the original implementation, protocol background, and broader documentation, see heistp/irtt.
Features
- Finite and continuous probe sessions
- Concurrent probing of multiple targets
- Reusable client library with a structured event stream
- Human-readable table output
- CSV, TSV, and JSON Lines output for scripts and monitoring systems
- Selectable output columns
- Automatic final summaries for eligible table-output runs
- Optional terminal UI
- Router-friendly multi-applet binary layout
Server support is not implemented.
The installed dispatcher is named irtt-rs rather than irtt to avoid conflicting with or being mistaken for upstream IRTT.
Installation
The build requires Rust 1.88 or newer.
From a local checkout:
git clone https://github.com/Lochnair/irtt-rs.git
cd irtt-rs
cargo install --path crates/irtt-cli
This installs:
irtt-rs, the canonical multi-applet dispatcherirtt-cli, the stream and text client
To also install the optional terminal UI:
cargo install --path crates/irtt-cli --features tui
Quick start
Probe a server using the default settings:
irtt-cli netperf-eu.bufferbloat.net:2112
Set the test duration and probe interval:
irtt-cli netperf-eu.bufferbloat.net:2112 \
--duration 30s \
--interval 100ms
Run continuously until interrupted:
irtt-cli netperf-eu.bufferbloat.net:2112 --duration 0
Use Ctrl-C to stop gracefully.
Multiple targets
Probe several targets concurrently:
irtt-cli host-a:2112 host-b:2112
Assign stable labels to targets:
irtt-cli \
--target ams=ams.example.com:2112 \
--target sg=sg.example.com:2112
Multi-target sessions use staggered pacing by default. To send each target's probes together:
irtt-cli host-a:2112 host-b:2112 --pacing burst
Target labels are included in the default multi-target output.
Output formats
The CLI supports four event-row formats:
table: human-readable terminal outputcsv: comma-separated outputtsv: tab-separated outputjsonl: one JSON object per event
Examples:
irtt-cli <server> --format table
irtt-cli <server> --format jsonl
irtt-cli <server> --format csv \
--columns event,seq,remote,effective_rtt_us
For a stream containing only effective RTT values in microseconds:
irtt-cli <server> \
--format tsv \
--columns effective_rtt_us \
--header never
List all available columns with:
irtt-cli --list-columns
Useful measurement fields include:
raw_rtt_us: client-observed send-to-receive RTTadjusted_rtt_us: RTT adjusted for server processing when availableeffective_rtt_us: adjusted RTT when available, otherwise raw RTTsd_usandrd_us: send and receive one-way delay estimatesipdv_us: inter-packet delay variationserver_processing_us: time spent processing the packet at the server
Adjusted RTT can be negative when server processing exceeds the measured raw RTT. One-way delay estimates can be negative because of clock skew between the client and server.
Default table output prints a final summary after completed finite runs and interrupted continuous runs when the run policy permits it. CSV, TSV, and JSON Lines output do not print this summary.
A peer closing a finite CLI or TUI run is accepted as a terminal outcome. In continuous mode, peer closure exits nonzero unless the user requested interruption, allowing a supervisor to restart the client.
Terminal UI
When built with the tui feature, irtt-tui provides a live cumulative dashboard:
irtt-tui <server>
It runs continuously by default. A finite duration can be selected explicitly:
irtt-tui <server> --duration 30s
Multiple targets and pacing options work the same way as in irtt-cli:
irtt-tui host-a:2112 host-b:2112 --pacing burst
Quit with q or Ctrl-C.
Library usage
irtt-client exposes the client session and event layer independently of CLI formatting and statistics.
Add it from a local checkout:
[dependencies]
irtt-client = { path = "crates/irtt-client", features = ["tokio"] }
Minimal managed-client example for a synchronous frontend:
use std::time::Duration;
use irtt_client::managed::{
BlockingManagedClient, ManagedClientConfig, ManagedCompletionPolicy,
ManagedTargetConfig, TargetId,
};
use irtt_client::ClientConfig;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = ManagedClientConfig {
client: ClientConfig {
duration: Some(Duration::from_secs(10)),
interval: Duration::from_secs(1),
..ClientConfig::default()
},
completion: ManagedCompletionPolicy::FinishWhenQuiescent,
..ManagedClientConfig::default()
};
let targets = vec![ManagedTargetConfig::new(
TargetId::from("edge"),
"netperf-eu.bufferbloat.net:2112",
)];
let owner = BlockingManagedClient::start(config, targets)?;
let outcome = owner.join()?;
println!("session ended: {:?}", outcome.end_reason);
Ok(())
}
For presentation events, use BlockingManagedClient::start_with_subscription,
ManagedEvent, and ManagedEventTryRecvError, while consulting the durable
handle.status() and final outcome for authoritative state. Presentation
events are bounded and lossy, not reliable history. Dynamic desired-target
updates are available through ManagedClientHandle::update_targets.
BlockingManagedClient owns a dedicated Tokio runtime and thread for
synchronous callers. Callers that already own Tokio can drive
ManagedClientTask directly.
Binaries and features
| Build | Binaries |
|---|---|
--no-default-features |
irtt-rs |
| Default features | irtt-rs, irtt-cli |
--features tui |
irtt-rs, irtt-cli, irtt-tui |
--all-features |
irtt-rs, irtt-cli, irtt-tui |
For available command-line options:
irtt-cli --help
irtt-tui --help
Development
Common verification commands:
cargo fmt --check
cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
cargo build -p irtt-cli --all-features --release
Project status
The client, event stream, machine-readable output, multi-target execution, local statistics, and optional TUI are implemented.
Server support is not implemented.