I had some issues caused by MTU recently, and decided to write a script to test for the Maximum Transmission Unit that a network or host could cope with.
I originally started off by using the PowerShell Test-Connection cmdlet, but then realised that it doesn’t allow you to set the DF bit (do not fragment) which is required for MTU testing, so I switched it out for the ping command.
The script works by trying buffer sizes that are calculated as the halfway point between a minimum and maximum value. These two points converge as the preceding test either passes or fails, which makes for a fairly swift determination of the MTU.
#set BufferSizeMax to the largest MTU you want to try, usually 1500 or up to 9000 if using Jumbo Frames $BufferSizeMax = 1500 #set TestAddress to the name or IP address you wish to test against $TestAddress = "www.bbc.co.uk" $LastMinBuffer=$BufferSizeMin $LastMaxBuffer=$BufferSizeMax $MaxFound=$false #calculate first MTU attempt, halfway between zero and BufferSizeMax [int]$BufferSize = ($BufferSizeMax - 0) / 2 while($MaxFound -eq $false){ try{ $Response = ping $TestAddress -n 1 -f -l $BufferSize #if MTU is too big, ping will return: Packet needs to be fragmented but DF set. if($Response -like "*fragmented*"){throw} if($LastMinBuffer -eq $BufferSize){ #test values have converged onto the highest working MTU, stop here and report value $MaxFound = $true Write-Host "found." break } else { #it worked at this size, make buffer bigger Write-Host "$BufferSize" -ForegroundColor Green -NoNewline $LastMinBuffer = $BufferSize $BufferSize = $BufferSize + (($LastMaxBuffer - $LastMinBuffer) / 2) } } catch { #it didn't work at this size, make buffer smaller Write-Host "$BufferSize" -ForegroundColor Red -NoNewline $LastMaxBuffer = $BufferSize #if we're getting close, just subtract 1 if(($LastMaxBuffer - $LastMinBuffer) -le 3){ $BufferSize = $BufferSize - 1 } else { $BufferSize = $LastMinBuffer + (($LastMaxBuffer - $LastMinBuffer) / 2) } } Write-Host "," -ForegroundColor Gray -NoNewline } Write-Host "MTU: $BufferSize"
Great script. Thank you for sharing.
LikeLike
hi, great script but buffersize is not mtu size. you need to add 28 bytes and therefore the resulting statement is misleading.
$mtu = $BufferSize + 28
Write-Host “MTU Size: $mtu”
https://en.code-bude.net/2017/02/18/tool-mtu-optimizer-automatically-find-the-best-mtu/
otherwise, AWESOME
LikeLike
While the binary reduction in your script will hone down on a the lowest mtu in a path, it will not find higher mtu’s of other routers in the path. You may need to test every possible packet size above fragmentation point without the -d to find mismatches (gaps) when going through multiple routers, firewalls, tunnels, etc.
LikeLike
PS 5.1 with NoFragmentation
Get-WmiObject -Class Win32_PingStatus -computer $ComputerName -Filter “Address=’$server’ AND Timeout=1000 AND BufferSize=$BufferSize AND NoFragmentation=TRUE”
LikeLike
Excellent script and agree with Herbert that the MTU is actually the $Buffersize + 28 => MTU == ping max payload ($Buffersize) + 8 bytes ICMP overhead + 20 bytes IP overhead.
For exotic users like me who also use Powershell on a Mac you will need to change the ping command accordingly:
$Response = ping $TestAddress -c 1 -D -s $BufferSize 2>&1
LikeLike