Troubleshoot Slow Network Speed in Linux

Tested on RHEL 10.2 (Coughlan) — vm1.lab.example (192.168.56.116); lab peer 192.168.56.220 on host-only enp0s8; default gateway 10.0.2.2 on enp0s3
Package iperf3 3.17.1-6.el10_2
curl 8.12.1-4.el10
ethtool 6.15-2.el10
iproute 6.17.0-2.el10
iputils 20240905-5.el10
mtr 0.95-11.el10
Applies to Ubuntu, Debian, Kali Linux, Linux Mint, Pop!_OS, Raspberry Pi OS, elementary OS, Zorin OS, Parrot OS, MX Linux, RHEL, Rocky Linux, AlmaLinux, Oracle Linux, CentOS Stream, Fedora, Arch Linux
Privilege Normal user for ping, curl, and read-only ip / ethtool; sudo or root for iperf3 server on privileged ports and interface changes
Scope Diagnose Linux slow ethernet and download speed using throughput tests, latency and loss checks, ethtool link speed, interface counters, MTU probes, and route selection. Does not cover Wi-Fi driver tuning, CDN selection, or full packet loss deep dives beyond latency basics.
Related guides Linux packet loss troubleshooting
Network is unreachable
ip route command
Test port connectivity
traceroute command

Downloads crawl, scp takes forever, and the browser spinner outlasts your coffee — but “slow network” on Linux can mean a 100 Mb/s link, congestion on one hop, a wrong route, or a remote server that answers slowly. Measure throughput first, then check whether latency, link speed, drops, MTU, or routing explain the gap.


Measure the actual network throughput

Subjective “feels slow” is not a benchmark. Start with a repeatable download test, then use iperf3 when you control both ends of the path.

HTTP downloads through curl reflect real-world TCP behavior — DNS, TLS, and the remote server included:

bash
curl -o /dev/null -s -w "Downloaded %{size_download} bytes in %{time_total}s (%{speed_download} B/s)\n" http://speedtest.tele2.net/1MB.zip
output
Downloaded 1048576 bytes in 4.050602s (258869 B/s)

Roughly 250 KiB/s on this lab NAT path is the baseline to compare after you change cables, routes, or firewall rules. Pick a test file size your link can finish in a few seconds — 1 MiB is enough for a quick check.

For point-to-point TCP without HTTP overhead, run iperf3 in server mode on the receiving host:

bash
iperf3 -s

From the sender, point the client at that host (iperf3 -c PEER -t 5 -f m). The lab captured the output format on loopback — expect far lower bitrates on a real LAN or WAN:

bash
iperf3 -c 127.0.0.1 -t 3 -f m
output
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-3.00   sec  14.5 GBytes  41569 Mbits/sec    9             sender
[  5]   0.00-3.00   sec  14.5 GBytes  41564 Mbits/sec                  receiver

iperf Done.

Read the Bitrate column on the receiver line — that is the sustained TCP throughput for the interval. Non-zero Retr means retransmits; occasional retries are normal on the internet, but hundreds per second on a quiet LAN point at loss or buffer pressure.


Check latency and packet loss

High latency and loss cap throughput even when ethtool reports gigabit — TCP backs off when packets disappear. Use ping for a quick RTT average and loss percentage on the same path you measured above:

bash
ping -c 10 -i 0.2 192.168.56.220
output
--- 192.168.56.220 ping statistics ---
10 packets transmitted, 10 received, 0% packet loss, time 1822ms
rtt min/avg/max/mdev = 0.685/1.055/1.999/0.379 ms

Sub-millisecond average RTT with 0% packet loss on the LAN peer is a healthy baseline. Loss or double-digit millisecond RTT on a host-only segment deserves a look at cables and switch ports before you tune TCP elsewhere.

For intermittent loss on longer paths, mtr combines traceroute with repeated probes:

bash
mtr -rw -c 5 192.168.56.220
output
Start: 2026-08-22T09:16:40+0530
HOST: vm1.lab.example Loss%   Snt   Last   Avg  Best  Wrst StDev
  1.|-- 192.168.56.220   0.0%     5    0.9   1.3   0.9   1.8   0.4

See Linux packet loss troubleshooting when Loss% climbs above zero on a path that should be clean.


A NIC negotiated to 100 Mb/s half-duplex on a gigabit switch caps speed far below what the cable supports. ethtool reports what the driver actually negotiated:

bash
sudo ethtool enp0s8
output
Speed: 1000Mb/s
	Duplex: Full
	Link detected: yes

1000Mb/s and Full match a healthy gigabit Ethernet link. 100Mb/s, Half, or Link detected: no explain slow transfers that have nothing to do with CPU load — fix cabling, switch port, or autoneg before chasing application settings.

Wi-Fi interfaces use different tools (iw dev wlan0 link), but the idea is the same: confirm the PHY rate before you blame the server.


Check interface errors and drops

Kernel counters show whether frames are discarded on the NIC or in the transmit queue while ethtool still reports link up. Inspect the interface that carries the slow traffic:

bash
ip -s link show enp0s8
output
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    RX:  bytes packets errors dropped  missed   mcast
        718124    5475      0       0       0     163
    TX:  bytes packets errors dropped carrier collsns
      29412516   24090      0       3       0       0

Watch errors, dropped, and carrier:

  • Rising errors — electrical or driver problems
  • Rising dropped — buffer or qdisc pressure (fq_codel drops under load)
  • Non-zero carrier — link flaps

Flat counters during a slow iperf3 run suggest the bottleneck is elsewhere — upstream congestion, a rate limit, or the remote endpoint.


Check MTU

An MTU mismatch makes large TCP segments fail while tiny ping probes succeed — downloads stall or crawl. Confirm the interface MTU first:

bash
ip link show enp0s8 | grep mtu
output
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000

mtu 1500 is standard Ethernet. Probe the path with do-not-fragment ICMP — payload 1472 bytes fills a 1500-byte frame including headers:

bash
ping -c 3 -M do -s 1472 192.168.56.220
output
--- 192.168.56.220 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1003ms

All replies returned means this LAN segment handles full-size frames. VPN and tunnel interfaces often use mtu 1400 or lower — if large transfers fail only through the tunnel, lower the inner MTU or enable TCP MSS clamping on that interface.


Check routes

Traffic sent out the wrong interface hits a slow or asymmetric path. ip route get shows which NIC and source IP the kernel picks for a destination:

bash
ip route get 192.168.56.220
output
192.168.56.220 dev enp0s8 src 192.168.56.116 uid 0
    cache

LAN peers should use the connected subnet device — here enp0s8. A remote address should exit through your intended gateway:

bash
ip route get 8.8.8.8
output
8.8.8.8 via 10.0.2.2 dev enp0s3 src 10.0.2.15 uid 0
    cache

Compare metrics when you have multiple default routes — lower metric wins:

bash
ip route show
output
default via 10.0.2.2 dev enp0s3 proto dhcp src 10.0.2.15 metric 116
10.0.2.0/24 dev enp0s3 proto kernel scope link src 10.0.2.15 metric 116
192.168.56.0/24 dev enp0s8 proto kernel scope link src 192.168.56.116 metric 117

If bulk traffic should prefer the faster uplink but ip route get shows the wrong dev, fix policy routing or NetworkManager connection metrics — see ip route command and network is unreachable when paths fail entirely.


Determine network vs application bottleneck

Split where time is spent. curl can print phase timings so you see whether DNS, TCP connect, or the server response dominates:

bash
curl -o /dev/null -s -w "namelookup: %{time_namelookup}s connect: %{time_connect}s starttransfer: %{time_starttransfer}s total: %{time_total}s speed: %{speed_download} B/s\n" http://speedtest.tele2.net/1MB.zip
output
namelookup: 0.047471s connect: 0.050023s starttransfer: 2.927185s total: 3.344723s speed: 313501 B/s

connect near 50 ms with starttransfer near 3 s means TCP came up quickly but the server took seconds before sending bytes — application or remote congestion, not a local duplex mismatch. Compare against raw TCP on the same path:

bash
iperf3 -c 127.0.0.1 -t 3 -f m

When iperf3 shows high megabits per second but one curl URL stays slow, test another mirror or run port connectivity checks on the service port. When iperf3 and curl are both slow with low ethtool speed or rising interface drops, fix the link and routes first.


Troubleshooting

Symptom Likely cause Fix
ethtool shows 100 Mb/s on a gigabit link Bad cable, port, or autoneg Reseat cable; try another switch port; force speed only as a temporary test
High TX dropped during transfers Qdisc or ring buffer pressure Check fq_codel drops; tune NIC ring buffers per vendor docs; reduce parallel streams
Fast ping, slow downloads, high time_starttransfer Remote server or TLS overhead Try another URL; test same host with iperf3; profile application
Slow only through VPN/tunnel Tunnel MTU too high Lower tunnel MTU; enable MSS clamp; test with ping -M do -s stepping down
iperf3 fast LAN, slow internet WAN bandwidth cap or ISP shaping Test at different times; compare gateway ping vs remote; expect lower WAN bitrate
Traffic exits wrong interface Route metric or policy ip route get DST; adjust NM metrics or add policy rules
iperf3: error - unable to connect Server not running or firewall Start iperf3 -s on peer; open TCP 5201 in firewall

References


Summary

Slow network complaints on Linux need a number before a fix — curl with speed_download gives a quick HTTP throughput baseline, and iperf3 between two hosts measures raw TCP when you need to exclude a single web server from the test. Pair those results with ping and mtr on the same path so latency and loss do not undermine an otherwise fast link.

Local link problems show up in ethtool (Speed, Duplex, Link detected) and in ip -s link error and drop counters. MTU mismatches punish large transfers while small probes still work — exercise ping -M do -s 1472 on standard Ethernet. ip route get confirms bulk traffic leaves the interface you expect; wrong metrics send packets through a slower uplink.

When curl phase timings show long time_starttransfer but fast connect, suspect the remote endpoint or congestion far from your NIC. When iperf3 and curl are both slow and the link negotiated below gigabit or drops are climbing, fix hardware and routing before you tune application buffers. For sustained loss on the path, continue with Linux packet loss troubleshooting.


Frequently Asked Questions

1. How do I test network speed on Linux?

Use curl -o /dev/null -w with speed_download for HTTP throughput, or run iperf3 between two hosts with iperf3 -s on one side and iperf3 -c PEER on the other. Compare the result to ethtool Speed on the NIC and to ping latency on the same path.

2. Why is my Linux download slow but ping fast?

Low ping RTT with slow HTTP downloads often means the remote server, TLS, or congestion on a far hop — not your local cable. Split the delay with curl timing fields: high time_connect points at routing or firewall; high time_starttransfer with fast connect points at the server or DNS.

3. What link speed should ethtool show?

Match the port you plugged into. A gigabit switch port should report Speed 1000Mb/s and Duplex Full. Speed 100Mb/s or Half on a gigabit link often means a bad cable, autoneg failure, or an old switch port — that caps throughput well below what you expect.

4. Can the wrong MTU make the network feel slow?

Yes. An MTU mismatch causes fragmentation or black-holed large packets. TCP may retransmit and crawl while small ping probes still work. Test with ping -M do -s 1472 on Ethernet MTU 1500 paths, or use tracepath to discover the path MTU.

5. How do I tell if slowness is the network or the application?

Measure raw TCP with iperf3 on the same path, then compare to your app. If iperf3 is fast but curl to one URL is slow, suspect the server or TLS. If iperf3 and curl are both slow with high ping loss or low ethtool speed, fix the link and routes first.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)