Public/Measure-LissWindowsBufferbloat.ps1

function Measure-LissWindowsBufferbloat {
    <#
    .SYNOPSIS
    Compares idle and loaded endpoint latency with approved iperf3 load.
    .DESCRIPTION
    Collects an idle ICMP baseline, starts the bundled signed iperf3 client or an explicitly selected approved executable without blocking redirected output, samples latency concurrently with upload or download load, and returns latency increases plus parsed iperf3 JSON. It cleans up the child process after success or failure. This consumes bandwidth and requires -Approved plus ShouldProcess confirmation.
    .PARAMETER Server
    Approved iperf3 server hostname or address.
    .PARAMETER LatencyTarget
    Endpoint used for idle and loaded ICMP latency sampling.
    .PARAMETER Port
    Approved iperf3 server port.
    .PARAMETER Direction
    Upload or Download load direction.
    .PARAMETER DurationSeconds
    Loaded test duration, from 5 through 120 seconds.
    .PARAMETER IdleDurationSeconds
    Idle baseline duration, from 1 through 30 seconds.
    .PARAMETER IntervalMilliseconds
    Latency sampling interval.
    .PARAMETER TimeoutMilliseconds
    Timeout for each ICMP sample.
    .PARAMETER IperfPath
    Optional path to another approved iperf3 executable. The signed bundled x64 client is used by default.
    .PARAMETER Approved
    Confirms that the server and bandwidth use are approved.
    .EXAMPLE
    Measure-LissWindowsBufferbloat -Server iperf.internal.example -LatencyTarget 1.1.1.1 -Direction Download -Approved -Confirm:$false
    #>

    [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
    [OutputType('LISSTech.WindowsNetworkDiagnostics.BufferbloatResult')]
    param(
        [Parameter(Mandatory)][ValidatePattern('^[a-zA-Z0-9][a-zA-Z0-9._:-]*$')][string]$Server,
        [Parameter(Mandatory)][ValidateNotNullOrEmpty()][string]$LatencyTarget,
        [ValidateRange(1, 65535)][int]$Port = 5201,
        [ValidateSet('Upload', 'Download')][string]$Direction = 'Upload',
        [ValidateRange(5, 120)][int]$DurationSeconds = 10,
        [ValidateRange(1, 30)][int]$IdleDurationSeconds = 5,
        [ValidateRange(50, 5000)][int]$IntervalMilliseconds = 250,
        [ValidateRange(100, 10000)][int]$TimeoutMilliseconds = 1000,
        [string]$IperfPath,
        [Parameter(Mandatory)][switch]$Approved
    )

    if (-not $Approved) {
        throw 'Explicit -Approved confirmation is required for bufferbloat testing.'
    }
    $executable = Resolve-LissIperfExecutable -Path $IperfPath
    $target = "$Direction load from approved server $Server`:$Port with latency target $LatencyTarget"
    if (-not $PSCmdlet.ShouldProcess($target, 'Run concurrent iperf3 and ICMP test')) {
        return
    }

    $started = Get-Date
    $idleSamples = @(Invoke-LissLatencyWindow -Target $LatencyTarget -DurationSeconds $IdleDurationSeconds -IntervalMilliseconds $IntervalMilliseconds -TimeoutMilliseconds $TimeoutMilliseconds)
    $idleSummary = Get-LissLatencySummary -Sample $idleSamples -Target $LatencyTarget
    $context = $null
    try {
        $context = Start-LissIperfLoad -Executable $executable -Server $Server -Port $Port -DurationSeconds $DurationSeconds -Direction $Direction
        $loadedSamples = @(Invoke-LissLatencyWindow -Target $LatencyTarget -DurationSeconds $DurationSeconds -IntervalMilliseconds $IntervalMilliseconds -TimeoutMilliseconds $TimeoutMilliseconds -WhileProcessRuns $context.Process)
        $iperfResult = Complete-LissIperfLoad -Context $context -DurationSeconds $DurationSeconds
        $context = $null
    }
    finally {
        if ($context) {
            Stop-LissProcessContext -Context $context
            if ($context.Process) {
                $context.Process.Dispose()
            }
            if ($context.WorkingDirectory -and [IO.Directory]::Exists($context.WorkingDirectory)) {
                [IO.Directory]::Delete($context.WorkingDirectory, $true)
            }
        }
    }
    $loadedSummary = Get-LissLatencySummary -Sample $loadedSamples -Target $LatencyTarget
    [pscustomobject]@{
        PSTypeName                       = 'LISSTech.WindowsNetworkDiagnostics.BufferbloatResult'
        Server                           = $Server
        Port                             = $Port
        Direction                        = $Direction
        LatencyTarget                    = $LatencyTarget
        StartedAt                        = $started
        CompletedAt                      = Get-Date
        IdleLatency                      = $idleSummary
        LoadedLatency                    = $loadedSummary
        AverageLatencyIncreaseMilliseconds = if ($null -ne $idleSummary.AverageMilliseconds -and $null -ne $loadedSummary.AverageMilliseconds) { [Math]::Round($loadedSummary.AverageMilliseconds - $idleSummary.AverageMilliseconds, 2) } else { $null }
        Percentile95IncreaseMilliseconds = if ($null -ne $idleSummary.Percentile95Milliseconds -and $null -ne $loadedSummary.Percentile95Milliseconds) { [Math]::Round($loadedSummary.Percentile95Milliseconds - $idleSummary.Percentile95Milliseconds, 2) } else { $null }
        IdleSamples                      = $idleSamples
        LoadedSamples                    = $loadedSamples
        IperfResult                      = $iperfResult
    }
}