Functions/Test-MTU.ps1

function Test-MTU {
<#
.SYNOPSIS
    Finds the MTU size for packets to a remote computer.
.DESCRIPTION
    Will find the point where packets don't fragment (MTU) to a remote source, which defaults to the computers logon server if an address isn't specified.
.PARAMETER RemoteAddress
    Specifies the name or IP of one or more remote computers.
.PARAMETER BufferSizeMax
    Allows you to specify the highest MTU to test.
.EXAMPLE
    C:\PS>Test-MTU
    Example of how to use this cmdlet.
.EXAMPLE
    C:\PS>Test-MTU www.wanderingstag.com
    Shows how to test the MTU to the website www.wanderingstag.com.
.EXAMPLE
    C:\PS>Test-MTU COMP1,www.wanderingstag.com
    Shows how to test the MTU to the computer COMP1 and the website www.wanderingstag.com.
.EXAMPLE
    C:\PS>Test-MTU COMP1 1272
    Shows how to test the MTU to the computer COMP1, the max buffer size (MTU) will start at 1272.
.INPUTS
    System.String
.OUTPUTS
    System.Management.Automation.PSCustomObject
.COMPONENT
    WSTools
.FUNCTIONALITY
    Maximum Transmission Unit, MTU, network, connectivity, troubleshooting
.NOTES
    Author: Skyler Hart
    Created: 2022-11-22 21:27:58
    Last Edit: 2022-11-22 23:06:11
    Other:
    Requires:
.LINK
    https://wanderingstag.github.io
#>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$false)]
        [Alias('Host', 'Name', 'Computer', 'ComputerName', 'TestAddress')]
        [string[]]$RemoteAddress,

        #Set BufferSizeMax to the largest MTU you want to test (1500 normally or up to 9000 if using Jumbo Frames)
        [Parameter(Mandatory=$false)]
        [int]$BufferSizeMax = 1500
    )

    if ([string]::IsNullOrWhiteSpace($RemoteAddress)) {
        Write-Verbose "Test Address not specified. Setting to logon server."
        $RemoteAddress = ($env:LOGONSERVER).Replace('\\','') + "." + $env:USERDNSDOMAIN
    }
    Write-Verbose "RemoteAddress: $TestAddress"
    Write-Verbose "BufferSizeMax: $BufferSizeMax"

    foreach ($TestAddress in $RemoteAddress) {
        $LastMinBuffer=$BufferSizeMin
        $LastMaxBuffer=$BufferSizeMax
        $MaxFound=$false
        $GoodMTU = @()
        $BadMTU = @()

        #Calculate first MTU test, 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
                    break
                }
                else {
                    #it worked at this size, make buffer bigger
                    Write-Verbose "Found good MTU: $BufferSize"
                    $GoodMTU += $BufferSize
                    $LastMinBuffer = $BufferSize
                    $BufferSize = $BufferSize + (($LastMaxBuffer - $LastMinBuffer) / 2)
                }
            }
            catch {
                #it didn't work at this size, make buffer smaller
                Write-Verbose "Found bad MTU: $BufferSize"
                $BadMTU += $BufferSize
                $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-Verbose "Good MTUs: $GoodMTU"
        Write-Verbose "Bad MTUs: $BadMTU"
        Write-Verbose "Recommended MTU: $BufferSize"

        if ($BufferSize -le 1472) {
            $BufferSize = $BufferSize+28
        }

        [PSCustomObject]@{
            ComputerName = $env:COMPUTERNAME
            GoodMTUs = $GoodMTU -join ","
            BadMTUs = $BadMTU -join ","
            MTUwithBuffer = $BufferSize
            TestAddress = $TestAddress
        }#new object
    }
}