iPerf is the tool network engineers reach for when someone asks the oldest question in the business: how fast is this network, really? It measures the maximum achievable throughput between two points you control, over TCP or UDP, and reports not just a speed but the evidence behind it - retransmits, congestion window behavior, jitter, and packet loss. Interface counters tell you what a link did; iPerf tells you what a path can do right now.
This guide is the hub of our iPerf cluster and everything in it is grounded in a live lab: a Linux client, two Cisco IOS XE routers running OSPF, and an iperf3 server, with impairments (latency, loss, bandwidth caps) injected on the WAN link so you can see exactly how each failure mode looks in real output. It covers what iPerf solves, how the client-server model works, the essential flags, a minimum viable test setup, TCP versus UDP methodology, hardening a test server, and the troubleshooting fingerprints that turn iPerf from a speedometer into a diagnostic instrument. Deep dives on each topic are linked throughout and indexed in reading order near the end.
What iPerf Solves
Three questions come up constantly and iPerf answers all of them with measurements instead of guesses. First, capacity: what will this path actually carry, as opposed to what the circuit order says? Second, verification: after a change (new circuit, QoS policy, VPN tunnel, firewall), did throughput improve, regress, or stay put? Third, diagnosis: when an application is slow, is the network dropping packets, is latency strangling the TCP window, or is the network fine and the application the problem?
What makes iPerf better than a browser speed test for these jobs is control. You choose both endpoints, so you measure the path you care about rather than the path to someone's CDN. You choose the protocol, direction, duration, and rate. And you can run it anywhere: bare metal, VMs, containers, a Raspberry Pi taped inside a wiring closet.
How iPerf Works
iPerf is a client-server tool. The server (iperf3 -s) listens on port 5201 and waits. The client (iperf3 -c <server>) opens a control connection, negotiates test parameters, then pushes traffic for 10 seconds by default. In TCP mode the client sends as fast as TCP congestion control allows, so the result converges on the path's sustainable capacity. In UDP mode the client sends at exactly the rate you request and the server counts what survives, exposing loss and jitter that TCP hides inside retransmissions.
Both sides report at the end, and the distinction between them is the single most important thing to understand about iPerf output: the sender line is what was handed to the network, the receiver line is what arrived. On a clean path they match. When they diverge, the gap is your problem, quantified. The annotated walkthrough of every output column lives in how to use iPerf3.
The Flags That Do the Work
-s / -c hostServer mode / client mode pointed at the server. The only two flags a first test needs.-t 30Test duration in seconds. 30 to 60 gives steadier numbers than the 10-second default.-RReverse the direction: server sends. Always test both ways; asymmetry is diagnostic.-u -b 20MUDP at a fixed rate. Reports jitter and loss - the real-time traffic view.-P 4Parallel streams. Separates per-flow limits from shared limits in one comparison.-w 512KSocket buffer / TCP window size. The lever behind the bandwidth-delay product.-p 5202Alternate port, on both server and client. Also the key to concurrent tests.-S 0xB8Set the ToS/DSCP byte (0xB8 = EF) to test how QoS treats marked traffic.-JFull JSON output for scripts, dashboards, and CI checks.-D --logfile fServer as a background daemon with a log. The persistent-server pattern.Minimum Viable iPerf: A Real Routed Test
Here is the whole workflow on our lab topology - client at 10.0.10.10, server at 10.0.20.10, two OSPF-routed IOS XE hops between them. Server first:
server:~$ iperf3 -s -D --logfile /var/log/iperf3.log
server:~$ ss -ltn | grep 5201
LISTEN 0 4096 *:5201 *:*Then confirm reachability and run the test from the client:
client:~$ ping -c 3 10.0.20.10
rtt min/avg/max/mdev = 2.948/3.611/5.239/0.833 ms
client:~$ iperf3 -c 10.0.20.10
Connecting to host 10.0.20.10, port 5201
[ 5] local 10.0.10.10 port 39290 connected to 10.0.20.10 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 4.12 MBytes 34.6 Mbits/sec 7 72.1 KBytes
[ 5] 5.00-6.00 sec 4.38 MBytes 36.7 Mbits/sec 0 93.3 KBytes
[ 5] 9.00-10.01 sec 4.00 MBytes 33.3 Mbits/sec 10 39.6 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.01 sec 41.2 MBytes 34.6 Mbits/sec 83 sender
[ 5] 0.00-10.01 sec 40.9 MBytes 34.2 Mbits/sec receiver
iperf Done.Then the reverse direction with -R (32.5 Mbit/sec on this path - close enough to call symmetric). That is a complete baseline: throughput both ways, RTT from ping, and a retransmit count for context. Record it somewhere; every future "is the network slow?" conversation starts from this number. You can even watch the test from the router's perspective mid-run:
R1# show interfaces Ethernet0/1 | include rate
5 minute input rate 184000 bits/sec, 206 packets/sec
5 minute output rate 5747000 bits/sec, 471 packets/secTCP or UDP: Choosing the Right Test
Answers "how much can this path sustain?" TCP adapts to the path, so the result is the practical ceiling for file transfers, backups, and anything bulk. Watch Retr and Cwnd for the story behind the number.
Answers "what happens to traffic that cannot slow down?" Fixed-rate send, with jitter and loss measured at the receiver. The right model for voice, video, and finding loss that TCP hides. See iPerf3 UDP testing.
A useful discipline: run TCP first to find the ceiling, then UDP at 50 to 80 percent of that ceiling to check quality under the ceiling. On our lab path the TCP ceiling is about 35 Mbit/sec; a 10 Mbit/sec UDP run came back 0% loss and 0.206 ms jitter, while deliberately over-driving at 100 Mbit/sec produced 29% loss at the receiver - and a sender line that still claimed a flawless 100 Mbit/sec, which is why you always read the receiver line.
Latency, Windows, and Why Fast Links Test Slow
A single TCP flow can never move more than its window size per round trip. That ceiling (window / RTT) is invisible on a LAN and brutal on a WAN. We injected 50 ms of one-way latency on the lab WAN link and watched a 34.6 Mbit/sec path drop to 26.3 with autotuning, then to 5.77 Mbit/sec with a forced 64 KB window - and recover to 21.2 Mbit/sec with four parallel streams at that same tiny window. The arithmetic, the full captures, and the diagnostic recipe are in parallel streams and TCP window size. If your transfers are slow on long-haul paths while iPerf with defaults is fast, this is almost always the mechanism.
Running Test Servers Properly
An iPerf3 server process handles one test at a time; a second client gets "the server is busy running a test. try again later." For a shared test box, run one daemon per port (-p 5202, 5203, and so on) and give each a --logfile so you keep a server-side record of every test. For anything permanent, put it under systemd. All patterns, plus the firewall rules (open your chosen port for both TCP and UDP), are in running an iPerf3 server.
Units, Overhead, and What Numbers to Expect
More iPerf "problems" are unit confusion than network faults. iPerf reports in bits per second by default (lowercase m in -f m); file managers report bytes (a factor of eight). A transfer showing 40 MBytes/sec is 320 Mbits/sec - a perfectly healthy number on a gigabit path that a hurried reader can mistake for one third of expectations. Use -f M or -f m deliberately and quote units in your notes.
Then there is overhead. A "gigabit" Ethernet link never yields 1,000 Mbit/sec of iPerf goodput: Ethernet framing, IP and TCP headers, and interframe gaps consume roughly 5 to 6 percent, so about 940 Mbit/sec of TCP payload is the practical ceiling on a clean 1G path (roughly 9.4 Gbit/sec on 10G). Through a VPN, subtract the tunnel encapsulation on top - IPsec or WireGuard overhead typically lands the ceiling somewhere between 850 and 920 Mbit/sec on the same link, before any crypto CPU limits. If your test lands within a few percent of these numbers, stop tuning: you are done.
Also expect virtualization to lie a little. Tests between VMs on the same hypervisor can exceed physical NIC speeds (traffic never leaves memory), and container networking layers can shave real percentages off. Measure the path your traffic will actually take, endpoints included - our lab numbers throughout this cluster run at IOL virtual-router speeds precisely because the routers, not the endpoints, are the constraint being measured.
Automating iPerf Tests
The moment a test matters, script it. With -J the entire result is machine-readable JSON, and one jq expression extracts the number you care about:
iperf3 -c 10.0.20.10 -t 30 -J | jq '.end.sum_received.bits_per_second'Wrap that in cron with a threshold check and you have a poor man's throughput monitor; feed it to your observability stack and you have circuit-validation history. Two habits make scheduled tests trustworthy: use -1 one-shot servers or dedicated ports so runs never collide (a busy server fails the test, not the network), and store RTT from a ping alongside every throughput sample, because a throughput drop with an RTT rise tells a completely different story than a drop alone.
Security: Test Servers Are Attack Surface
- Never leave an iPerf server listening on an internet-facing interface; anyone who finds it can saturate your link on demand.
- Bind to a specific internal address with
-Bon multihomed hosts, and firewall the port to known test sources. - Prefer one-shot servers (
-1) launched on demand over always-on daemons where practical. - Keep packages current, and remember results from public internet iperf servers are indicative, not diagnostic.
- On Cisco-routed paths, remember an ACL that permits TCP 5201 but not UDP 5201 produces a working TCP test and a 100%-loss UDP test - an asymmetry worth checking before blaming the network.
Troubleshooting: The Three Fingerprints
Slow throughput has three root causes, and each leaves distinct evidence in iPerf3 output. A bandwidth bottleneck pins throughput just under a round number with few retransmits (our 10 Mbit/sec capped link tested at 9.46). A latency-window ceiling shows high but stable RTT, zero loss, and dramatic sensitivity to -w. Packet loss shows climbing Retr, a congestion window that never grows, and zero-byte intervals - on our lab path, just 2% injected loss at 104 ms RTT collapsed TCP from 26 Mbit/sec to 1.47, while ping still reported 0% loss and a moderate UDP test nailed the loss at 2.1%. The full decision tree with all captures is in troubleshooting slow throughput with iPerf3.
iPerf2 and iPerf3 Are Different Tools
They do not interoperate, they default to different ports (5001 vs 5201), several flags collide in meaning, and both are actively maintained by different teams. iPerf3 is the right default (JSON output, clean reverse mode, Retr/Cwnd visibility); iPerf2 still wins for multicast, concurrent clients on one server, inline latency reporting, and multithreaded parallel streams on very fast links. The head-to-head with real output from both is in iPerf2 vs iPerf3.
The Full iPerf Cluster, in Reading Order
Install, first test, and how to actually read every column of the output.
Persistent servers, multi-port concurrency, systemd, and firewall rules.
Fixed-rate testing, reading jitter, and finding the loss knee of a path.
Bandwidth-delay product, a live 78% window-starvation collapse, and the parallel-stream recovery.
The three fingerprints (caps, ceilings, loss) demonstrated by breaking a healthy path on real routers.
Two maintained tools, no interop, colliding flags, and when each one wins.
Related fundamentals elsewhere on PingLabz: the ping guide for latency and reachability groundwork, the QoS guide for what routers do to your marked test traffic, and the Nmap guide for the discovery side of network validation.
FAQ
What port does iPerf3 use?
TCP and UDP 5201 by default (iPerf2 uses 5001). One port carries both the control connection and the test traffic, so open it for both protocols on any firewall or ACL in the path.
Why do my sender and receiver numbers differ?
The sender reports what it transmitted; the receiver reports what arrived. Small gaps on TCP are normal (data in flight when the timer expired). Large gaps, especially on UDP, are packet loss - and the receiver line is the one to trust.
How long should an iPerf test run?
At least 30 seconds for anything you plan to act on. The 10-second default includes TCP slow start and can swing several percent run to run; 30 to 60 seconds converges, and -O 3 can omit the ramp-up from the stats entirely.
Why is iPerf3 slower than my link speed?
Usually one of three things: a real bottleneck somewhere in the path, the bandwidth-delay product (single-flow window / RTT ceiling), or endpoint CPU. Check RTT, try -P 4, and watch CPU during the test before concluding the circuit is at fault.
Can iPerf test through NAT or a VPN?
Yes, as long as the client can reach the server's port - the client initiates everything, so NAT on the client side just works. Expect lower numbers through encrypted tunnels; you are measuring the tunnel's effective capacity, including its encryption overhead, which is often exactly what you want to know.
Is iPerf3 newer and therefore better than iPerf2?
Newer, yes; strictly better, no. They are separately maintained tools with different strengths. Default to iPerf3, but reach for iPerf2 for multicast, concurrent server clients, and latency-under-load reporting.
Key Takeaways
iPerf measures what a path can actually deliver, on your terms: your endpoints, your protocol, your direction. Trust the receiver line, test both directions, and run long enough to get past slow start. Use TCP to find the ceiling and UDP to judge quality beneath it. Know your path's bandwidth-delay product before calling a WAN slow, harden any server you leave running, and learn the three troubleshooting fingerprints so a strange result points you at a cause instead of a shrug. Every claim in this cluster comes from live lab output - the same commands will tell you the truth about your network too.