chore: improve documentation and README
Rust CI / cargo fmt (push) Successful in 17s
Rust CI / cargo clippy (push) Successful in 33s
Rust CI / cargo check (x86_64-unknown-linux-gnu) (push) Successful in 23s
Rust CI / cargo check (x86_64-unknown-linux-musl) (push) Successful in 33s
Rust CI / cargo test (x86_64-unknown-linux-gnu) (push) Successful in 1m7s
Rust CI / cargo doc (push) Successful in 27s
Rust CI / cargo test (x86_64-unknown-linux-musl) (push) Successful in 1m21s
Fuzz Smoke / cargo fuzz smoke (push) Successful in 1m40s
Netem Interop / netem interop (push) Successful in 1m18s
Supply chain / cargo-deny advisories (push) Successful in 18s
Supply chain / actionlint (push) Failing after 4s
Supply chain / cargo-deny bans licenses sources (push) Successful in 17s
Build binaries / Build (arm-musleabi) (push) Successful in 4m58s
Build binaries / Build (aarch64-musl) (push) Successful in 5m6s
Build binaries / Build (arm-musleabihf) (push) Successful in 4m38s
Build binaries / Build (armv7-musleabi) (push) Successful in 4m33s
Build binaries / Build (armv7-musleabihf) (push) Successful in 4m57s
Build binaries / Build (i686-musl) (push) Successful in 5m1s
Build binaries / Build (mips64-muslabi64) (push) Successful in 4m35s
Build binaries / Build (mips-musl) (push) Successful in 4m42s
Build binaries / Build (mips64el-muslabi64) (push) Successful in 4m54s
Build binaries / Build (mipsel-musl) (push) Successful in 4m54s
Build binaries / Build (riscv64gc-musl) (push) Successful in 4m36s
Build binaries / Build (x86_64-musl) (push) Successful in 4m40s
Rust CI / cargo fmt (push) Successful in 17s
Rust CI / cargo clippy (push) Successful in 33s
Rust CI / cargo check (x86_64-unknown-linux-gnu) (push) Successful in 23s
Rust CI / cargo check (x86_64-unknown-linux-musl) (push) Successful in 33s
Rust CI / cargo test (x86_64-unknown-linux-gnu) (push) Successful in 1m7s
Rust CI / cargo doc (push) Successful in 27s
Rust CI / cargo test (x86_64-unknown-linux-musl) (push) Successful in 1m21s
Fuzz Smoke / cargo fuzz smoke (push) Successful in 1m40s
Netem Interop / netem interop (push) Successful in 1m18s
Supply chain / cargo-deny advisories (push) Successful in 18s
Supply chain / actionlint (push) Failing after 4s
Supply chain / cargo-deny bans licenses sources (push) Successful in 17s
Build binaries / Build (arm-musleabi) (push) Successful in 4m58s
Build binaries / Build (aarch64-musl) (push) Successful in 5m6s
Build binaries / Build (arm-musleabihf) (push) Successful in 4m38s
Build binaries / Build (armv7-musleabi) (push) Successful in 4m33s
Build binaries / Build (armv7-musleabihf) (push) Successful in 4m57s
Build binaries / Build (i686-musl) (push) Successful in 5m1s
Build binaries / Build (mips64-muslabi64) (push) Successful in 4m35s
Build binaries / Build (mips-musl) (push) Successful in 4m42s
Build binaries / Build (mips64el-muslabi64) (push) Successful in 4m54s
Build binaries / Build (mipsel-musl) (push) Successful in 4m54s
Build binaries / Build (riscv64gc-musl) (push) Successful in 4m36s
Build binaries / Build (x86_64-musl) (push) Successful in 4m40s
This commit is contained in:
6 files changed
+534
-466
No files matched your search
@@ -1,97 +1,67 @@
|
||||
# irtt-rs
|
||||
|
||||
`irtt-rs` is a Rust implementation of an IRTT-compatible client and server:
|
||||
finite or continuous UDP latency probing, plus the server side those probes
|
||||
run against.
|
||||
`irtt-rs` is an IRTT-compatible client and server written in Rust. You can use
|
||||
it to measure UDP latency for a fixed duration or leave it running
|
||||
continuously, and run your own server for the probes to talk to.
|
||||
|
||||
This is not the upstream IRTT project. For the original implementation,
|
||||
protocol background, and broader documentation, see
|
||||
[heistp/irtt](https://github.com/heistp/irtt). The installed dispatcher is
|
||||
named `irtt-rs` rather than `irtt` to avoid conflicting with or being
|
||||
mistaken for it.
|
||||
The original IRTT implementation is [heistp/irtt](https://github.com/heistp/irtt),
|
||||
which also has protocol background and more documentation. This project is
|
||||
independent, so the installed dispatcher is named `irtt-rs` to keep it from
|
||||
conflicting with or being mistaken for `irtt`.
|
||||
|
||||
## Features
|
||||
|
||||
* Finite and continuous probe sessions
|
||||
* Concurrent probing of multiple targets, with staggered or burst pacing
|
||||
* Reusable client library with a structured event stream (blocking, Tokio,
|
||||
- Finite and continuous probe sessions
|
||||
- Concurrent probing of multiple targets, with staggered or burst pacing
|
||||
- Reusable client library with a structured event stream (blocking, Tokio,
|
||||
or managed)
|
||||
* Human-readable table output, plus CSV, TSV, and JSON Lines for scripts and
|
||||
- Human-readable table output, plus CSV, TSV, and JSON Lines for scripts and
|
||||
monitoring systems, with selectable output columns
|
||||
* Optional terminal UI
|
||||
* Reusable Tokio-native server library
|
||||
* UDP server applet with sensible zero-argument defaults and explicit bind
|
||||
and session-policy options
|
||||
* Router-friendly multi-applet binary layout
|
||||
- Optional terminal UI
|
||||
- Reusable Tokio-native server library
|
||||
- UDP server applet you can run without arguments, with options for bind
|
||||
addresses and session policy when you need them
|
||||
- A single binary that can run several applets, useful on routers
|
||||
|
||||
## Comparison with upstream IRTT
|
||||
|
||||
`irtt-rs` is an independent, compatible reimplementation, not a successor or
|
||||
replacement for upstream IRTT — [heistp/irtt](https://github.com/heistp/irtt)
|
||||
remains the original implementation. Interoperability is a project goal; see
|
||||
[`docs/INTEROP_COMPARISON.md`](docs/INTEROP_COMPARISON.md) and
|
||||
[`docs/protocol/`](docs/protocol/) for the black-box interoperability
|
||||
methodology and protocol baseline this project verifies against. Choose
|
||||
between them based on the capabilities and deployment model you need.
|
||||
`irtt-rs` is useful if you want to watch several targets at once, compare
|
||||
them in a terminal dashboard, or feed selected measurements into a script.
|
||||
You can leave it running with statistics and automatic reconnection, use
|
||||
its Rust libraries in your own application, or deploy a single binary on
|
||||
a router.
|
||||
|
||||
The table below was checked against upstream release
|
||||
[v0.9.2](https://github.com/heistp/irtt/releases/tag/v0.9.2) (2026-07-17).
|
||||
This project's own interop testing and protocol baseline are currently
|
||||
pinned to the prior release, v0.9.1; the wire protocol version number is
|
||||
unchanged between the two, but v0.9.2 has not itself been exercised against
|
||||
this project's interop harness.
|
||||
Upstream IRTT is much more mature, and if you don't need the features
|
||||
specific to `irtt-rs`, you should probably use it. It also has more tools
|
||||
for working with saved results and controlling how probes run, including
|
||||
replaying saved JSON reports, timer and clock diagnostics, and client
|
||||
payload fill and timing algorithms.
|
||||
|
||||
| Capability | irtt-rs | upstream IRTT (v0.9.2) |
|
||||
| --- | --- | --- |
|
||||
| Wire protocol | Protocol version 1, verified against upstream v0.9.1 | Protocol version 1 (unchanged in v0.9.2) |
|
||||
| Finite probing | Supported, default 10s | Supported, default 1m |
|
||||
| Continuous/indefinite operation | Supported (`--continuous` or `--duration 0`), with optional per-target reconnection | Supported via streaming mode (`-s`, added in v0.9.2); computes no statistics at all in that mode |
|
||||
| Statistics in continuous mode | Optional running count/min/max/mean/variance per session; no exact medians; bounded IPDV tracking. Use `--no-stats` or omit the `stats` feature to disable collection | None in streaming mode — raw/event output only, by design, to avoid unbounded memory |
|
||||
| Multi-target probing (one invocation) | Supported, with labels and staggered/burst pacing | Not supported — one remote address per invocation |
|
||||
| Terminal UI | `irtt-tui`, a live graph/dashboard applet | Not present |
|
||||
| Output formats | table, csv, tsv, jsonl, with selectable columns | Text summary, JSON (optionally gzip to file), and a fixed-field raw mode; no CSV/TSV and no column selection |
|
||||
| Client/server library API | Separate, independently versioned Rust crates (`irtt-client`, `irtt-server`) | One combined Go package exposing both roles |
|
||||
| Server: multiple listeners | `ServerSet` supervises several listeners in one process | `ListenAndServe` also serves multiple requested addresses |
|
||||
| Server: wildcard reply-source | Default behavior on Linux/macOS/FreeBSD; refused elsewhere rather than served incorrectly | Opt-in via `--set-src-ip`, with a documented per-packet allocation cost |
|
||||
| Server: zero-argument bind | Binds the wildcard address on both families by default, gated by the platform check above | Binds the wildcard address on both families by default; no documented platform gate |
|
||||
| Prebuilt release binaries | Published for six target triples | None published; install via `go install` or manual build |
|
||||
|
||||
Upstream has capabilities this project does not implement: a `report`
|
||||
subcommand for replaying saved JSON results, benchmarking and
|
||||
timer/clock-diagnostic subcommands, client-side payload fill and
|
||||
don't-fragment/wait-strategy/timer-algorithm controls, an operator-configurable
|
||||
server-side fill policy (this project's server always honors a session's
|
||||
negotiated fill request, with a fixed fallback pattern, but has no equivalent
|
||||
to upstream's flags for restricting or overriding it), syslog logging, and
|
||||
bundled systemd/OpenRC service files.
|
||||
|
||||
This project has capabilities upstream does not implement: multi-target
|
||||
probing with labels, the terminal UI, CSV/TSV output with selectable
|
||||
columns, a quantified and actively-warned memory-retention model for
|
||||
long-running client sessions, and best-effort Linux kernel-timestamp
|
||||
preference for its own send/receive endpoint.
|
||||
See the [detailed comparison](docs/INTEROP_COMPARISON.md) for individual
|
||||
features, version coverage, and black-box interoperability testing.
|
||||
|
||||
## Installation
|
||||
|
||||
The build requires Rust 1.88 or newer.
|
||||
Prebuilt binaries for supported platforms are available on the
|
||||
[GitHub Releases](https://github.com/Lochnair/irtt-rs/releases) page.
|
||||
|
||||
Install the latest release from crates.io:
|
||||
Alternatively, install from crates.io using Rust 1.88 or newer:
|
||||
|
||||
```sh
|
||||
cargo install irtt-rs --locked
|
||||
```
|
||||
|
||||
This installs the `irtt-rs` dispatcher plus dedicated `irtt-client`,
|
||||
`irtt-tui`, and `irtt-server` binaries. Each applet can also be built in
|
||||
isolation with `--no-default-features` plus the applet's own feature, for
|
||||
example a lightweight client-only install without statistics:
|
||||
This installs the `irtt-rs` dispatcher along with dedicated `irtt-client`,
|
||||
`irtt-tui`, and `irtt-server` binaries. If you only need the client, you can
|
||||
disable the other applets and statistics:
|
||||
|
||||
```sh
|
||||
cargo install irtt-rs --locked --no-default-features --features client
|
||||
```
|
||||
|
||||
Add `stats` (`--features client,stats`) to retain statistics in a client-only
|
||||
build. Statistics are enabled by default; the TUI always enables them.
|
||||
This installs `irtt-client` and the `irtt-rs` dispatcher. Add `stats`
|
||||
(`--features client,stats`) to retain statistics in a client-only build.
|
||||
Statistics are enabled by default; the TUI always enables them.
|
||||
|
||||
For development, or to install directly from a checkout:
|
||||
|
||||
@@ -131,30 +101,56 @@ Watch the same session live in the terminal UI:
|
||||
irtt-tui netperf-eu.bufferbloat.net:2112
|
||||
```
|
||||
|
||||
Run a server with sensible defaults — no `--bind` needed:
|
||||
To run your own server, you can leave out `--bind` and use the defaults:
|
||||
|
||||
```sh
|
||||
irtt-server
|
||||
```
|
||||
|
||||
### Dynamic targets from stdin
|
||||
|
||||
If another application decides which servers to probe, `--targets-stdin`
|
||||
lets it change targets without restarting the client. It works in
|
||||
continuous mode:
|
||||
|
||||
```sh
|
||||
irtt-client --continuous --targets-stdin --reconnect --no-stats \
|
||||
--format csv --columns event,target,seq,rd_us,sd_us
|
||||
```
|
||||
|
||||
Send one comma-separated target set per line to stdin, for example:
|
||||
|
||||
```text
|
||||
ams=ams.example:2112,lhr=lhr.example:2112
|
||||
ams=ams.example:2112
|
||||
[]
|
||||
```
|
||||
|
||||
Each line gives the complete desired target set. Unchanged targets keep
|
||||
running, removed targets stop, and new or changed targets start. Use `[]`
|
||||
to clear all targets without exiting.
|
||||
|
||||
The CSV includes an `event` column so your script can distinguish
|
||||
`echo_reply` measurements from other events.
|
||||
|
||||
Keep stdin open while controlling the client. Closing it sends EOF and stops the run gracefully.
|
||||
|
||||
See [Dynamic target sets from standard input](docs/irtt-client.md#dynamic-target-sets-from-standard-input)
|
||||
for the full syntax and behavior.
|
||||
|
||||
## Documentation
|
||||
|
||||
* [`docs/irtt-client.md`](docs/irtt-client.md) — target syntax, output
|
||||
- [`docs/irtt-client.md`](docs/irtt-client.md): target syntax, output
|
||||
formats and columns, measurement field definitions, finite/continuous
|
||||
memory behavior, kernel timestamps.
|
||||
* [`docs/irtt-tui.md`](docs/irtt-tui.md) — controls, continuous default,
|
||||
- [`docs/irtt-tui.md`](docs/irtt-tui.md): controls, continuous default,
|
||||
retained history.
|
||||
* [`docs/irtt-server.md`](docs/irtt-server.md) — bind defaults and
|
||||
- [`docs/irtt-server.md`](docs/irtt-server.md): bind defaults and
|
||||
overrides, wildcard listener behavior, session policy, HMAC.
|
||||
* [`docs/irtt-rs.md`](docs/irtt-rs.md) — the multicall dispatcher, applet
|
||||
- [`docs/irtt-rs.md`](docs/irtt-rs.md): the multicall dispatcher, applet
|
||||
binary names, feature-gated builds.
|
||||
* [docs.rs](https://docs.rs) for the library crates below.
|
||||
* [`docs/protocol/`](docs/protocol/) and
|
||||
[`docs/INTEROP_COMPARISON.md`](docs/INTEROP_COMPARISON.md) for the wire
|
||||
protocol specification and interoperability validation against upstream
|
||||
`irtt`.
|
||||
|
||||
Every applet also documents its full option list with `--help`.
|
||||
You can also run any applet with `--help` for its full option list.
|
||||
|
||||
## Crates
|
||||
|
||||
@@ -166,9 +162,6 @@ Every applet also documents its full option list with `--help`.
|
||||
| [`irtt-stats`](crates/irtt-stats) | [crates.io](https://crates.io/crates/irtt-stats) | Statistics aggregation over `irtt-client` events ([docs.rs](https://docs.rs/irtt-stats)) |
|
||||
| [`irtt-proto`](crates/irtt-proto) | [crates.io](https://crates.io/crates/irtt-proto) | Low-level wire protocol encode/decode ([docs.rs](https://docs.rs/irtt-proto)) |
|
||||
|
||||
Each library crate has its own crates.io README describing what it's for and
|
||||
when to use it instead of `irtt-client`/`irtt-server` directly.
|
||||
|
||||
## Binaries and features
|
||||
|
||||
| Build | Binaries |
|
||||
@@ -188,7 +181,3 @@ cargo test --workspace --locked
|
||||
cargo test --workspace --doc --all-features --locked
|
||||
cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
|
||||
```
|
||||
|
||||
See [`AGENTS.md`](AGENTS.md) for architecture, testing policy, and the
|
||||
clean-room provenance boundary this project maintains against upstream
|
||||
`irtt`.
|
||||
Reference in new issue
Block a user