Litmus Documentation

Server Setup Guide

Run a permanent Litmus test server for your network. Applies to Litmus v1.1.1 — binaries are self-contained .NET 8 single files, no runtime install required. The same binary is also the client.

PlatformBinaryServer modes
Linux x64litmusInteractive TUI (-s), headless (-s --no-tui), systemd service
Windows x64Litmus.exeServer mode tab in the desktop app, optional Auto-Start

Default port: 7201 (TCP + UDP on the same number).

Linux Server

Recommended for permanent servers — headless mode, systemd integration, and BBR congestion control.

Quick start

Grab the Linux binary from the downloads section (or wget it directly as below) and drop it in /opt/litmus:

mkdir -p /opt/litmus && cd /opt/litmus
# download the Linux binary from bobpopcorn.com/tools/litmus, then:
wget https://bobpopcorn.com/tools/litmus-x64 -O litmus
chmod +x litmus
./litmus -s                 # interactive 3-pane TUI (server info / connections / chat)
./litmus -s --no-tui        # plain text output (for logging pipelines / no TTY)
./litmus -v                 # verify version

Useful server flags

FlagPurpose
-p, --port <n>Control port (default 7201)
-B, --bind <ip>Bind a specific local interface
--port-range 10000-10100Constrain data connections to a fixed port range (required behind strict firewalls — without it data ports are OS-assigned ephemerals)
--log <file-or-dir>Write a server log (directory = auto-named file)
--no-tuiPlain text output, required for systemd

Firewall

Each test uses the control port plus one data connection per stream on a separate port. Without --port-range, data ports are random ephemerals and inbound rules can't be written for them — so on firewalled hosts always run with a range and open it:

sudo ufw allow 7201/tcp
sudo ufw allow 7201/udp
sudo ufw allow 10000:10100/tcp    # match your --port-range
sudo ufw allow 10000:10100/udp

LAN-only ports — do not expose on public hosts

UDP 45678 (multicast peer discovery/chat, group 239.255.69.67) and TCP 45679 (direct chat) bind all interfaces — block them at the firewall on internet-facing servers.

Kernel tuning (strongly recommended)

Stock Linux uses CUBIC congestion control and 4 MB buffer ceilings. On high-latency or lossy paths (satellite, intercontinental, congested peering) this caps each TCP stream far below the line rate — a 75 ms path with light loss can sit at 30–40 Mbps while the link carries 10× that. BBR + bigger autotuning ceilings fix it:

# BBR is built into kernels >= 4.9
sudo modprobe tcp_bbr
echo tcp_bbr | sudo tee /etc/modules-load.d/bbr.conf

sudo tee /etc/sysctl.d/90-litmus-tcp.conf <<'EOF'
# BBR: rate-based congestion control - tolerant of loss bursts that collapse CUBIC
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr

# Autotuning ceilings: high-bandwidth/high-RTT paths need windows beyond the 4MB stock max
# (300 Mbps @ 200 ms bufferbloated RTT needs ~8 MB in flight)
net.ipv4.tcp_rmem = 4096 131072 67108864
net.ipv4.tcp_wmem = 4096 16384 67108864

# Ceilings for explicitly pinned buffers (Litmus --buffer option); stock cap is ~208 KB
net.core.rmem_max = 67108864
net.core.wmem_max = 67108864
EOF
sudo sysctl --system

# verify
sysctl net.ipv4.tcp_congestion_control net.core.default_qdisc   # expect: bbr / fq
  • Congestion control is assigned per-socket at creation — restart a running Litmus server after changing it. Existing SSH sessions keep their old algorithm; that's normal.
  • BBR on the server governs download tests (server → client). Upload tests are governed by the client OS.
  • Rollback: sudo rm /etc/sysctl.d/90-litmus-tcp.conf && sudo reboot.
  • Leave Litmus's --buffer at 0 (OS auto-tuned). Pinning a size disables receive-window auto-tuning and caps each stream at roughly size ÷ RTT.

Run as a systemd service

/etc/systemd/system/litmus.service
# /etc/systemd/system/litmus.service
[Unit]
Description=Litmus network test server
After=network-online.target
Wants=network-online.target

[Service]
ExecStart=/opt/litmus/litmus -s --no-tui --port-range 10000-10100 --log /var/log/litmus.log
Restart=on-failure
RestartSec=5
User=litmus
NoNewPrivileges=true
StateDirectory=litmus
Environment=DOTNET_BUNDLE_EXTRACT_BASE_DIR=/var/lib/litmus

[Install]
WantedBy=multi-user.target
sudo useradd -r -s /usr/sbin/nologin litmus
sudo touch /var/log/litmus.log && sudo chown litmus:litmus /var/log/litmus.log
sudo systemctl daemon-reload
sudo systemctl enable --now litmus
systemctl status litmus

Security hardening for public servers

  • Use SSH key auth only (PasswordAuthentication no in /etc/ssh/sshd_config) — public test servers attract constant brute-force scanners.
  • Firewall UDP 45678 / TCP 45679 (chat/discovery) from the internet.
  • Anyone who can reach port 7201 can run tests that saturate your uplink. Restrict source IPs at the firewall if the server isn't meant to be public.

Verifying server-side performance

While a download test runs, on the server:

watch -n1 "ss -ti dst <client-ip>"

Read three things per data connection:

  • The congestion algorithm tag — expect bbr after kernel tuning.
  • rwnd_limited — a high % means the client's receive window is the ceiling.
  • rtt vs minrtt — a large gap under load = bufferbloat on the path.

Windows Server

The Windows build is the desktop app (Litmus.exe); it contains the full server in the Server tab.

  1. 1Download Litmus.exe, run it, switch to Server mode, set the port (default 7201), Start.
  2. 2Enable Auto-Start in server settings to begin listening on launch.
  3. 3Add firewall rules (run as Administrator):
netsh advfirewall firewall add rule name="Litmus TCP" dir=in action=allow protocol=TCP localport=7201
netsh advfirewall firewall add rule name="Litmus UDP" dir=in action=allow protocol=UDP localport=7201

Windows TCP tuning

Defaults are usually fine. Confirm receive autotuning is on (it is unless someone disabled it):

netsh interface tcp show global    # "Receive Window Auto-Tuning Level" should be: normal
netsh interface tcp set global autotuninglevel=normal   # restore if not

No production BBR on Windows

Windows sends with CUBIC; there is no production BBR. Windows 11 has an experimental BBR2 (netsh int tcp set supplemental Template=Internet CongestionProvider=BBR2) — known to break some apps; revert with CongestionProvider=CUBIC. For serious server duty on hard paths, prefer a Linux host.

Port Reference

PortProtocolPurposeExpose publicly?
7201TCPControl channel: handshake, ping/latency, statsYes (that's the service)
7201UDPUDP test trafficYes
OS-assigned or --port-rangeTCP/UDPData connections (one per stream)Yes — use --port-range
45678UDPMulticast peer discovery + LAN chat (239.255.69.67)No
45679TCPDirect peer chat (desktop app)No

Reading Results on Hard Paths

Expectation setting for satellite, long-haul, and lossy links.

  • Single-stream TCP on high-RTT/lossy links (satellite, long-haul) reads far below link capacity — that is TCP physics, not a server fault. Use -P 4-P 8 parallel streams and BBR on the server.
  • The UDP test with a bandwidth cap (--udp -b 300) measures raw path capacity and loss with no TCP dynamics — use it to establish the ceiling, then compare TCP against it.
  • Latency rising under load (visible in test results) is bufferbloat on the path, not server overload.