iperf3-rs
A Rust frontend for libiperf that adds live observability while keeping iperf3 behavior intact.
- Live Metrics: Exports interval results to a Prometheus Pushgateway directly from
libiperfwhile a test is running, without waiting for final JSON output or scraping CLI text. - Upstream Compatibility: Uses upstream
esnet/iperf3under the hood instead of a Rust reimplementation, so iperf3 options and wire behavior stay aligned with upstream.
Installation
macOS (Homebrew)
Prebuilt macOS binaries are available from the Homebrew tap:
$ brew tap mi2428/iperf3-rs
$ brew install iperf3-rs
Cargo (crates.io)
Install the CLI from crates.io with Cargo:
$ cargo install iperf3-rs
$ cargo install iperf3-rs --version 1.0.1 # install a specific version
[!NOTE] Cargo builds the vendored
libiperfsource, so the host needs a C compiler,make, andpkg-config.
Build from source
Source builds compile the vendored upstream iperf3 submodule. Clone recursively, or initialize the submodule in an existing checkout, then install the release binary and shell completions:
$ git clone --recursive https://github.com/mi2428/iperf3-rs
$ git submodule update --init --recursive # if the submodule is missing
$ make install # install the binary only
$ make install COMPLETION=1 # install the binary and shell completions
CLI Usage
Use iperf3-rs like iperf3, then add --push.* or --metrics.* options when you need live interval metrics.
The help output keeps the upstream iperf3 options and adds an iperf3-rs options section near the top:
$ iperf3-rs -h | head -40
Usage: iperf3 [-s|-c host] [options]
iperf3 [-h|--help] [-v|--version]
iperf3-rs options:
--push.url URL push interval metrics to a Pushgateway URL
bare host:port values default to http://
--push.delete-on-exit delete this Pushgateway grouping key after the run exits
--push.interval DURATION aggregate interval samples before pushing window metrics
--push.job JOB Pushgateway job name (default: iperf3)
--push.label KEY=VALUE add a Pushgateway grouping label; repeatable
--push.retries N retry failed Pushgateway requests N times (default: 0)
--push.timeout DURATION per-request timeout: 500ms, 5s, 1m, or seconds (default: 5s)
--push.user-agent VALUE HTTP User-Agent for Pushgateway requests
--metrics.file PATH write live interval metrics to a file
does not change iperf stdout
--metrics.format FORMAT metrics file format: jsonl or prometheus (default: jsonl)
--metrics.label KEY=VALUE add a Prometheus file sample label; repeatable
requires --metrics.format prometheus
--metrics.prefix P Prometheus metric name prefix (default: iperf3)
iperf3-rs environment:
IPERF3_PUSH_URL=URL default value for --push.url
IPERF3_PUSH_DELETE_ON_EXIT=BOOL default value for --push.delete-on-exit
IPERF3_PUSH_INTERVAL=DURATION default value for --push.interval
IPERF3_PUSH_JOB=JOB default value for --push.job
IPERF3_PUSH_LABELS=KEY=VALUE,... default labels added before --push.label values
IPERF3_PUSH_RETRIES=N default value for --push.retries
IPERF3_PUSH_TIMEOUT=DURATION default value for --push.timeout
IPERF3_PUSH_USER_AGENT=VALUE default value for --push.user-agent
IPERF3_METRICS_FILE=PATH default value for --metrics.file
IPERF3_METRICS_FORMAT=FORMAT default value for --metrics.format
IPERF3_METRICS_LABELS=KEY=VALUE,... default labels for Prometheus file output
IPERF3_METRICS_PREFIX=P default value for --metrics.prefix
Server or Client:
-p, --port # server port to listen on/connect to
-f, --format [kmgtKMGT] format to report: Kbits, Mbits, Gbits, Tbits
-i, --interval # seconds between periodic throughput reports
-I, --pidfile file write PID file
-F, --file name xmit/recv the specified file
CLI values override environment defaults. Duplicate label names are rejected within each label set. Pushgateway writes and delete-on-exit cleanup are best-effort. Failures are reported on stderr, but they do not make the CLI fail when the iperf run itself succeeds.
Pushgateway
Start the local observability stack (Prometheus, Pushgateway, and Grafana) with Docker Compose:
$ docker compose up
Bare host:port Pushgateway values default to HTTP. Use an explicit https:// URL when your Pushgateway requires TLS.
Add grouping labels with --push.label KEY=VALUE, repeating the flag for multiple labels.
The grouping key always includes job (default: iperf3); other labels are included only when you set them.
When a client and server, or multiple concurrent sessions, push to the same gateway, add labels that distinguish the role or test run.
$ iperf3-rs -c 198.18.0.1 \
--push.url 127.0.0.1:9091 \
--push.label role=client --push.label scenario=sample
$ iperf3-rs -s \
--push.url 127.0.0.1:9091 \
--push.label role=server --push.label scenario=sample
If the Pushgateway cannot keep up with every iperf interval, use --push.interval to aggregate samples locally and push one window summary per interval.
Window pushes use iperf3_window_* metric families such as iperf3_window_duration_seconds, iperf3_window_transferred_bytes, and iperf3_window_bandwidth_mean_bits_per_second.
$ iperf3-rs -s \
--push.url 127.0.0.1:9091 --push.interval 10s \
--push.label role=server --push.label scenario=sample
File Output
Use --metrics.file when the metrics artifact should affect the exit status:
$ iperf3-rs --metrics.file iperf3-metrics.jsonl -c 198.18.0.1
The default jsonl format writes one JSON object per libiperf interval.
The prometheus format writes the latest interval as Prometheus text exposition and atomically replaces the file on each interval:
$ iperf3-rs -c 198.18.0.1 \
--metrics.file iperf3.prom --metrics.format prometheus --metrics.prefix nettest \
--metrics.label role=client --metrics.label scenario=sample
File output can be used by itself or together with Pushgateway export.
It does not change normal iperf stdout or -J JSON behavior.
Rust API Usage
Use iperf3-rs as a Rust crate when bots, controllers, or test harnesses need to run iperf directly and consume live metrics programmatically.
See the examples directory for complete library examples.
[]
= "1"
use Duration;
use ;
Developer setup, verification, release operations, and detailed behavior contracts live in CONTRIBUTING.md.
Verification Coverage
The current test suite is intentionally broader than ordinary unit coverage: it exercises the Rust API, CLI behavior, Docker interop with upstream iperf3, Pushgateway delivery, release-image shape, and bounded model-checking invariants.
Current coverage snapshot:
- 95 default-feature unit tests.
- 12 local integration tests in
tests/integration. - 2 rustdoc compile tests.
- 2 Docker E2E tests in
tests/e2e, covering Compose interop, live Pushgateway metrics, protocol variants, and release-image smoke behavior. - 1 Docker example integration test for
examples/bwcheck. - 21 Kani proof harnesses for parsers, metric aggregation, Prometheus labels, Pushgateway retry/path encoding, and other bounded invariants.
That is 133 named default-feature runtime/model-checking checks, plus a no-default feature matrix that re-runs 46 unit, integration, and doctest checks without pushgateway/serde.
$ make check # fmt, clippy, docs, default tests, no-default tests, completions
$ make integration # local integration suite
$ make e2e # Docker E2E suite
$ make kani # Kani proof harnesses
License
iperf3-rsRust code is licensed under MIT.- The vendored
esnet/iperf3source keeps its upstream BSD-style license and third-party notices. - SORACOM, Inc. also has a separate permissive license grant. See LICENSE-SORACOM.
