riperf3
A ground-up, idiomatic Rust implementation of iperf3, the standard network performance measurement tool — not a C port or a binding, but a faithful reimplementation in safe, async Rust.
riperf3 speaks iperf3's exact wire protocol: a riperf3 client interoperates with an iperf3 server, and vice versa, across every mode. Fidelity is the guiding principle — riperf3 matches iperf3 flag for flag and quirk for quirk rather than reinventing the interface. Where iperf3 accepts an option, riperf3 implements it to behave the same way; it does not reject, rename, or work around iperf3's semantics. The goal is a drop-in you can swap in without your scripts, dashboards, or muscle memory noticing.
Highlights
- Wire-protocol compatible with iperf3. Passes interchange tests in both directions across all modes.
- Comprehensive flag support — 60+ flags covering TCP, UDP, parallel streams, reverse/bidir, zerocopy, GSO/GRO, RSA authentication, IPv6, MPTCP, and more.
- Safe Rust —
unsafeis used only for platform-specific kernel syscalls (setsockopt/getsockopt) with no safe wrapper. No unsafe in any application logic or public API. See the audit table for the full inventory. - Single static binary with no runtime dependencies.
- Idiomatic Rust — not a C port. Uses tokio for async I/O, serde for JSON, clap for CLI parsing, nix for safe Unix syscalls.
- 369 tests — unit, integration, and full client-server loopback with interchange verification.
Quick Start
# Build
# Server
# Client (from another machine)
Common Options
Interchange Compatibility
riperf3 is wire-compatible with iperf3. You can freely mix clients and servers:
# riperf3 server, iperf3 client
# iperf3 server, riperf3 client
Verified across TCP (normal, reverse, bidir, parallel, zerocopy, BBR, file mode), UDP (10G, 50G), IPv6, and RSA authentication.
Performance
On a two-VM QEMU/KVM sandbox (virtio-net, MTU 9000, 8 vCPU), a 30-run-per-cell campaign puts riperf3 at or above iperf3 throughput across the board:
- TCP — near-parity single-stream (~75 Gbps; one marginal cell aside); a few percent ahead at
-P 8. - UDP — significantly faster in every cell (~+10–17%), and holds steady across
-Pinstead of collapsing. - Wire-compatible with iperf3 (current and 3.12) in both directions.
BENCHMARKS.md has the authoritative numbers — per-cell 95% confidence intervals, significance tests, the compatibility matrix, and full methodology.
Platform Support
riperf3 builds on Linux, macOS, FreeBSD, and Windows. Linux is the reference platform (full feature set, primary CI); macOS is verified in native CI; Windows compiles and is cross-checked in CI, with a few runtime gaps still under triage in the issue tracker; FreeBSD is supported via conditional compilation but is not yet exercised in CI. Platform-specific features use safe Rust wrappers where available, with graceful degradation or a clear error message where a flag is unavailable.
| Feature | Linux | macOS | FreeBSD | Windows |
|---|---|---|---|---|
| TCP/UDP core | yes | yes | yes | yes |
-w window size |
yes | yes | yes | yes |
-N no-delay |
yes | yes | yes | yes |
-M MSS |
yes | yes | yes | yes |
-S TOS |
yes | yes | yes | yes |
-A CPU affinity |
yes | yes | yes | |
--dont-fragment |
yes | yes | yes | yes |
-Z zerocopy (sendfile) |
yes | yes | yes | |
-C congestion control |
yes | yes | ||
-D daemon |
yes* | yes* | ||
--bind-dev |
yes | yes | ||
--rcv-timeout |
yes | yes | yes | |
--cntl-ka keepalive |
yes | yes | yes | |
| TCP_INFO stats | yes | yes | yes | |
--snd-timeout |
yes | |||
--fq-rate pacing |
yes | |||
--flowlabel IPv6 |
yes | |||
--gsro UDP GSO/GRO |
yes | |||
--sendmmsg batched UDP |
yes | yes |
All platform-specific flags match iperf3's support matrix exactly for flags shared with iperf3. --sendmmsg is a riperf3-exclusive experimental optimization. Blank cells indicate the feature is unavailable on that platform in both riperf3 and iperf3. Unsupported flags return a clear error at startup.
* -s -D daemon mode is currently broken — the daemonized server listens but never serves, so clients hang (#81). Tracked for a post-0.6.0 fix; use a foreground -s server meanwhile.
CLI Reference
Usage: riperf3 [OPTIONS] <--server|--client <host>>
General:
-s, --server Run in server mode
-c, --client <host> Run in client mode
-p, --port <PORT> Server port (default: 5201)
-f, --format <k|m|g|t> Report format (default: Mbits)
-i, --interval <secs> Seconds between periodic reports
-V, --verbose Verbose output
-J, --json JSON output
--json-stream Line-delimited JSON output
-v, --version Print version
-I, --pidfile <file> Write PID to file
--logfile <file> Redirect output to log file
--forceflush Flush output at every interval
--timestamps [<format>] Timestamp each output line
Server:
-1, --one-off Handle one client then exit
-D, --daemon Daemonize
--idle-timeout <secs> Restart idle server after N seconds
--server-bitrate-limit <rate> Server's total bitrate limit
--server-max-duration <secs> Max test duration on server
Test parameters:
-u, --udp Use UDP instead of TCP
-t, --time <secs> Test duration (default: 10)
-n, --bytes <N[KMG]> Bytes to transmit (instead of -t)
-k, --blockcount <N[KMG]> Blocks to transmit (instead of -t)
-l, --length <N[KMG]> Buffer size (default: 128K TCP; UDP tracks MSS, else 1460)
-P, --parallel <N> Parallel streams
-R, --reverse Server sends, client receives
--bidir Bidirectional test
-b, --bitrate <rate[/burst]> Target bitrate (default: unlimited TCP, 1M UDP)
-O, --omit <secs> Omit first N seconds
TCP options:
-w, --window <N[KMG]> Socket buffer size
-C, --congestion <algo> Congestion control algorithm (e.g., bbr)
-M, --set-mss <N> Maximum segment size
-N, --no-delay Set TCP_NODELAY
-Z, --zerocopy Zero-copy sends via sendfile()
--cntl-ka <idle/intv/cnt> Control connection TCP keepalive
UDP options:
--gsro Enable UDP GSO/GRO
--sendmmsg Batched UDP sends via sendmmsg (experimental)
--udp-counters-64bit Use 64-bit UDP counters
--repeating-payload Repeating pattern payload
--dont-fragment Set IPv4 Don't Fragment
Network:
-4, --version4 IPv4 only
-6, --version6 IPv6 only
-B, --bind <host> Bind to address
--bind-dev <dev> Bind to device (SO_BINDTODEVICE)
--cport <port> Bind to specific client port
--fq-rate <rate> Fair-queue socket pacing (bits/sec)
-L, --flowlabel <N> IPv6 flow label
-S, --tos <N> IP type of service
--dscp <val> DSCP value (0-63 or symbolic)
-m, --mptcp Use MPTCP
--connect-timeout <ms> Control connection timeout
--rcv-timeout <ms> Receive idle timeout
--snd-timeout <ms> Unacknowledged TCP data timeout
--skip-rx-copy Discard received data (MSG_TRUNC)
File mode:
-F, --file <name> Transmit/receive a file
CPU affinity:
-A, --affinity <n[,m]> Pin to CPU core(s)
Authentication (RSA):
--username <name> Username for auth
--rsa-public-key-path <file> RSA public key (client)
--rsa-private-key-path <file> RSA private key (server)
--authorized-users-path <file> Authorized users CSV (server)
--time-skew-threshold <secs> Auth timestamp tolerance
--use-pkcs1-padding Use PKCS#1 instead of OAEP
Misc:
-T, --title <str> Prefix output lines
--extra-data <str> Extra data in JSON output
--get-server-output Get results from server
-d, --debug [<level>] Debug level 1-4
Project Structure
riperf3/ Core library
src/
client.rs Client protocol state machine
server.rs Server protocol state machine
protocol.rs Wire protocol: cookie, state machine, JSON framing
net.rs TCP/UDP socket helpers, socket options (nix + socket2)
stream.rs Data stream I/O, counters, rate limiting, zerocopy
reporter.rs Human-readable and JSON output formatting
auth.rs RSA authentication (OAEP/PKCS#1, credential validation)
units.rs Byte/bit unit formatting
tcp_info.rs TCP_INFO (Linux/FreeBSD) / TCP_CONNECTION_INFO (macOS)
cpu.rs CPU utilization via getrusage
error.rs Error types
utils.rs Constants, KMG parser, DSCP parser
tests/
integration.rs Client-server loopback tests
riperf3-cli/ CLI binary
src/
cli.rs clap argument definitions + wiring tests
main.rs CLI-to-library wiring, CPU affinity, pidfile/logfile
Building and Testing
Status
Feature-complete for the core iperf3 flag set, with full interchange compatibility verified against real iperf3 (current and 3.12) in both directions across all modes. Linux and macOS are fully supported and exercised in native CI; Windows compiles and cross-checks but has a few runtime gaps under active triage; FreeBSD is supported via conditional compilation. Platform-specific flags match iperf3's support matrix (see Platform Support).
See CHANGELOG.md for the 0.6.0 release notes and current known issues — including a daemon-mode (-s -D) bug (#81) and a handful of options that are accepted but not yet fully effective.
Not yet implemented:
- SCTP transport
libiperf-compatible FFI library
Experimental:
--sendmmsg— batched UDP sends viasendmmsg(2). Uses safe Rust only (nix wrapper). Available on Linux and FreeBSD (the send path is also written for NetBSD, but the crate doesn't yet build there — #78). Not part of iperf3 — a riperf3-exclusive optimization exploring safe Rust performance at the kernel boundary.
License
Dual-licensed under MIT and Apache 2.0. Choose whichever you prefer.
Contributing
Contributions welcome. Please open an issue or reach out to @therealevanhenry.