From 1bf7c3b335a41bbb37fd021b05743b58333bbd85 Mon Sep 17 00:00:00 2001 From: Alan Jowett Date: Tue, 28 Jul 2026 13:45:30 -0700 Subject: [PATCH 1/6] fix: improve QUIC echo kernel test reliability Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/scripts/run-quic-echo-test.ps1 | 45 +++++++++++++++++++ .../workflows/network-traffic-performance.yml | 4 +- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/.github/scripts/run-quic-echo-test.ps1 b/.github/scripts/run-quic-echo-test.ps1 index 132e2cb8..456f0243 100644 --- a/.github/scripts/run-quic-echo-test.ps1 +++ b/.github/scripts/run-quic-echo-test.ps1 @@ -561,6 +561,51 @@ function Install-RemoteWinQuicEchoKmDriver { } } + function Ensure-RemoteMsQuicLoaded { + param([Parameter(Mandatory=$true)][string]$MsQuicPath) + + $relativeMsQuicPath = 'system32\drivers\msquic.sys' + + if (-not (Test-Path -LiteralPath $MsQuicPath)) { + Write-Host "Required msquic.sys not found at $MsQuicPath" + $found = Get-ChildItem -Path "$env:SystemRoot\System32\drivers" -Filter 'msquic*' -ErrorAction SilentlyContinue + if ($found) { Write-Host "Found msquic files: $($found.Name -join ', ')" } + else { Write-Host "No msquic driver files found in drivers directory" } + throw "Required msquic.sys was not found; kernel-mode WinQuicEcho tests require the inbox msquic driver." + } + + Write-Host "Found msquic.sys at $MsQuicPath (size: $((Get-Item $MsQuicPath).Length) bytes)" + + $svc = Get-Service -Name 'msquic' -ErrorAction SilentlyContinue + if ($null -eq $svc) { + Write-Host "Creating msquic kernel service" + & sc.exe create msquic type= kernel binPath= $MsQuicPath start= demand | Out-Null + if ($LASTEXITCODE -ne 0) { + throw "Remote sc create msquic failed with exit code $LASTEXITCODE" + } + } + + try { + Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\msquic" -Name "ImagePath" -Value $relativeMsQuicPath + } catch { + throw "Failed to normalize remote msquic ImagePath: $($_.Exception.Message)" + } + + $svc = Get-Service -Name 'msquic' -ErrorAction SilentlyContinue + if ($null -eq $svc) { + throw "Remote msquic service was not found after create" + } + if ($svc.Status -ne 'Running') { + Write-Host "Starting msquic service" + & sc.exe start msquic 2>&1 | ForEach-Object { Write-Host " $_" } + if ($LASTEXITCODE -ne 0) { + throw "Remote sc start msquic failed with exit code $LASTEXITCODE" + } + } else { + Write-Host "msquic service is already running" + } + } + $identity = [Security.Principal.WindowsIdentity]::GetCurrent() $principal = [Security.Principal.WindowsPrincipal]::new($identity) if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { diff --git a/.github/workflows/network-traffic-performance.yml b/.github/workflows/network-traffic-performance.yml index 99673d75..045ee61d 100644 --- a/.github/workflows/network-traffic-performance.yml +++ b/.github/workflows/network-traffic-performance.yml @@ -443,8 +443,8 @@ jobs: fail-fast: false matrix: vec: ${{ fromJSON(contains(inputs.receiver_options, '--backend msquic-km') && - '[{"env":"lab","os":"rsiof","arch":"x64","runner_extra":"self-hosted","sender_connections":"16","sender_outstanding":"16","sender_connect_stagger_ms":"0","sender_warmup":"15"}]' || - '[{"env":"lab","os":"2022","arch":"x64","runner_extra":"ebpf","sender_connections":"","sender_outstanding":"","sender_connect_stagger_ms":"","sender_warmup":""},{"env":"lab","os":"rsiof","arch":"x64","runner_extra":"self-hosted","sender_connections":"16","sender_outstanding":"16","sender_connect_stagger_ms":"0","sender_warmup":"15"}]') }} + '[{"env":"lab","os":"rsiof","arch":"x64","runner_extra":"self-hosted","supports_msquic_km":true,"sender_connections":"16","sender_outstanding":"16","sender_connect_stagger_ms":"0","sender_warmup":"15"}]' || + '[{"env":"lab","os":"2022","arch":"x64","runner_extra":"ebpf","supports_msquic_km":false,"sender_connections":"","sender_outstanding":"","sender_connect_stagger_ms":"","sender_warmup":""},{"env":"lab","os":"rsiof","arch":"x64","runner_extra":"self-hosted","supports_msquic_km":true,"sender_connections":"16","sender_outstanding":"16","sender_connect_stagger_ms":"0","sender_warmup":"15"}]') }} runs-on: - self-hosted - ${{ matrix.vec.env }} From ae24724417d9ea85b95e1a56566c8aa2d0e77753 Mon Sep 17 00:00:00 2001 From: Alan Jowett Date: Tue, 28 Jul 2026 14:15:28 -0700 Subject: [PATCH 2/6] Update reusable build reference in workflow --- .github/workflows/network-traffic-performance.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/network-traffic-performance.yml b/.github/workflows/network-traffic-performance.yml index 045ee61d..52f0b649 100644 --- a/.github/workflows/network-traffic-performance.yml +++ b/.github/workflows/network-traffic-performance.yml @@ -426,14 +426,14 @@ jobs: # Consider migrating to an organization-owned repository to avoid maintenance risks if the # personal account becomes unavailable. For now, this is the authoritative source for the # WinQuicEcho tool. - uses: Alan-Jowett/WinQuicEcho/.github/workflows/reusable-build.yml@53cd6c01279eb789f6b52218121c248088a0d608 + uses: Alan-Jowett/WinQuicEcho/.github/workflows/reusable-build.yml@41992af784788cc07fedd355c93633d60f7cb27a with: artifact_name: quic_echo_test config: 'Release' repository: 'Alan-Jowett/WinQuicEcho' # Pinned to the same audited commit as the workflow ref to prevent # arbitrary code execution via user-controlled inputs. - ref: '53cd6c01279eb789f6b52218121c248088a0d608' + ref: '41992af784788cc07fedd355c93633d60f7cb27a' test_quic_echo: if: ${{ inputs.test_tool == 'quicEcho' }} From 1a6659bc67eba798ad4cb51b4c781143c537d4ee Mon Sep 17 00:00:00 2001 From: Alan Jowett Date: Tue, 28 Jul 2026 14:36:00 -0700 Subject: [PATCH 3/6] fix: install MsQuic private kernel dependency Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/scripts/run-quic-echo-test.ps1 | 113 ++++++++++++++++++++++--- 1 file changed, 101 insertions(+), 12 deletions(-) diff --git a/.github/scripts/run-quic-echo-test.ps1 b/.github/scripts/run-quic-echo-test.ps1 index 456f0243..709b7b1d 100644 --- a/.github/scripts/run-quic-echo-test.ps1 +++ b/.github/scripts/run-quic-echo-test.ps1 @@ -202,6 +202,16 @@ function Get-QuicEchoKmDriverPath { return $driverPath } +function Get-MsQuicPrivDriverPath { + $toolRoot = Split-Path -Parent $scriptDir + $driverPath = Join-Path $toolRoot 'km\msquicpriv.sys' + if (-not (Test-Path -LiteralPath $driverPath)) { + throw "Required MsQuic kernel driver not found: $driverPath" + } + + return $driverPath +} + function Test-LocalTestSigningEnabled { $output = (& bcdedit /enum '{current}' 2>$null | Out-String) return $output -match '(?im)^\s*testsigning\s+Yes\s*$' @@ -233,6 +243,7 @@ function Prepare-WinQuicEchoKmDriver { param( [Parameter(Mandatory=$true)]$Session, [Parameter(Mandatory=$true)][string]$DriverSourcePath, + [Parameter(Mandatory=$true)][string]$MsQuicPrivDriverSourcePath, [Parameter(Mandatory=$true)][string]$RemoteDir ) @@ -242,6 +253,9 @@ function Prepare-WinQuicEchoKmDriver { if (-not (Test-RemoteTestSigningEnabled -Session $Session)) { throw 'Remote machine does not have test signing enabled. Enable it with "bcdedit /set testsigning on" and reboot.' } + if (-not (Test-Path -LiteralPath $MsQuicPrivDriverSourcePath)) { + throw "Required msquicpriv.sys not found at $MsQuicPrivDriverSourcePath" + } $signtoolPath = Get-SignToolPath @@ -338,6 +352,46 @@ function Ensure-MsQuicLoaded { } } +function Ensure-MsQuicPrivLoaded { + param( + [Parameter(Mandatory=$true)][string]$DriverPath, + [string]$Label = 'local' + ) + + $driverDest = Join-Path $env:SystemRoot 'System32\drivers\msquicpriv.sys' + $relativeDriverPath = 'system32\drivers\msquicpriv.sys' + $WriteFunc = if ($Label -eq 'local') { { param($m) Write-Phase $m } } else { { param($m) Write-Host $m } } + + if (-not (Test-Path -LiteralPath $DriverPath)) { + throw "Required msquicpriv.sys not found at $DriverPath" + } + + Copy-Item -LiteralPath $DriverPath -Destination $driverDest -Force + $svc = Get-Service -Name 'msquicpriv' -ErrorAction SilentlyContinue + if ($null -eq $svc) { + & $WriteFunc "Creating msquicpriv kernel service" + & sc.exe create msquicpriv type= kernel binPath= $driverDest start= demand | Out-Null + if ($LASTEXITCODE -ne 0) { + throw "sc create msquicpriv failed with exit code $LASTEXITCODE" + } + } + + Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\msquicpriv" -Name "ImagePath" -Value $relativeDriverPath + $svc = Get-Service -Name 'msquicpriv' -ErrorAction SilentlyContinue + if ($null -eq $svc) { + throw "msquicpriv service was not found after create" + } + if ($svc.Status -ne 'Running') { + & $WriteFunc "Starting msquicpriv service" + & sc.exe start msquicpriv 2>&1 + if ($LASTEXITCODE -ne 0) { + throw "sc start msquicpriv failed with exit code $LASTEXITCODE" + } + } else { + & $WriteFunc "msquicpriv service is already running" + } +} + function Get-WinQuicEchoServiceNames { $serviceNames = @( Get-Service -Name 'WinQuicEcho*' -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Name @@ -406,7 +460,10 @@ function Update-ServerArgument { } function Install-LocalWinQuicEchoKmDriver { - param([Parameter(Mandatory=$true)][string]$DriverSourcePath) + param( + [Parameter(Mandatory=$true)][string]$DriverSourcePath, + [Parameter(Mandatory=$true)][string]$MsQuicPrivDriverSourcePath + ) if (-not (Test-IsAdministrator)) { throw "Installing the WinQuicEcho kernel driver locally requires administrator privileges." @@ -416,6 +473,7 @@ function Install-LocalWinQuicEchoKmDriver { # Ensure msquic.sys is loaded (WinQuicEcho has PE import dependency on it) Ensure-MsQuicLoaded -Label 'local' + Ensure-MsQuicPrivLoaded -DriverPath $MsQuicPrivDriverSourcePath -Label 'local' # Stop any running WinQuicEcho instance, including prior fallback names. foreach ($name in Get-WinQuicEchoServiceNames) { @@ -453,14 +511,14 @@ function Install-LocalWinQuicEchoKmDriver { $svc = Get-Service -Name $name -ErrorAction SilentlyContinue if ($null -eq $svc) { Write-Phase "Creating local $name kernel service" - & sc.exe create $name type= kernel binPath= $driverDest start= demand depend= msquic | Out-Null + & sc.exe create $name type= kernel binPath= $driverDest start= demand depend= msquicpriv | Out-Null if ($LASTEXITCODE -eq 0) { Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\$name" -Name "ImagePath" -Value $relativeDriverPath $serviceName = $name; break } Write-Phase "sc create $name failed ($LASTEXITCODE); trying next name" } else { - & sc.exe config $name start= demand depend= msquic | Out-Null + & sc.exe config $name start= demand depend= msquicpriv | Out-Null if ($LASTEXITCODE -eq 0) { Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\$name" -Name "ImagePath" -Value $relativeDriverPath $serviceName = $name; Write-Phase "Reconfigured local $name service"; break @@ -471,7 +529,7 @@ function Install-LocalWinQuicEchoKmDriver { if ($null -eq $serviceName) { $uniqueName = "WinQuicEcho_$([guid]::NewGuid().ToString('N').Substring(0,8))" Write-Phase "All primary service names exhausted; creating $uniqueName" - & sc.exe create $uniqueName type= kernel binPath= $driverDest start= demand depend= msquic | Out-Null + & sc.exe create $uniqueName type= kernel binPath= $driverDest start= demand depend= msquicpriv | Out-Null if ($LASTEXITCODE -eq 0) { Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\$uniqueName" -Name "ImagePath" -Value $relativeDriverPath $serviceName = $uniqueName @@ -496,11 +554,13 @@ function Install-RemoteWinQuicEchoKmDriver { param( [Parameter(Mandatory=$true)]$Session, [Parameter(Mandatory=$true)][string]$DriverSourcePath, + [Parameter(Mandatory=$true)][string]$MsQuicPrivDriverSourcePath, [Parameter(Mandatory=$true)][string]$RemoteDir ) $remoteKmDir = Join-Path (Join-Path $RemoteDir 'quic_echo') 'km' $remoteDriverSourcePath = Join-Path $remoteKmDir 'winquicecho_km.sys' + $remoteMsQuicPrivSourcePath = Join-Path $remoteKmDir 'msquicpriv.sys' Invoke-Command -Session $Session -ArgumentList $remoteKmDir -ScriptBlock { param($kmDir) @@ -511,10 +571,12 @@ function Install-RemoteWinQuicEchoKmDriver { Write-Phase "Copying WinQuicEcho kernel driver to remote path $remoteDriverSourcePath" Copy-Item -ToSession $Session -LiteralPath $DriverSourcePath -Destination $remoteDriverSourcePath -Force + Write-Phase "Copying msquicpriv kernel driver to remote path $remoteMsQuicPrivSourcePath" + Copy-Item -ToSession $Session -LiteralPath $MsQuicPrivDriverSourcePath -Destination $remoteMsQuicPrivSourcePath -Force $remoteWinQuicEchoServiceNames = Get-WinQuicEchoServiceNames - Invoke-Command -Session $Session -ArgumentList $remoteDriverSourcePath, $remoteWinQuicEchoServiceNames -ScriptBlock { - param($driverSourcePath, $existingServiceNames) + Invoke-Command -Session $Session -ArgumentList $remoteDriverSourcePath, $remoteMsQuicPrivSourcePath, $remoteWinQuicEchoServiceNames -ScriptBlock { + param($driverSourcePath, $msquicPrivSourcePath, $existingServiceNames) function Ensure-RemoteMsQuicLoaded { param([Parameter(Mandatory=$true)][string]$MsQuicPath) @@ -618,6 +680,32 @@ function Install-RemoteWinQuicEchoKmDriver { $msquicSys = Join-Path $env:SystemRoot 'System32\drivers\msquic.sys' Ensure-RemoteMsQuicLoaded -MsQuicPath $msquicSys + $msquicPrivDest = Join-Path $env:SystemRoot 'System32\drivers\msquicpriv.sys' + if (-not (Test-Path -LiteralPath $msquicPrivSourcePath)) { + throw "Required msquicpriv.sys not found at $msquicPrivSourcePath" + } + Copy-Item -LiteralPath $msquicPrivSourcePath -Destination $msquicPrivDest -Force + $msquicPrivSvc = Get-Service -Name 'msquicpriv' -ErrorAction SilentlyContinue + if ($null -eq $msquicPrivSvc) { + Write-Host "Creating msquicpriv kernel service" + & sc.exe create msquicpriv type= kernel binPath= $msquicPrivDest start= demand | Out-Null + if ($LASTEXITCODE -ne 0) { + throw "Remote sc create msquicpriv failed with exit code $LASTEXITCODE" + } + } + Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\msquicpriv" -Name "ImagePath" -Value 'system32\drivers\msquicpriv.sys' + $msquicPrivSvc = Get-Service -Name 'msquicpriv' -ErrorAction SilentlyContinue + if ($null -eq $msquicPrivSvc) { + throw "Remote msquicpriv service was not found after create" + } + if ($msquicPrivSvc.Status -ne 'Running') { + Write-Host "Starting msquicpriv service" + & sc.exe start msquicpriv 2>&1 | ForEach-Object { Write-Host " $_" } + if ($LASTEXITCODE -ne 0) { + throw "Remote sc start msquicpriv failed with exit code $LASTEXITCODE" + } + } + # Stop any running WinQuicEcho instance, including prior fallback names. # Verify the stop succeeded before proceeding. $serviceNames = @($existingServiceNames) @@ -678,14 +766,14 @@ function Install-RemoteWinQuicEchoKmDriver { $svc = Get-Service -Name $name -ErrorAction SilentlyContinue if ($null -eq $svc) { Write-Host "Creating remote $name kernel service" - & sc.exe create $name type= kernel binPath= $driverDest start= demand depend= msquic | Out-Null + & sc.exe create $name type= kernel binPath= $driverDest start= demand depend= msquicpriv | Out-Null if ($LASTEXITCODE -eq 0) { Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\$name" -Name "ImagePath" -Value $relativeDriverPath $serviceName = $name; break } Write-Host "sc create $name failed ($LASTEXITCODE); trying next name" } else { - & sc.exe config $name start= demand depend= msquic | Out-Null + & sc.exe config $name start= demand depend= msquicpriv | Out-Null if ($LASTEXITCODE -eq 0) { Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\$name" -Name "ImagePath" -Value $relativeDriverPath $serviceName = $name; Write-Host "Reconfigured remote $name service"; break @@ -696,7 +784,7 @@ function Install-RemoteWinQuicEchoKmDriver { if ($null -eq $serviceName) { $uniqueName = "WinQuicEcho_$([guid]::NewGuid().ToString('N').Substring(0,8))" Write-Host "All primary service names exhausted; creating $uniqueName" - & sc.exe create $uniqueName type= kernel binPath= $driverDest start= demand depend= msquic | Out-Null + & sc.exe create $uniqueName type= kernel binPath= $driverDest start= demand depend= msquicpriv | Out-Null if ($LASTEXITCODE -eq 0) { Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\$uniqueName" -Name "ImagePath" -Value $relativeDriverPath $serviceName = $uniqueName @@ -1227,10 +1315,11 @@ try { $receiverBackend = Get-ReceiverBackend -Options $ReceiverOptions if ($receiverBackend -eq 'msquic-km') { $kmDriverPath = Get-QuicEchoKmDriverPath + $msquicPrivDriverPath = Get-MsQuicPrivDriverPath Write-Phase "Receiver backend is msquic-km; installing WinQuicEcho kernel driver locally and remotely" - Prepare-WinQuicEchoKmDriver -Session $Session -DriverSourcePath $kmDriverPath -RemoteDir $script:RemoteDir - Install-LocalWinQuicEchoKmDriver -DriverSourcePath $kmDriverPath - Install-RemoteWinQuicEchoKmDriver -Session $Session -DriverSourcePath $kmDriverPath -RemoteDir $script:RemoteDir + Prepare-WinQuicEchoKmDriver -Session $Session -DriverSourcePath $kmDriverPath -MsQuicPrivDriverSourcePath $msquicPrivDriverPath -RemoteDir $script:RemoteDir + Install-LocalWinQuicEchoKmDriver -DriverSourcePath $kmDriverPath -MsQuicPrivDriverSourcePath $msquicPrivDriverPath + Install-RemoteWinQuicEchoKmDriver -Session $Session -DriverSourcePath $kmDriverPath -MsQuicPrivDriverSourcePath $msquicPrivDriverPath -RemoteDir $script:RemoteDir } # Diagnostic: verify executables and msquic.dll are present locally and remotely From d46e677ef3e32cf2b3b3884de02d48e2fc2c4a7a Mon Sep 17 00:00:00 2001 From: Alan Jowett Date: Wed, 29 Jul 2026 14:53:28 -0700 Subject: [PATCH 4/6] fix: grant lab reset dispatch permission Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/network-traffic-performance.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/network-traffic-performance.yml b/.github/workflows/network-traffic-performance.yml index 52f0b649..78421687 100644 --- a/.github/workflows/network-traffic-performance.yml +++ b/.github/workflows/network-traffic-performance.yml @@ -412,6 +412,7 @@ jobs: if: ${{ always() && inputs.test_tool == 'ctsTraffic' }} permissions: actions: write + contents: write uses: microsoft/netperf/.github/workflows/schedule-lab-reset.yml@main with: workflowId: ${{ github.run_id }} @@ -680,6 +681,7 @@ jobs: if: ${{ always() && inputs.test_tool == 'quicEcho' }} permissions: actions: write + contents: write uses: microsoft/netperf/.github/workflows/schedule-lab-reset.yml@main with: workflowId: ${{ github.run_id }} From 90880dc2383a61d04ee9a500a282cbecd9415141 Mon Sep 17 00:00:00 2001 From: Alan Jowett Date: Wed, 29 Jul 2026 17:42:30 -0700 Subject: [PATCH 5/6] feat: make MsQuic driver installation optional Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/scripts/run-quic-echo-test.ps1 | 111 ++++++++++++++++-- .../workflows/network-traffic-performance.yml | 10 ++ 2 files changed, 109 insertions(+), 12 deletions(-) diff --git a/.github/scripts/run-quic-echo-test.ps1 b/.github/scripts/run-quic-echo-test.ps1 index 709b7b1d..f5db0c99 100644 --- a/.github/scripts/run-quic-echo-test.ps1 +++ b/.github/scripts/run-quic-echo-test.ps1 @@ -3,7 +3,8 @@ param( [string]$PeerName, [string]$SenderOptions, [string]$ReceiverOptions, - [string]$Duration = "60" + [string]$Duration = "60", + [switch]$InstallMsQuic ) Set-StrictMode -Version Latest @@ -212,6 +213,16 @@ function Get-MsQuicPrivDriverPath { return $driverPath } +function Get-MsQuicDriverPath { + $toolRoot = Split-Path -Parent $scriptDir + $driverPath = Join-Path $toolRoot 'km\msquic.sys' + if (-not (Test-Path -LiteralPath $driverPath)) { + throw "Requested MsQuic kernel driver not found: $driverPath" + } + + return $driverPath +} + function Test-LocalTestSigningEnabled { $output = (& bcdedit /enum '{current}' 2>$null | Out-String) return $output -match '(?im)^\s*testsigning\s+Yes\s*$' @@ -302,12 +313,34 @@ function Prepare-WinQuicEchoKmDriver { } function Ensure-MsQuicLoaded { - param([string]$Label = 'local') + param( + [string]$DriverSourcePath, + [string]$Label = 'local' + ) $msquicSys = Join-Path $env:SystemRoot 'System32\drivers\msquic.sys' $relativeMsQuicPath = 'system32\drivers\msquic.sys' $WriteFunc = if ($Label -eq 'local') { { param($m) Write-Phase $m } } else { { param($m) Write-Host $m } } + $svc = Get-Service -Name 'msquic' -ErrorAction SilentlyContinue + if ($DriverSourcePath) { + if (-not (Test-Path -LiteralPath $DriverSourcePath)) { + throw "Requested MsQuic kernel driver not found at $DriverSourcePath" + } + if ($null -ne $svc -and $svc.Status -eq 'Running') { + & $WriteFunc "Stopping msquic service to install the requested driver" + Stop-Service -Name 'msquic' -Force -ErrorAction Stop + $svc.WaitForStatus('Stopped', '00:00:30') + } + if (Test-Path -LiteralPath $msquicSys) { + $stale = "${msquicSys}.$([guid]::NewGuid().ToString('N')).os" + Move-Item -LiteralPath $msquicSys -Destination $stale -Force -ErrorAction Stop + & $WriteFunc "Moved the OS msquic.sys to $stale" + } + Copy-Item -LiteralPath $DriverSourcePath -Destination $msquicSys -Force -ErrorAction Stop + & $WriteFunc "Installed MsQuic driver from $DriverSourcePath" + } + # Check if msquic.sys file exists if (-not (Test-Path -LiteralPath $msquicSys)) { & $WriteFunc "Required msquic.sys not found at $msquicSys" @@ -462,7 +495,8 @@ function Update-ServerArgument { function Install-LocalWinQuicEchoKmDriver { param( [Parameter(Mandatory=$true)][string]$DriverSourcePath, - [Parameter(Mandatory=$true)][string]$MsQuicPrivDriverSourcePath + [Parameter(Mandatory=$true)][string]$MsQuicPrivDriverSourcePath, + [string]$MsQuicDriverSourcePath ) if (-not (Test-IsAdministrator)) { @@ -472,7 +506,7 @@ function Install-LocalWinQuicEchoKmDriver { $driverDest = Join-Path $env:SystemRoot 'System32\drivers\winquicecho_km.sys' # Ensure msquic.sys is loaded (WinQuicEcho has PE import dependency on it) - Ensure-MsQuicLoaded -Label 'local' + Ensure-MsQuicLoaded -DriverSourcePath $MsQuicDriverSourcePath -Label 'local' Ensure-MsQuicPrivLoaded -DriverPath $MsQuicPrivDriverSourcePath -Label 'local' # Stop any running WinQuicEcho instance, including prior fallback names. @@ -555,12 +589,14 @@ function Install-RemoteWinQuicEchoKmDriver { [Parameter(Mandatory=$true)]$Session, [Parameter(Mandatory=$true)][string]$DriverSourcePath, [Parameter(Mandatory=$true)][string]$MsQuicPrivDriverSourcePath, + [string]$MsQuicDriverSourcePath, [Parameter(Mandatory=$true)][string]$RemoteDir ) $remoteKmDir = Join-Path (Join-Path $RemoteDir 'quic_echo') 'km' $remoteDriverSourcePath = Join-Path $remoteKmDir 'winquicecho_km.sys' $remoteMsQuicPrivSourcePath = Join-Path $remoteKmDir 'msquicpriv.sys' + $remoteMsQuicSourcePath = Join-Path $remoteKmDir 'msquic.sys' Invoke-Command -Session $Session -ArgumentList $remoteKmDir -ScriptBlock { param($kmDir) @@ -573,16 +609,42 @@ function Install-RemoteWinQuicEchoKmDriver { Copy-Item -ToSession $Session -LiteralPath $DriverSourcePath -Destination $remoteDriverSourcePath -Force Write-Phase "Copying msquicpriv kernel driver to remote path $remoteMsQuicPrivSourcePath" Copy-Item -ToSession $Session -LiteralPath $MsQuicPrivDriverSourcePath -Destination $remoteMsQuicPrivSourcePath -Force + if ($MsQuicDriverSourcePath) { + Write-Phase "Copying MsQuic kernel driver to remote path $remoteMsQuicSourcePath" + Copy-Item -ToSession $Session -LiteralPath $MsQuicDriverSourcePath -Destination $remoteMsQuicSourcePath -Force + } $remoteWinQuicEchoServiceNames = Get-WinQuicEchoServiceNames - Invoke-Command -Session $Session -ArgumentList $remoteDriverSourcePath, $remoteMsQuicPrivSourcePath, $remoteWinQuicEchoServiceNames -ScriptBlock { - param($driverSourcePath, $msquicPrivSourcePath, $existingServiceNames) + Invoke-Command -Session $Session -ArgumentList $remoteDriverSourcePath, $remoteMsQuicPrivSourcePath, $remoteMsQuicSourcePath, $remoteWinQuicEchoServiceNames -ScriptBlock { + param($driverSourcePath, $msquicPrivSourcePath, $msquicSourcePath, $existingServiceNames) function Ensure-RemoteMsQuicLoaded { - param([Parameter(Mandatory=$true)][string]$MsQuicPath) + param( + [Parameter(Mandatory=$true)][string]$MsQuicPath, + [string]$DriverSourcePath + ) $relativeMsQuicPath = 'system32\drivers\msquic.sys' + $svc = Get-Service -Name 'msquic' -ErrorAction SilentlyContinue + if ($DriverSourcePath) { + if (-not (Test-Path -LiteralPath $DriverSourcePath)) { + throw "Requested MsQuic kernel driver not found at $DriverSourcePath" + } + if ($null -ne $svc -and $svc.Status -eq 'Running') { + Write-Host "Stopping msquic service to install the requested driver" + Stop-Service -Name 'msquic' -Force -ErrorAction Stop + $svc.WaitForStatus('Stopped', '00:00:30') + } + if (Test-Path -LiteralPath $MsQuicPath) { + $stale = "${MsQuicPath}.$([guid]::NewGuid().ToString('N')).os" + Move-Item -LiteralPath $MsQuicPath -Destination $stale -Force -ErrorAction Stop + Write-Host "Moved the OS msquic.sys to $stale" + } + Copy-Item -LiteralPath $DriverSourcePath -Destination $MsQuicPath -Force -ErrorAction Stop + Write-Host "Installed MsQuic driver from $DriverSourcePath" + } + if (-not (Test-Path -LiteralPath $MsQuicPath)) { Write-Host "Required msquic.sys not found at $MsQuicPath" $found = Get-ChildItem -Path "$env:SystemRoot\System32\drivers" -Filter 'msquic*' -ErrorAction SilentlyContinue @@ -624,10 +686,32 @@ function Install-RemoteWinQuicEchoKmDriver { } function Ensure-RemoteMsQuicLoaded { - param([Parameter(Mandatory=$true)][string]$MsQuicPath) + param( + [Parameter(Mandatory=$true)][string]$MsQuicPath, + [string]$DriverSourcePath + ) $relativeMsQuicPath = 'system32\drivers\msquic.sys' + $svc = Get-Service -Name 'msquic' -ErrorAction SilentlyContinue + if ($DriverSourcePath) { + if (-not (Test-Path -LiteralPath $DriverSourcePath)) { + throw "Requested MsQuic kernel driver not found at $DriverSourcePath" + } + if ($null -ne $svc -and $svc.Status -eq 'Running') { + Write-Host "Stopping msquic service to install the requested driver" + Stop-Service -Name 'msquic' -Force -ErrorAction Stop + $svc.WaitForStatus('Stopped', '00:00:30') + } + if (Test-Path -LiteralPath $MsQuicPath) { + $stale = "${MsQuicPath}.$([guid]::NewGuid().ToString('N')).os" + Move-Item -LiteralPath $MsQuicPath -Destination $stale -Force -ErrorAction Stop + Write-Host "Moved the OS msquic.sys to $stale" + } + Copy-Item -LiteralPath $DriverSourcePath -Destination $MsQuicPath -Force -ErrorAction Stop + Write-Host "Installed MsQuic driver from $DriverSourcePath" + } + if (-not (Test-Path -LiteralPath $MsQuicPath)) { Write-Host "Required msquic.sys not found at $MsQuicPath" $found = Get-ChildItem -Path "$env:SystemRoot\System32\drivers" -Filter 'msquic*' -ErrorAction SilentlyContinue @@ -678,7 +762,8 @@ function Install-RemoteWinQuicEchoKmDriver { # Ensure msquic.sys is loaded (WinQuicEcho has PE import dependency on it) $msquicSys = Join-Path $env:SystemRoot 'System32\drivers\msquic.sys' - Ensure-RemoteMsQuicLoaded -MsQuicPath $msquicSys + $msquicSource = if (Test-Path -LiteralPath $msquicSourcePath) { $msquicSourcePath } else { $null } + Ensure-RemoteMsQuicLoaded -MsQuicPath $msquicSys -DriverSourcePath $msquicSource $msquicPrivDest = Join-Path $env:SystemRoot 'System32\drivers\msquicpriv.sys' if (-not (Test-Path -LiteralPath $msquicPrivSourcePath)) { @@ -1316,10 +1401,12 @@ try { if ($receiverBackend -eq 'msquic-km') { $kmDriverPath = Get-QuicEchoKmDriverPath $msquicPrivDriverPath = Get-MsQuicPrivDriverPath - Write-Phase "Receiver backend is msquic-km; installing WinQuicEcho kernel driver locally and remotely" + $msquicDriverPath = if ($InstallMsQuic) { Get-MsQuicDriverPath } else { $null } + $msquicMode = if ($InstallMsQuic) { 'built MsQuic driver' } else { 'OS MsQuic driver' } + Write-Phase "Receiver backend is msquic-km; installing WinQuicEcho kernel driver locally and remotely using the $msquicMode" Prepare-WinQuicEchoKmDriver -Session $Session -DriverSourcePath $kmDriverPath -MsQuicPrivDriverSourcePath $msquicPrivDriverPath -RemoteDir $script:RemoteDir - Install-LocalWinQuicEchoKmDriver -DriverSourcePath $kmDriverPath -MsQuicPrivDriverSourcePath $msquicPrivDriverPath - Install-RemoteWinQuicEchoKmDriver -Session $Session -DriverSourcePath $kmDriverPath -MsQuicPrivDriverSourcePath $msquicPrivDriverPath -RemoteDir $script:RemoteDir + Install-LocalWinQuicEchoKmDriver -DriverSourcePath $kmDriverPath -MsQuicPrivDriverSourcePath $msquicPrivDriverPath -MsQuicDriverSourcePath $msquicDriverPath + Install-RemoteWinQuicEchoKmDriver -Session $Session -DriverSourcePath $kmDriverPath -MsQuicPrivDriverSourcePath $msquicPrivDriverPath -MsQuicDriverSourcePath $msquicDriverPath -RemoteDir $script:RemoteDir } # Diagnostic: verify executables and msquic.dll are present locally and remotely diff --git a/.github/workflows/network-traffic-performance.yml b/.github/workflows/network-traffic-performance.yml index 78421687..f5b35ce2 100644 --- a/.github/workflows/network-traffic-performance.yml +++ b/.github/workflows/network-traffic-performance.yml @@ -52,6 +52,11 @@ on: required: false default: '' type: string + install_msquic: + description: 'Install the MsQuic kernel driver from the test artifact instead of using the OS version' + required: false + default: false + type: boolean permissions: contents: read @@ -538,6 +543,7 @@ jobs: Write-Output " ref: ${{ inputs.ref }}" Write-Output " Duration: ${{ inputs.duration }}" Write-Output " RequestResponseSize: ${{ inputs.request_response_size }}" + Write-Output " InstallMsQuic: ${{ inputs.install_msquic }}" - name: Diagnostic - List files in quic_echo Release directory run: | @@ -565,6 +571,7 @@ jobs: MATRIX_SENDER_WARMUP: ${{ matrix.vec.sender_warmup }} RECEIVER_OPTIONS: ${{ inputs.receiver_options }} REQUEST_RESPONSE_SIZE: ${{ inputs.request_response_size }} + INSTALL_MSQUIC: ${{ inputs.install_msquic }} shell: pwsh run: | $scriptPath = '.\run-quic-echo-test.ps1' @@ -603,6 +610,9 @@ jobs: if ($env:PROFILE -eq 'true' -or $env:PROFILE -eq 'True' -or $env:PROFILE -eq 'TRUE' -or $env:PROFILE -eq $true) { $params.CpuProfile = $true } + if ($env:INSTALL_MSQUIC -eq 'true' -or $env:INSTALL_MSQUIC -eq 'True' -or $env:INSTALL_MSQUIC -eq 'TRUE' -or $env:INSTALL_MSQUIC -eq $true) { + $params.InstallMsQuic = $true + } Write-Output "Running: $scriptPath with parameters:" $params.GetEnumerator() | Sort-Object Name | ForEach-Object { Write-Output " $($_.Name)=$($_.Value)" } From 9cd0d7878c96761c643670f28ac5df227113bd1b Mon Sep 17 00:00:00 2001 From: Alan Jowett Date: Mon, 3 Aug 2026 10:25:19 -0700 Subject: [PATCH 6/6] chore: update WinQuicEcho percentile metrics Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/network-traffic-performance.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/network-traffic-performance.yml b/.github/workflows/network-traffic-performance.yml index f5b35ce2..793f7146 100644 --- a/.github/workflows/network-traffic-performance.yml +++ b/.github/workflows/network-traffic-performance.yml @@ -432,14 +432,14 @@ jobs: # Consider migrating to an organization-owned repository to avoid maintenance risks if the # personal account becomes unavailable. For now, this is the authoritative source for the # WinQuicEcho tool. - uses: Alan-Jowett/WinQuicEcho/.github/workflows/reusable-build.yml@41992af784788cc07fedd355c93633d60f7cb27a + uses: Alan-Jowett/WinQuicEcho/.github/workflows/reusable-build.yml@504b79cc4ac31140a2f1e47c1ce554090b84f4d3 with: artifact_name: quic_echo_test config: 'Release' repository: 'Alan-Jowett/WinQuicEcho' # Pinned to the same audited commit as the workflow ref to prevent # arbitrary code execution via user-controlled inputs. - ref: '41992af784788cc07fedd355c93633d60f7cb27a' + ref: '504b79cc4ac31140a2f1e47c1ce554090b84f4d3' test_quic_echo: if: ${{ inputs.test_tool == 'quicEcho' }}