xfr
A fast, modern network bandwidth testing tool with TUI. Built in Rust as an iperf replacement.
Quick Start
# Server
# Client (in another terminal or machine)
Features
- Live TUI with real-time throughput graphs and per-stream stats
- Server dashboard -
xfr serve --tuifor monitoring active tests - Multi-client server - handle multiple simultaneous tests
- TCP and UDP with configurable bitrate and parallel streams
- Bidirectional testing - measure upload and download simultaneously
- Multiple output formats - plain text, JSON, JSON streaming, CSV
- Result comparison -
xfr diffto detect performance regressions - LAN discovery - find xfr servers with mDNS (
xfr discover) - Prometheus metrics - export stats for monitoring dashboards
- Config file - save defaults in
~/.config/xfr/config.toml - Environment variables -
XFR_PORT,XFR_DURATIONoverrides
vs iperf3
| Feature | iperf3 | xfr |
|---|---|---|
| Live TUI | No | Yes (client & server) |
| Multi-client server | No | Yes |
| Output formats | Text/JSON | Text/JSON/CSV/Prometheus |
| Compare runs | No | xfr diff |
| LAN discovery | No | xfr discover |
| Config file | No | Yes |
Installation
From crates.io (Recommended)
From Source
&&
With Optional Features
# Prometheus metrics support
# io_uring backend (Linux only, requires kernel 5.10+)
# All features
Usage
Server
Client
UDP Mode
Output Formats
Interval Control
Compare Results
Discovery
Keybindings (Client TUI)
| Key | Action |
|---|---|
q |
Quit (cancels test) |
p |
Pause/Resume display |
t |
Cycle color theme |
? / F1 |
Help |
j |
Print JSON result |
Keybindings (Server TUI)
| Key | Action |
|---|---|
q |
Quit server |
? / F1 |
Help |
Esc |
Close help |
Themes
xfr includes 11 built-in color themes. Select with --theme or press t during a test:
Available themes: default, kawaii, cyber, dracula, monochrome, matrix, nord, gruvbox, catppuccin, tokyo_night, solarized
Your theme preference is auto-saved to ~/.config/xfr/prefs.toml.
Configuration
xfr reads defaults from ~/.config/xfr/config.toml:
[]
= 10
= 1
= false
= false
= false
= "default" # or dracula, catppuccin, nord, matrix, etc.
= "relative" # or "iso8601", "unix"
= "~/.config/xfr/xfr.log"
= "info"
[]
= 5201
= "http://pushgateway:9091"
= "~/.config/xfr/xfr-server.log"
= "info"
= "my-secret-key"
= 5
= ["192.168.0.0/16", "10.0.0.0/8"]
= "/var/log/xfr-audit.log"
= "json"
Environment variables override config file:
Prometheus Metrics
Enable with --features prometheus:
Metrics available at http://localhost:9090/metrics:
xfr_bytes_total- Total bytes transferredxfr_throughput_mbps- Current throughputxfr_active_tests- Number of active testsxfr_retransmits_total- TCP retransmissions
See examples/grafana-dashboard.json for a sample Grafana dashboard.
CLI Reference
| Flag | Short | Default | Description |
|---|---|---|---|
--port |
-p |
5201 | Server/client port |
--time |
-t |
10s | Test duration |
--udp |
-u |
false | UDP mode |
--bitrate |
-b |
unlimited | Target bitrate (e.g., 1G, 100M) |
--parallel |
-P |
1 | Parallel streams |
--reverse |
-R |
false | Reverse direction (download) |
--bidir |
false | Bidirectional test | |
--json |
false | JSON output | |
--json-stream |
false | JSON per interval | |
--csv |
false | CSV output | |
--quiet |
-q |
false | Summary only |
--interval |
-i |
1.0 | Report interval (seconds) |
--omit |
0 | Omit first N seconds | |
--output |
-o |
stdout | Output file |
--no-tui |
false | Disable TUI | |
--theme |
default | Color theme (dracula, nord, matrix, etc.) | |
--tcp-nodelay |
false | Disable Nagle algorithm | |
--window |
OS default | TCP window size | |
--timestamp-format |
relative | Timestamp format (relative, iso8601, unix) | |
--log-file |
none | Log file path (e.g., ~/.config/xfr/xfr.log) | |
--log-level |
info | Log level (error, warn, info, debug, trace) | |
--push-gateway |
none | Prometheus Push Gateway URL (server only) | |
--psk |
none | Pre-shared key for authentication (server) | |
--psk-file |
none | Read PSK from file (server) | |
--tls |
false | Enable TLS encryption (server) | |
--tls-cert |
none | TLS certificate file (server) | |
--tls-key |
none | TLS private key file (server) | |
--rate-limit |
none | Max concurrent tests per IP (server) | |
--allow |
none | Allow IP/subnet, repeatable (server) | |
--deny |
none | Deny IP/subnet, repeatable (server) | |
--audit-log |
none | Audit log file path (server) | |
--audit-format |
json | Audit format: json or text (server) | |
--tui |
false | Enable live dashboard (server) |
Platform Support
| Platform | Status |
|---|---|
| Linux | Full support, TCP_INFO stats |
| macOS | Full support, TCP_INFO stats |
| Windows | Via WSL2 |
Troubleshooting
Permission denied on port 5201
Use a port above 1024 or run with elevated privileges:
Connection refused
Ensure the server is running and the port is not blocked by a firewall.
Low throughput
- Try multiple parallel streams:
-P 4 - Disable Nagle's algorithm:
--tcp-nodelay - Increase TCP window size:
--window 4M
UDP packet loss
- Reduce bitrate:
-b 500M - Check for network congestion or firewall issues
Documentation
- Changelog - Release history
- Roadmap - Planned features
- Contributing - Development guidelines
License
Licensed under either of Apache License, Version 2.0 or MIT license at your option.