How do you check, test and change MTU on Linux, and how do you find a path MTU problem?
Show the answer
Say this first
ip link show shows each interface's MTU; ip link set dev ens192 mtu 9000 changes it until reboot, and the
network manager's config makes it permanent. To test a path, ping with the DF bit set and a payload of MTU
minus 28: ping -M do -s 1472. Linux caches a smaller path MTU learned from ICMP "fragmentation needed" per
destination, and ip route get shows it. The classic symptom of a broken path MTU is small requests working
while large transfers or TLS handshakes hang.
Go deeper
Test
$ ping -M do -s 1472 -c 1 10.0.10.30
PING 10.0.10.30 (10.0.10.30) 1472(1500) bytes of data.
1480 bytes from 10.0.10.30: icmp_seq=1 ttl=64 time=0.412 ms
$ ping -M do -s 8972 -c 1 10.0.10.30
PING 10.0.10.30 (10.0.10.30) 8972(9000) bytes of data.
ping: local error: message too long, mtu=1500
$ ping -M do -s 1472 -c 1 198.51.100.80
PING 198.51.100.80 (198.51.100.80) 1472(1500) bytes of data.
From 10.0.10.1 icmp_seq=1 Frag needed and DF set (mtu = 1400)- 1472 + 8 (ICMP) + 20 (IP) = 1500. For jumbo, 8972 + 28 = 9000.
- "local error" means our own interface MTU is smaller than the packet.
- "Frag needed" comes from a router on the path, here telling us the next link is 1400.
The cache
$ ip route get 198.51.100.80
198.51.100.80 via 10.0.10.1 dev ens192 src 10.0.10.21 uid 1000
cache expires 586sec mtu 1400Learned values expire after 10 minutes (net.ipv4.route.mtu_expires 600). tracepath walks the path and
reports where the MTU drops.
Common overheads
VXLAN adds 50 bytes (1450 inside a 1500 underlay), GRE 24 (1476), and WireGuard interfaces default to 1420.
On a Linux router
Clamp TCP MSS for tunnels and PPPoE:
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu, or in nftables
tcp flags syn tcp option maxseg size set rt mtu.
They will ask next
One host on a VLAN is set to 9000 and the rest to 1500. What breaks?
TCP mostly survives because each side advertises an MSS from its own MTU and the sender uses the smaller. Large UDP or ICMP from the jumbo host is dropped by the 1500-byte receivers and switch ports. Everything on one layer 2 segment must agree on the MTU.
How do you make the MTU change permanent?
Netplan
mtu: 9000under the interface, NetworkManagernmcli con mod ens192 802-3-ethernet.mtu 9000, or systemd-networkdMTUBytes=9000in the[Link]section.
Traps
- Testing with
ping -s 1500. The payload size excludes the 28 bytes of headers. - Raising the server MTU without the switch ports, which then drop the jumbo frames as giants.