Adds four Criterion.rs benchmark suites to measure hot-path performance
and demonstrate the impact of Sprints 1–3 optimizations:
- benches/protocol.rs — Command & StatusMessage serialize/deserialize
- benches/bandwidth.rs — BandwidthState atomics, budget, interval math
- benches/tcp_rx_scan.rs — memchr SIMD scan vs naive O(n) loop (55× faster
on 256KB buffers with status at end)
- benches/ecsrp5.rs — WCurve::new() heavy math vs cached LazyLock
(~123,000× faster access)
Also adds BENCHMARKS.md with usage instructions and example results.
Visibility changes (bench-only):
- scan_status_message is now pub (was #[cfg(test)] only)
- WCurve and WCURVE are now pub in ecsrp5.rs
dev-dependencies: criterion + pprof (optional flamegraph support)
btest-rs
A Rust reimplementation of the MikroTik Bandwidth Test (btest) protocol. Both server and client modes, fully compatible with MikroTik RouterOS devices.
Free Public Servers
Test your MikroTik link speed right now — no setup, no registration:
| Server | Location | Dashboard |
|---|---|---|
104.225.217.60 |
US | btest.home.kg |
188.245.59.196 |
EU | btest.mikata.ru |
/tool bandwidth-test address=104.225.217.60 user=btest password=btest protocol=tcp direction=both
After the test, visit https://btest.home.kg/dashboard/YOUR_IP to see your results, throughput history, and quota usage. Per-IP limits: 2 GB daily / 8 GB weekly / 24 GB monthly.
Note: TCP is recommended for remote testing. UDP bidirectional through NAT will only show one direction — this is a btest protocol limitation, not specific to btest-rs. See KNOWN_ISSUES.md for details.
Want to run your own public server? Build with cargo build --release --features pro — see Server Pro below.
Features
- Full protocol support -- TCP and UDP data transfer, IPv4 and IPv6
- EC-SRP5 authentication -- modern RouterOS >= 6.43 Curve25519-based auth (server and client)
- MD5 authentication -- legacy RouterOS < 6.43 challenge-response auth
- Multi-connection support -- handles MikroTik's multi-connection UDP mode
- Bidirectional testing -- simultaneous upload and download
- Syslog logging -- send structured events (auth, test start/end) to a remote syslog server
- CSV output -- append machine-readable test results to a CSV file
- CPU usage monitoring -- local and remote CPU shown per interval, warning at >70%
- Timed tests --
--durationflag to automatically stop after N seconds - Quiet mode -- suppress terminal output for scripted/automated use
- NAT traversal -- probe packet to open firewall holes for UDP receive
- Single static binary -- ~2 MB, zero runtime dependencies (musl build)
- Cross-platform -- macOS, Linux (x86_64, ARM64, ARMv7), Windows, Android (Termux), Docker
- Async I/O -- tokio-based, handles many concurrent connections efficiently
Performance
Tested over WiFi 6E (MikroTik RouterOS <-> macOS):
| Mode | Protocol | Speed |
|---|---|---|
| Server RX (1 conn) | UDP | 1.05 Gbps |
| Client TCP download | TCP | 530 Mbps |
| Client TCP upload | TCP | 840 Mbps |
| Client UDP download | UDP | 433 Mbps |
| Client TCP bidirectional | TCP | 264/264 Mbps |
| Server bidirectional | UDP | 280/393 Mbps |
On wired gigabit links, expect line-rate performance in both TCP and UDP modes.
Installation
From source
cargo install --path .
Pre-built binaries
Download from releases or GitHub releases:
# Linux x86_64
curl -L <release-url>/btest-linux-x86_64.tar.gz | tar xz
sudo mv btest /usr/local/bin/
# Raspberry Pi 4/5 (64-bit OS)
curl -L <release-url>/btest-linux-aarch64.tar.gz | tar xz
sudo mv btest /usr/local/bin/
# Raspberry Pi 3/Zero 2 (32-bit OS)
curl -L <release-url>/btest-linux-armv7.tar.gz | tar xz
sudo mv btest /usr/local/bin/
# Windows
# Download btest-windows-x86_64.zip from releases
# Android (Termux, no root needed)
curl -L <release-url>/btest-android-aarch64.tar.gz | tar xz
mv btest $PREFIX/bin/
Raspberry Pi
The static musl binaries run on any Raspberry Pi without dependencies:
# On the Pi — detect architecture and install
ARCH=$(uname -m)
case $ARCH in
aarch64) FILE=btest-linux-aarch64.tar.gz ;;
armv7l) FILE=btest-linux-armv7.tar.gz ;;
*) echo "Unsupported: $ARCH"; exit 1 ;;
esac
curl -LO "https://github.com/manawenuz/btest-rs/releases/latest/download/$FILE"
tar xzf "$FILE"
sudo mv btest /usr/local/bin/
rm "$FILE"
# Run as server
btest -s -a admin -p password --ecsrp5
# Or install as systemd service
curl -LO https://raw.githubusercontent.com/manawenuz/btest-rs/main/scripts/install-service.sh
sudo bash install-service.sh --auth-user admin --auth-pass password
Docker
docker compose up -d
See docs/docker.md for full Docker and deployment options.
systemd service
sudo ./scripts/install-service.sh
sudo ./scripts/install-service.sh --auth-user admin --auth-pass secret
sudo ./scripts/install-service.sh --auth-user admin --auth-pass secret --port 2000
The installer creates a dedicated btest system user, installs a hardened systemd unit, and enables the service.
Quick Start
Server mode
MikroTik devices connect to this server to run bandwidth tests.
# No authentication
btest -s
# MD5 authentication (legacy RouterOS)
btest -s -a admin -p password
# EC-SRP5 authentication (RouterOS >= 6.43)
btest -s -a admin -p password --ecsrp5
# Custom port, verbose logging
btest -s -P 3000 -v
# With syslog and CSV logging
btest -s -a admin -p password --syslog 192.168.1.1:514 --csv /var/log/btest.csv
Client mode
Connect to a MikroTik device's built-in btest server.
# TCP download test
btest -c 192.168.88.1 -r
# TCP upload test
btest -c 192.168.88.1 -t
# Bidirectional TCP
btest -c 192.168.88.1 -t -r
# UDP download with bandwidth limit
btest -c 192.168.88.1 -r -u -b 100M
# With authentication
btest -c 192.168.88.1 -r -a admin -p password
# Timed test (30 seconds), results to CSV
btest -c 192.168.88.1 -r -d 30 --csv results.csv
# Quiet mode (no terminal output)
btest -c 192.168.88.1 -r -d 10 --csv results.csv -q
# UDP through NAT
btest -c 192.168.88.1 -r -u -n
Debug logging
btest -s -v # debug messages
btest -s -vv # trace messages (hex dumps of status exchange)
btest -s -vvv # maximum verbosity
CLI Reference
Usage: btest [OPTIONS]
Options:
-s, --server Run in server mode
-c, --client <HOST> Run in client mode, connect to HOST
-t, --transmit Client transmits data (upload test)
-r, --receive Client receives data (download test)
-u, --udp Use UDP instead of TCP
-b, --bandwidth <BW> Target bandwidth limit (e.g., 100M, 1G, 500K)
-P, --port <PORT> Listen/connect port [default: 2000]
--listen <ADDR> IPv4 listen address [default: 0.0.0.0] (use "none" to disable)
--listen6 [<ADDR>] Enable IPv6 listener [default: ::] (experimental)
-a, --authuser <USER> Authentication username
-p, --authpass <PASS> Authentication password
--ecsrp5 Use EC-SRP5 authentication (RouterOS >= 6.43)
-n, --nat NAT traversal mode (send UDP probe packet)
-d, --duration <SECS> Test duration in seconds (client mode, 0=unlimited) [default: 0]
--csv <FILE> Output results to CSV file (appends if file exists)
-q, --quiet Suppress terminal output (use with --csv)
--syslog <HOST:PORT> Send logs to remote syslog server (UDP, RFC 3164)
-v, --verbose Increase log verbosity (-v, -vv, -vvv)
-h, --help Show help
-V, --version Show version
MikroTik Configuration
Enable btest server on MikroTik (for client mode)
/tool/bandwidth-server set enabled=yes
Run btest from MikroTik (connecting to our server)
/tool/bandwidth-test address=<server-ip> direction=both protocol=udp \
user=admin password=password
Protocol
The MikroTik btest protocol uses:
- TCP port 2000 for control (handshake, authentication, status exchange)
- UDP ports 2001+ for data transfer (server side)
- UDP ports 2257+ for data transfer (client side, offset +256)
- MD5 double-hash challenge-response authentication (RouterOS < 6.43)
- EC-SRP5 Curve25519 Weierstrass authentication (RouterOS >= 6.43)
- 1-second status interval with dynamic speed adjustment
See docs/protocol.md for the full wire-format specification.
Authentication
Both legacy and modern MikroTik authentication schemes are supported:
| Scheme | RouterOS Version | Flag |
|---|---|---|
| None | Any | (no flags) |
| MD5 challenge-response | < 6.43 | -a USER -p PASS |
| EC-SRP5 (Curve25519) | >= 6.43 | -a USER -p PASS --ecsrp5 |
In server mode, --ecsrp5 advertises EC-SRP5 to connecting clients. Without it, MD5 is advertised. In client mode, the authentication type is auto-detected from the server's response.
Known Issues
See KNOWN_ISSUES.md for the full list including:
- IPv6 UDP on macOS — server TX hits ENOBUFS, use IPv4 or deploy on Linux
- macOS UDP send buffer — first 2-3 seconds unreliable on unlimited speed tests
- Windows binaries — cross-compiled but untested
- IPv6 UDP on Linux — untested, likely works fine
Contributions and bug reports welcome:
Documentation
- User Guide -- complete CLI reference with examples for every mode
- Architecture -- module structure, threading model, design decisions
- Protocol Specification -- wire format, authentication, status exchange
- Docker & Deployment -- Docker, Docker Compose, systemd, firewall rules
- EC-SRP5 Research -- reverse-engineering notes and cryptographic details
- Man Page -- Unix manual page (install to
/usr/share/man/man1/)
Testing
cargo test # Unit + integration tests
scripts/test-local.sh # Loopback self-test
scripts/test-mikrotik.sh <ip> # Test against MikroTik device
scripts/test-docker.sh # Docker container test
Server Pro
An optional superset of the standard server with multi-user support, quotas, and a web dashboard. Build with --features pro:
cargo build --release --features pro --bin btest-server-pro
Features:
- SQLite user database — add/remove users, per-user quotas
- Per-IP bandwidth quotas — daily, weekly, monthly limits with inline byte budget enforcement
- Web dashboard — session history, throughput stats, quota progress bars, JSON export
- TCP multi-connection — handles MikroTik's default 20-connection mode
- MD5 auth against DB — proper challenge-response verification
# Create a user and start the server
btest-server-pro --users-db users.db useradd btest btest
btest-server-pro --users-db users.db --ip-daily 2147483648 --ip-weekly 8589934592 --web-port 8080
The pro features are completely optional and don't affect the standard btest binary.
Credits
- btest-opensource by Alex Samorukov -- original C implementation and protocol reverse-engineering. Licensed under MIT.
- Margin Research -- EC-SRP5 authentication reverse-engineering (Curve25519 Weierstrass, SRP key exchange). Licensed under Apache 2.0.
- MikroTik -- creator of the bandwidth test protocol and RouterOS.
License
MIT License -- see LICENSE.
This project is derived from btest-opensource (MIT License, Copyright 2016 Alex Samorukov). The EC-SRP5 implementation is based on research by Margin Research (Apache License 2.0). Original license and copyright notices are preserved as required.