Public/Start-BfdSession.ps1
|
function Start-BfdSession { <# .SYNOPSIS Starts a single-hop BFD session (UDP, TTL 255, source port 49152-65535). .PARAMETER ListenPort Local UDP port to receive on (3784 normally). .PARAMETER Port Remote UDP port to send to (3784 normally). #> [CmdletBinding()] param( [Parameter(Mandatory)][string]$RemoteAddress, [string]$Name, [int]$Port = 3784, [int]$ListenPort = 3784, [uint32]$DesiredMinTxMs = 500, [uint32]$RequiredMinRxMs = 500, [ValidateRange(1, 255)][int]$DetectMult = 3 ) if (-not $Name) { $Name = $RemoteAddress } $reg = Get-PowerBgpRegistry $existing = $reg.Bfd[$Name] if ($existing -and $existing.State -ne 'Stopped') { throw "BFD session '$Name' already exists." } $S = [hashtable]::Synchronized(@{ Name = $Name Config = [pscustomobject]@{ RemoteAddress = $RemoteAddress; RemotePort = $Port; ListenPort = $ListenPort DesiredMinTx = $DesiredMinTxMs * 1000; RequiredMinRx = $RequiredMinRxMs * 1000; DetectMult = $DetectMult } State = 'Down' RemoteState = $null Stop = $false Suppress = $false Sent = 0 Received = 0 LocalDiscriminator = 0 LastError = $null History = [System.Collections.Concurrent.ConcurrentQueue[string]]::new() PowerShell = $null Handle = $null }) $reg.Bfd[$Name] = $S Start-PowerBgpRunspace -State $S -Entry 'Invoke-BfdSessionLoop' Get-BfdSession -Name $Name } function Get-BfdSession { [CmdletBinding()] param([string]$Name = '*') foreach ($S in @((Get-PowerBgpRegistry).Bfd.Values)) { if ($S.Name -notlike $Name) { continue } [pscustomobject]@{ PSTypeName = 'PowerBGP.BfdSession' Name = $S.Name State = $S.State RemoteState = $S.RemoteState Remote = '{0}:{1}' -f $S.Config.RemoteAddress, $S.Config.RemotePort TxMs = $S.Config.DesiredMinTx / 1000 RxMs = $S.Config.RequiredMinRx / 1000 DetectMult = $S.Config.DetectMult Sent = $S.Sent Received = $S.Received Suppressed = [bool]$S.Suppress LastError = $S.LastError History = $S.History.ToArray() } } } function Stop-BfdSession { <# .SYNOPSIS Stops a BFD session. It stays configured (State 'Stopped') so Resume-BfdSession can restart it; use Remove-BfdSession to delete it. #> [CmdletBinding()] param([Parameter(Mandatory, ValueFromPipelineByPropertyName)][string]$Name) process { $S = (Get-PowerBgpRegistry).Bfd[$Name] if (-not $S) { Write-Error "No such BFD session '$Name'."; return } Stop-PowerBgpRunspace $S $S.State = 'Stopped' } } function Resume-BfdSession { [CmdletBinding()] param([Parameter(Mandatory, ValueFromPipelineByPropertyName)][string]$Name) process { $old = (Get-PowerBgpRegistry).Bfd[$Name] if (-not $old) { Write-Error "No such BFD session '$Name'."; return } $c = $old.Config $null = Start-BfdSession -Name $Name -RemoteAddress $c.RemoteAddress -Port $c.RemotePort -ListenPort $c.ListenPort ` -DesiredMinTxMs ($c.DesiredMinTx / 1000) -RequiredMinRxMs ($c.RequiredMinRx / 1000) -DetectMult $c.DetectMult Get-BfdSession -Name $Name } } function Update-BfdSession { <# .SYNOPSIS Changes a BFD session's stored settings. A running session is restarted (it goes Down and renegotiates). #> [CmdletBinding()] param( [Parameter(Mandatory)][string]$Name, [int]$Port, [int]$ListenPort, [uint32]$DesiredMinTxMs, [uint32]$RequiredMinRxMs, [ValidateRange(1, 255)][int]$DetectMult ) $S = (Get-PowerBgpRegistry).Bfd[$Name] if (-not $S) { throw "No such BFD session '$Name'." } $wasRunning = $S.State -ne 'Stopped' if ($wasRunning) { Stop-BfdSession -Name $Name } $c = $S.Config if ($PSBoundParameters.ContainsKey('Port')) { $c.RemotePort = $Port } if ($PSBoundParameters.ContainsKey('ListenPort')) { $c.ListenPort = $ListenPort } if ($PSBoundParameters.ContainsKey('DesiredMinTxMs')) { $c.DesiredMinTx = $DesiredMinTxMs * 1000 } if ($PSBoundParameters.ContainsKey('RequiredMinRxMs')) { $c.RequiredMinRx = $RequiredMinRxMs * 1000 } if ($PSBoundParameters.ContainsKey('DetectMult')) { $c.DetectMult = $DetectMult } if ($wasRunning) { Resume-BfdSession -Name $Name } else { Get-BfdSession -Name $Name } } function Remove-BfdSession { [CmdletBinding(SupportsShouldProcess)] param([Parameter(Mandatory, ValueFromPipelineByPropertyName)][string]$Name) process { $reg = Get-PowerBgpRegistry $S = $reg.Bfd[$Name] if (-not $S) { Write-Error "No such BFD session '$Name'."; return } if ($PSCmdlet.ShouldProcess($Name, 'Remove BFD session')) { Stop-PowerBgpRunspace $S $reg.Bfd.Remove($Name) } } } function Set-BfdSession { <# .SYNOPSIS Fault injection: -Suppress $true stops sending BFD control packets while the session object stays alive. #> [CmdletBinding()] param([Parameter(Mandatory)][string]$Name, [Parameter(Mandatory)][bool]$Suppress) $S = (Get-PowerBgpRegistry).Bfd[$Name] if (-not $S) { throw "No such BFD session '$Name'." } $S.Suppress = $Suppress } |