riperf3
A ground-up Rust implementation of iperf3, the standard network performance measurement tool. Wire-compatible with ESNet's iperf3 — a riperf3 client talks to an iperf3 server and vice versa.
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.
- 269 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 — statistical parity single-stream (~75 Gbps); a few percent ahead at
-P 8. - UDP — significantly faster in every cell (~+10–18%), 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 compiles and runs on Linux, macOS, FreeBSD, and Windows. Platform-specific features use safe Rust wrappers where available, with graceful degradation or clear error messages on unsupported platforms.
| 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.
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. Full interchange compatibility verified across all modes. Full platform parity across Linux, macOS, FreeBSD, and Windows.
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, FreeBSD, NetBSD. 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.