Ethernet — test your wired links
Before blaming your provider, measure the link between two devices in your home with iperf3. It removes the internet from the equation entirely: one machine acts as the server, another as the client, and you measure the raw throughput of the cable between them. Testing Wi-Fi instead? See the Wi-Fi guide.
WIREDEthernet — wired links
STEP 1Install iperf3 on two machines
You need two devices on your LAN. Ideally both wired, so you’re testing pure Ethernet.
- Windows: press the Windows key, type
powershell, and press Enter. - Mac: press Cmd + Space, type
terminal, and press Enter.
Once it opens, just copy and paste the commands below — the COPY button on each block does it for you.
Command not found right after installing? Close the terminal window and open a fresh one. A terminal only reads its list of program locations when it starts, so a newly-installed tool won’t appear until you reopen it — nothing’s broken.
STEP 2Start the server
On the first machine, start iperf3 in server mode and note its local IP address (e.g. 192.168.1.10). Allow it through the firewall if prompted.
Need that machine’s IP? You can read it from your router’s device list or your computer’s network settings — but since the terminal’s already open:
On a Mac, en0 is usually the built-in Wi-Fi — a USB or Thunderbolt Ethernet adapter is typically en1 or en2. If getifaddr en0 returns nothing or a Wi-Fi address, run ifconfig | grep "inet " to list every interface and pick the wired one’s 192.168… or 10… address.
When you’re done, stop the server with Ctrl-C in its terminal. iperf3 -s stays up and keeps accepting tests until you stop it, so you can run as many as you like before closing it.
STEP 3Run the test from the client
Run both commands from the client. The first measures what the client sends to the server — your upload path; adding -R reverses the direction, so the client receives instead — your download path. Between the two you’ve measured the link both ways.
These are TCP tests — the default, because TCP behaves like most real applications and retransmits lost packets, so the number reflects what real transfers achieve. A UDP test (add -u) is the right tool when you’re specifically chasing packet loss or jitter rather than raw throughput.
STEP 4Interpret the result
A healthy link runs close to its rated speed. The most common fault is a gigabit link silently negotiating down to 100 Mbps — usually a damaged cable, a bad wall jack, or a faulty pair.
| Measured | What it means | Verdict |
|---|---|---|
| ~930–945 Mbps | Healthy gigabit link | GOOD |
| ~94 Mbps | Link negotiated at 100 Mbps — check cable & ports | FAULT |
| 300–700 Mbps, unstable | Marginal cable, duplex mismatch, or CPU limit | INVESTIGATE |
| <10 Mbps | Severely damaged cabling or failing port | FAULT |
Fix checklist — start with the cheap reset: unplug and replug the cable at both ends (this re-triggers link negotiation), or power-cycle the switch. That clears transient stuck states in seconds. Verify it held, though — if the fault comes straight back it’s a real one, so then swap in a known-good Cat5e/Cat6 cable, try a different switch port, check the negotiated link speed, and inspect wall plates and joins.
On Linux you can look past the speed your adapter reports. ethtool eth0 shows what the link actually negotiated (speed and duplex), and ethtool -S eth0 exposes the error counters — if rx_frame_check_sequence_errors (CRC) or rx_symbol_errors climb during a test, the link is corrupting frames at the physical layer (a cable, port, or connector fault), not just running slow.
A gigabit USB adapter delivers gigabit only if every part of the chain is USB 3.0+ — the port, the adapter, and any cable or joiner in between. One USB 2.0 link anywhere caps the lot at ~300 Mbps, cleanly, with no error or instability to hint at it. Blue connectors and ports signal USB 3, but black doesn’t guarantee USB 2 — plenty of USB 3 ports aren’t coloured. Plug the adapter directly into a known USB 3 port to rule out the chain, then confirm with lsusb -t (480M = USB 2.0, 5000M = USB 3.0).
STEP 5Physically test a suspect cable
If iperf3 points at the cabling, a basic two-piece continuity tester (around $10–30 at electronics or hardware stores) will confirm it. It has a master unit and a small remote unit, so you can test cables already run through walls — plug the master into the wall plate at one end and the remote into the patch panel or far wall plate at the other.
Unplug the cable from all equipment first, connect master and remote, then switch it on. The tester steps through the 8 wires (plus G for shield, if present) and lights an LED pair for each. Watch both units:
| LED pattern | What it means | Verdict |
|---|---|---|
| 1→8 light in sequence on both units | All pairs continuous and in correct order | PASS |
| One number never lights | Open circuit — broken wire or bad crimp on that pin | RE-TERMINATE |
| Lights out of order (e.g. 3 on master, 6 on remote) | Miswired plug — pairs crossed during termination | RE-TERMINATE |
| Two numbers light at once | Short circuit between wires | REPLACE / RE-TERMINATE |
| Pins 4,5,7,8 dead, 1,2,3,6 fine | Only two pairs connected — link caps at 100 Mbps | EXPLAINS ~94 Mbps |
Know the limits: a continuity tester proves the wires connect end to end — it can't measure signal quality, so a cable can pass continuity yet still fail at gigabit speeds (marginal crimps, untwisted pairs at the plug, split pairs). If a cable passes the tester but iperf3 still shows ~94 Mbps or instability, re-terminate both ends (Step 6) or simply replace the patch lead. Wall-to-wall runs that keep failing are a job for a professional installer with a proper certification tester (in Australia, a registered cabler).
No tester? Test the run in service. Connect two computers directly through the suspect cable — no router or switch in between — and run iperf3 across it. Give each a static IP in the same subnet (say 192.168.50.1 and 192.168.50.2, mask 255.255.255.0, gateway left blank), then test as in Steps 2–3. Gigabit NICs auto-sense the wiring (auto-MDIX), so an ordinary straight cable works — no crossover needed. A clean ~940 Mbps proves the run end to end; CRC errors or collapsing throughput point at the cable or its terminations, with the router and switch taken out of the picture.
- Two-piece RJ45 continuity tester — master + remote, tests in-wall runs end to end~$20–60
- 8-port gigabit smart switch (TP-Link TL-SG108E) — its web UI has built-in cable diagnostics, so it doubles as a tester you keep using~$52
Already own a smart switch or a Linux box? Use its built-in cable test first (above) — no need to buy anything.
NO TESTER?Your hardware may already be one
Most Ethernet chips include a built-in TDR (Time Domain Reflectometry) function: the port sends a pulse down each pair and times the reflection, detecting opens and shorts and even estimating the distance to the fault in metres. You just need software that exposes it. This works on copper Ethernet only — there is no equivalent for Wi-Fi, which has no cable to test. For best results, unplug the far end of the cable before testing — a connected device can confuse the readings.
| You have… | How to run a cable test |
|---|---|
| A smart / managed switch (TP-Link Easy Smart, Netgear Plus, UniFi, Omada — from ~$30) | Open the switch's web interface and look for Cable Diagnostics or Cable Test under monitoring/tools. Plug the suspect cable into a port, run the test, read per-pair results. |
| A Linux machine (kernel 5.8+) | Run the command below against a wired Ethernet port. Support depends on the network chip's driver — it either works or reports "not supported". Support is the exception, not the rule: many common chips — including the Raspberry Pi's Broadcom PHY and most desktop and USB-Ethernet adapters — don't implement it. It's mainly certain Marvell, TI and Microchip PHYs, plus managed-switch silicon. Copper Ethernet only: it does nothing on Wi-Fi adapters, and most USB Ethernet dongles (ASIX, Realtek chips) don't expose it either. For wireless links, use the Wi-Fi guide below instead. |
| A MikroTik router | In the terminal: /interface ethernet cable-test ether1 — reports pair state and distance to fault, usually within a few metres. |
eth0 is just a placeholder. Modern Linux gives wired ports “predictable” names like enp3s0 or eno1 (USB adapters get enx<mac>), so run ip -br link to list yours — the wired one starts with en and shows state UP — and use that in place of eth0. On a Raspberry Pi it really is eth0.
Same limits apply: NIC-based TDR is a continuity-class test, not certification — it won't catch marginal crimps or split-pair faults that only show up at gigabit speeds, and distance accuracy is typically ±2–5 m. But as a free first check using hardware you already own, it tells you in seconds whether a pair is broken and roughly where.
STEP 6Re-terminate the plug (T568A or T568B)
There are two standard colour orders, T568A and T568B — they're electrically identical, and the only rule is that both ends of the cable use the same one. This guide shows T568A (the fixed-cabling standard in Australia and New Zealand; the US more often uses T568B). Both ends of a normal straight-through cable are wired identically. Hold the RJ45 plug with the clip facing down and the pins facing you — pin 1 is then on the left.
Which standard should you use? Either — just be consistent end to end. Matching your local fixed-cabling standard keeps your plugs consistent with existing wall sockets and patch panels: that's T568A in Australia and New Zealand (AS/CA S008), and T568B is the common choice in the US. One DIY caveat that applies everywhere: cabling run inside walls is often where a licensed professional is required — in Australia that's a registered cabler, by law. Patch leads and plugs on loose, surface-run cable are DIY territory anywhere; the in-wall structural work is the part to hand off. (Not legal advice — check your local rules.)
- Pre-made Cat6 patch leads — the honest first choice; factory-terminated and tested, no crimping~$5–15
- RJ45 crimp tool (Jaycar TH1935) — cuts, strips and crimps RJ45/RJ11; only worth it if you'll terminate several~$30
For one or two cables, a pre-made lead is cheaper, faster and more reliable than buying tools to crimp your own.
A real example: when the link said “gigabit” but wasn’t
This guide grew out of an actual fault. It is worth walking through, because it shows why you test instead of guess — and how one bad number hid two unrelated problems while the obvious suspect turned out innocent.
It began with one laptop whose USB Wi-Fi adapter had been flaky for weeks — so it had become the reflex explanation for anything network-related on that machine. When the laptop's wired link then came in at only about 300 Mbps, gigabit expected, that same flaky adapter caught the blame out of habit. It was the cause of nothing here.
The discipline that cracked it was simple: change one variable at a time, and re-test after every change.
Fault one — a throttled USB chain. The ~300 Mbps ceiling followed one laptop wherever it plugged in, so the network was not the problem. That laptop reached its Ethernet port through a USB-C joiner and a USB-C-to-USB-A cable. A single USB 2.0 link anywhere in that chain caps the lot at ~300 Mbps — cleanly, no errors, just a flat ceiling. The same adapter plugged straight into a USB 3 port did 940 Mbps.
Fault two — a corrupting router port. A different machine (a Raspberry Pi, wired) was far worse: heavy UDP loss and TCP collapsing to about 1.5 Mbps. That is not a clean cap, it is corruption — and ethtool -S named it. The CRC (FCS) and symbol error counters were climbing by thousands every test, so the link was mangling frames at the physical layer.
$ ethtool -S eth0 | grep -E 'fcs|symbol' rx_frame_check_sequence_errors: 48213 rx_symbol_errors: 12904
These are lifetime totals — what matters is that they climbed during a single test. Thousands of new errors per run is active corruption.
Swapping the cable changed nothing. Moving the Pi to a different router port restored 940 Mbps at 0% loss with the counters static. The twist: the original port was not dead. After a power-cycle it tested clean and held — it had been in a transient stuck state, which is exactly why you bounce a link first and then confirm the fix held (Step 4).
And the Wi-Fi adapter that started as prime suspect? It was cleared by testing it on its own. Running iperf3 between two wireless machines — the laptop and a second PC, both connected by Wi-Fi with no wired device anywhere in the path — came back at 0.0014% loss. A result that clean means both Wi-Fi adapters, the router and the airwaves between them were all healthy — so the flaky adapter had been a red herring, and the fault was on the wired side all along.
| What was tested | Result | What it meant |
|---|---|---|
| USB-Ethernet adapter via joiner + USB-A cable | ~300 Mbps, no errors | Flat, clean cap — a USB 2.0 link in the chain |
| Same adapter, direct into a USB 3 port | 940 Mbps | The chain was the only limit |
| Pi via the original router port | ~1.5 Mbps, ~16% UDP loss | CRC + symbol errors climbing — physical corruption |
| Pi via a different router port | 940 Mbps, 0% loss | That port was the fault |
| Original port after a power-cycle | 940 Mbps, holds | Transient stuck state, not a dead port |
What the saga teaches
- A port can negotiate gigabit and still deliver a fraction of it — only a throughput test exposes the gap.
- The shape of the result names the fault class: a flat, clean ceiling is a bandwidth limit (a USB 2.0 link); lossy, collapsing throughput with rising CRC/symbol errors is physical corruption.
- Change one variable at a time, and re-test after every fix — a number measured while another fault is still active is worthless.
- Do not stop at the first culprit. There were two unrelated faults here, and the most obvious suspect was guilty of nothing.