How to determine the proper MTU size with ICMP pings

There's a nice intro on the topic in one of the Linksys knowledgebase articles. I copy the info here so it won't vanish once their knowledgebase goes offline. The original article used the Windows ping command in its examples, but I've added linux and Mac specific examples too.

To find the proper MTU size, you'll have to do a special ping of the destination you're trying to go to. This could be a local machine (a router, gateway, etc.) or a distant server on the internet (eg. example.com).

In case of a Windows machine the ping command should be formatted like:
ping [-f] [-l <packet size>] [host]

An example test-run would be:
ping -f -l 1472 example.com
(result = "Packet needs to be fragmented but DF set.")
ping -f -l 1462 example.com
(result = "Request timed out.")
ping -f -l 1452 example.com
(result = reply)

The options used are:
  • -f: set "Don't Fragment" flag in packet
  • -l size: send buffer size
In case of Linux, the command line should be:
ping [-M do] [-s <packet size>] [host]

An example test-run would be:
ping -M do -s 1472 example.com
(result = "Frag needed and DF set")
ping -M do -s 1462 example.com
(result = "Frag needed and DF set")
ping -M do -s 1452 example.com
(result = reply)

The options used are:
  • -M <hint>: Select Path MTU Discovery strategy. <hint> may be either "do" (prohibit fragmentation, even local one), "want" (do PMTU discovery, fragment locally when packet size is large), or "dont" (do not set DF flag).
  • -s packetsize: Specifies the number of data bytes to be sent. The default is 56, which translates into 64 ICMP data bytes when combined with the 8 bytes of ICMP header data.
In case of Mac (Leopard), the command should be:
ping [-D] [-s <packet size>] [host]

An example test-run would be:
ping -D -s 1472 example.com
(result = "sendto: Message too long")
ping -D -s 1462 example.com
(result = "frag needed and DF set")
ping -D -s 1452 example.com
(result = reply)

The options used are:
  • -D: set the "Don't Fragment" bit
  • -s packetsize: Specify the number of data bytes to be sent. The default is 56, which translates into 64 ICMP data bytes when combined with the 8 bytes of ICMP header data.
You should always start at 1472 and work your way down by 10 each time. Once you get a reply, go up by 2 until you get a fragmented packet. Take that value and add 28 to the value to account for the various TCP/IP headers. Eg. let's say that 1452 was the proper packet size (where you first got an ICMP reply to your ping). The actual MTU size would be 1480, which is the optimum for the network we're working with.

You can read more about MTU in the respective Wikipedia article.

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

MAC

On my MAC I personally use the Min -g 1330 and Max -G 1500, plus 8 byte ICMP header to start and increment by 1 (-h 1), let ping do the work.
for a VPN I like to start at 1330 with a 1500 max.

ping -g 1330 -G 1500 -h 1 -D 10.152.0.19
PING 10.152.0.19 (10.152.0.19): (1330 ... 1400) data bytes
1338 bytes from 10.152.0.19: icmp_seq=0 ttl=121 time=418.883 ms
1339 bytes from 10.152.0.19: icmp_seq=1 ttl=121 time=441.258 ms
1340 bytes from 10.152.0.19: icmp_seq=2 ttl=121 time=289.218 ms
36 bytes from 10.152.0.19: frag needed and DF set (MTU 1360)
Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
4 5 00 5105 a691 0 0000 3a 01 dd47 172.24.1.16 10.152.0.19


For DSL min -g 1420 max -G 1500, My MTU is 1454

ping -g 1420 -G 1500 -h 1 -D 4.2.2.2
PING 4.2.2.2 (4.2.2.2): (1420 ... 1500) data bytes
1428 bytes from 4.2.2.2: icmp_seq=0 ttl=58 time=43.811 ms
1429 bytes from 4.2.2.2: icmp_seq=1 ttl=58 time=47.041 ms
1430 bytes from 4.2.2.2: icmp_seq=2 ttl=58 time=46.520 ms
1431 bytes from 4.2.2.2: icmp_seq=3 ttl=58 time=44.635 ms
1432 bytes from 4.2.2.2: icmp_seq=4 ttl=58 time=46.400 ms
1433 bytes from 4.2.2.2: icmp_seq=5 ttl=58 time=45.652 ms
1434 bytes from 4.2.2.2: icmp_seq=6 ttl=58 time=43.712 ms
36 bytes from pool-xx-xx-xx-52.dfw.dsl-w.verizon.net (xx.xx.xx.52): frag needed and DF set (MTU 1454)
Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
4 5 00 af05 83c7 0 0000 40 01 9f64 10.200.1.87 4.2.2.2


Just my two cents!

Re: MAC

Thanks! I didn't notice the -g and -G options on Mac.

here is an odd situation...

I tried this method to with my new NetGear GS116E switch and it always blocks pings with buffer sizes between 513 and 1472! The switch has NO problem passing traffic with even jumbo frames as proven by sharking the traffic. Pings however within those ranges are not passed.

I have not been able to find an explanation for this.

Ron <><

Re: here is an odd situation...

Does this mean that only pings with a packet size below 513 bytes go through? I'm asking because 1472 is most probably the upper limit (at least for most networks/ISPs). Have you tried to ping multiple hosts and the results were all the same? Do pings work with all sorts of packet sizes if you remove the switch from your network setup?

for loop with ping

You can try this.

for i in {1500..900..-2}; do ping -M do -c 1 $IP_OF_VPN_SERVER -s "$i" 2>&1 | grep -q '1 received' && break; done; echo $i

HTH