XFR(1)

NAME
xfr - modern network bandwidth testing with TUI

SYNOPSIS
xfr [OPTIONS] HOST
xfr serve [OPTIONS]
xfr diff BASELINE CURRENT [OPTIONS]
xfr discover [OPTIONS]

DESCRIPTION
xfr is a fast, modern network bandwidth testing tool with a terminal user interface. It is designed as a replacement for iperf with additional features like live TUI, multi-client server support, QUIC transport, and result comparison.

CLIENT OPTIONS

-p, --port PORT
    Server port (default: 5201). Environment: XFR_PORT

-t, --time DURATION
    Test duration (default: 10s). Supports units: s, m, h. Environment: XFR_DURATION

-n, --bytes COUNT
    Transfer this many bytes, then stop, instead of running for a fixed time. Binary suffixes: K=KiB, M=MiB, G=GiB (for example -n 1G). The count is the total across all streams, not per stream. Without an explicit -t the test runs until the transfer completes; with one, -t becomes an upper bound. Cannot be combined with --probe-mtu. Requires a server advertising the byte_budget_v1 capability. Environment: XFR_BYTES

-u ,  --udp
    Use UDP instead of TCP

-Q ,  --quic
    Use QUIC transport (encrypted, multiplexed streams over UDP)

-b, --bitrate RATE
    Target bitrate for UDP mode (e.g., 1G, 100M, 10K)

-P, --parallel N
    Number of parallel streams (default: 1)

-R ,  --reverse
    Reverse direction (server sends to client, i.e., download test)

--bidir
    Bidirectional test (both upload and download)

--json
    Output results as JSON

--json-stream
    JSON streaming output (one JSON object per line per interval)

--csv
    CSV output format

-q ,  --quiet
    Quiet mode - suppress interval output, show only summary

-o, --output FILE
    Save results to file

--no-tui
    Disable terminal UI, use plain text output

--no-update-check
    Disable the background check for a newer release. Also honored via the DO_NOT_TRACK or XFR_NO_UPDATE_CHECK environment variables.

--theme THEME
    Color theme: default, kawaii, cyber, dracula, monochrome, matrix, nord, gruvbox, catppuccin, tokyo_night, solarized. The monochrome theme (alias: mono) is the high-visibility option for glare and monochrome displays: it renders in the terminal's own default colors at maximum contrast, and works on light and dark backgrounds alike. Loss severity in the throughput graph is always also encoded without color (underline for light loss, reverse video for heavy loss).

-i, --interval SECS
    Report interval in seconds (default: 1.0)

--omit N
    Omit first N seconds from interval output (TCP ramp-up)

--tcp-nodelay
    Disable Nagle algorithm (TCP_NODELAY)

--window SIZE
    TCP window size (e.g., 512K, 1M, 4M)

--congestion ALGO
    TCP congestion control algorithm (e.g., cubic, bbr, reno). Applied on both client and server sockets via setsockopt(TCP_CONGESTION). Requires kernel support for the selected algorithm.

--timestamp-format FORMAT
    Timestamp format: relative (default), iso8601, unix

--log-file PATH
    Log file path (e.g., ~/.config/xfr/xfr.log)

--log-level LEVEL
    Log level: error, warn, info, debug, trace

--psk KEY
    Pre-shared key for server authentication. Environment: XFR_PSK. Values supplied via --psk or XFR_PSK may be visible through process metadata; prefer --psk-file.

--psk-file FILE
    Read PSK from file

-4 ,  --ipv4
    Force IPv4 only

-6 ,  --ipv6
    Force IPv6 only

--bind ADDR
    Local address to bind to (e.g., 192.168.1.100 or ::1)

--cport PORT
    Client source port for firewall traversal (UDP/QUIC/TCP data streams)

--dscp VALUE
    Set DSCP/TOS marking on sockets for QoS policy testing. Accepts numeric values (0-255) or standard DSCP names: EF, AF11-AF43, CS0-CS7, VA. Applied to both client-side and server-side TCP/UDP sockets (the value is propagated in the TestStart message) so download and bidirectional tests mark traffic in both directions. QUIC manages its own socket and ignores this flag; non-Unix platforms warn before the test starts.

--mptcp
    Use MPTCP (Multi-Path TCP, Linux 5.6+)

--random
    Use random payload data (default for TCP/UDP client-sent traffic)

--zeros
    Use zero-filled payload data instead of random bytes

-Z ,  --zerocopy
    Zero-copy TCP sends via sendfile(2), like iperf3 -Z (Linux only; lowers sender CPU overhead). On by default for TCP since v0.9.17; passing -Z explicitly warns when zero-copy cannot take effect instead of falling back silently. Forwarded to servers that support it for -R/--bidir

--no-zerocopy
    Disable zero-copy TCP sends (use regular buffered writes)

--probe-mtu
    Probe the path MTU instead of running a throughput test: walks UDP payload sizes with the don't-fragment flag set and reports the largest size surviving in each direction. Implies UDP; requires a server with mtu_probe_v1 support (xfr >= 0.9.17)

--connect-timeout DURATION
    Fail if the control connection (TCP connect or QUIC handshake) takes longer than this (e.g. 5s). Without it, a dead or filtered server is bounded only by OS defaults

--completions SHELL
    Generate shell completions: bash, zsh, fish, powershell, elvish

SERVER OPTIONS

-p, --port PORT
    Listen port (default: 5201). Environment: XFR_PORT

--one-off
    Exit after a single test

--tui
    Enable TUI dashboard showing active tests

--max-duration DURATION
    Maximum test duration (server-side limit)

--push-gateway URL
    Prometheus push gateway URL (e.g., http://pushgateway:9091)

--log-file PATH
    Log file path

--log-level LEVEL
    Log level: error, warn, info, debug, trace

--psk KEY
    Pre-shared key for authentication. Environment: XFR_PSK. Values supplied via --psk or XFR_PSK may be visible through process metadata; prefer --psk-file.

--psk-file FILE
    Read PSK from file

--preset NAME
    Use a named server preset from the config file. Preset allowed_clients entries, if present, are enforced as an additional allowlist together with the normal ACL. Preset max_duration_secs, if present, is used only when --max-duration is not also supplied on the command line. The bandwidth_limit field is reserved for future use and is not enforced today.

--rate-limit N
    Max concurrent tests per IP

--rate-limit-window DURATION
    Rate limit time window (default: 60s)

--allow IP/SUBNET
    Allow IP or subnet (can be repeated)

--deny IP/SUBNET
    Deny IP or subnet (can be repeated)

--acl-file FILE
    Load ACL rules from file

-B, --bind IP
    Bind to specific address (e.g., 192.168.1.1, ::1). Rejects unspecified addresses; use -4/-6 instead to control address family. Validates against -4/-6 flags.

--no-mdns
    Disable mDNS service registration. By default the server registers itself via mDNS for automatic discovery by xfr discover. Use this flag when another service already uses mDNS or when running in environments where multicast is unwanted.

-4 ,  --ipv4
    Force IPv4 only

-6 ,  --ipv6
    Force IPv6 only

DIFF OPTIONS

--threshold PERCENT
    Regression threshold percentage (default: 5)

DISCOVER OPTIONS

--timeout DURATION
    Discovery timeout (default: 5s)

CONFIGURATION
xfr reads configuration from ~/.config/xfr/config.toml (Linux/macOS) or %APPDATA%\xfr\config.toml (Windows) if present. CLI arguments override config file values. Environment variables override config file.

Example config:
    [client]
    duration_secs = 30
    parallel_streams = 4
    bitrate = "100M"
    congestion = "bbr"
    dscp = "EF"
    interval_secs = 1.0
    bind = "192.168.1.100"
    cport = 5202
    theme = "dracula"
    [server]
    port = 5201
    psk = "secret"
    rate_limit = 5
    no_mdns = false
    allow = ["192.168.0.0/16"]

These client transport and output configuration values are defaults: an explicit CLI value takes precedence. The bitrate value accepts the same 100M/1G syntax as --bitrate, and dscp accepts the same names and numeric values as --dscp.

ENVIRONMENT

XFR_PORT
    Server/client port

NO_COLOR
    When set and no theme is chosen via --theme, config, or a saved preference, the monochrome theme is used (https://no-color.org). The choice is not persisted.

XFR_DURATION
    Test duration

XFR_BYTES
    Byte count for a fixed-size transfer (see -n)

XFR_PSK
    Pre-shared key

XFR_PUSH_GATEWAY
    Prometheus push gateway URL

XFR_LOG_FILE
    Log file path

XFR_LOG_LEVEL
    Log level

XFR_TIMESTAMP_FORMAT
    Timestamp format

DO_NOT_TRACK
    Set to a non-empty, non-zero value to disable the update check (cross-tool standard)

XFR_NO_UPDATE_CHECK
    Set to a non-empty, non-zero value to disable the update check

EXAMPLES

xfr 192.168.1.1
    Run a 10-second TCP upload test

xfr 192.168.1.1 -t 30s -P 4
    30-second test with 4 parallel streams

xfr 192.168.1.1 -R
    Download test (server sends to client)

xfr 192.168.1.1 -n 1G
    Transfer exactly 1 GiB and stop, however long that takes - comparable across links in a way a timed test is not

xfr 192.168.1.1 -u -b 1G
    UDP test at 1 Gbps

xfr 192.168.1.1 --quic
    QUIC encrypted test

xfr 192.168.1.1 --json --no-tui
    JSON output for scripting

xfr 192.168.1.1 --zeros
    Use zero-filled payloads for compression/dedup testing

xfr serve
    Start server on default port 5201

xfr serve --tui
    Start server with live dashboard

xfr serve --psk secret --rate-limit 2
    Authenticated server with rate limiting

xfr serve --allow 192.168.0.0/16 --deny 0.0.0.0/0
    Server with IP access control

xfr diff baseline.json current.json --threshold 5
    Compare results, fail if throughput drops more than 5%

xfr discover
    Find xfr servers on the local network via mDNS

PROTOCOL

xfr servers and clients using protocol v1.1 exchange capability strings during the Hello handshake (protocol v1.1). A feature activates only when both peers advertise its capability; older peers fall back to prior behavior, so adding a capability is wire-additive.

tcp Peer supports TCP tests.

udp Peer supports UDP tests.

quic
    Peer supports QUIC tests.

multistream
    Peer supports multiple parallel streams.

single_port_tcp
    All TCP data streams multiplex over the single control port. Servers fall back to per-stream ephemeral ports for clients that don't advertise this.

pause_resume
    The p key in the TUI (or a control message in scripted mode) pauses and resumes the test mid-run.

udp_feedback_v1
    Server emits 36-byte cumulative (packets_received, packets_lost) feedback packets back to the client at 2 Hz on the same UDP data socket, sidestepping the TCP control channel for live UDP-loss visibility under upload-mode saturation (issue #70). Available v0.9.14+. Capability negotiation gates emission so older clients never see a packet they don't understand.

zerocopy_v1
    Server honors a zero-copy request for its own sends in -R/--bidir TCP tests (sendfile-based, issue #33). Available v0.9.16+.

mtu_probe_v1
    Server answers path-MTU probe packets (ack + same-size echo) for --probe-mtu (issue #64). Hard requirement: the client refuses to probe servers without it. Available v0.9.17+.

single_port_udp_v1
    All UDP stream data flows to the server's main port via per-stream connected sockets negotiated with a token-bearing hello, instead of per-stream ephemeral server ports (issue #63). Advertised only when a startup self-test proves the kernel's connected-socket routing; servers fall back to ephemeral ports for older clients or unsupported platforms. Available v0.9.18+.

SIGNALS

SIGINT (Ctrl+C)
    Gracefully cancels the running test: signals the server over the control channel, waits briefly for the final result, then displays the accumulated test summary. Works in both plain text and TUI modes. A second Ctrl+C during the cancel window force-exits immediately.

EXIT STATUS

0   Success

1   Error or regression detected (with diff command)

2   Invalid arguments

3   Server rejected test (auth, rate limit, ACL)

130 Test was interrupted by SIGINT before server could report a full result (partial summary printed if any data was collected)

FILES

~/.config/xfr/config.toml
    User configuration file

~/.config/xfr/prefs.toml
    User preferences (theme)

SEE ALSO
iperf3(1)

BUGS
Report bugs at: https://github.com/lance0/xfr/issues

AUTHOR
lance0