|
|
|
@@ -426,6 +426,7 @@ type vpnFabricSessionDialStats struct {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type vpnFabricEndpointObservationStore struct {
|
|
|
|
|
reporterNodeID string
|
|
|
|
|
mu sync.Mutex
|
|
|
|
|
observations map[string]mesh.EndpointCandidateHealthObservation
|
|
|
|
|
}
|
|
|
|
@@ -434,8 +435,13 @@ func newVPNFabricSessionDialStats() *vpnFabricSessionDialStats {
|
|
|
|
|
return &vpnFabricSessionDialStats{}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func newVPNFabricEndpointObservationStore() *vpnFabricEndpointObservationStore {
|
|
|
|
|
func newVPNFabricEndpointObservationStore(reporterNodeID ...string) *vpnFabricEndpointObservationStore {
|
|
|
|
|
nodeID := ""
|
|
|
|
|
if len(reporterNodeID) > 0 {
|
|
|
|
|
nodeID = strings.TrimSpace(reporterNodeID[0])
|
|
|
|
|
}
|
|
|
|
|
return &vpnFabricEndpointObservationStore{
|
|
|
|
|
reporterNodeID: nodeID,
|
|
|
|
|
observations: map[string]mesh.EndpointCandidateHealthObservation{},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -533,6 +539,8 @@ func (s *vpnFabricEndpointObservationStore) ObserveSuccess(endpointID string, la
|
|
|
|
|
defer s.mu.Unlock()
|
|
|
|
|
observation := s.observations[endpointID]
|
|
|
|
|
observation.EndpointID = endpointID
|
|
|
|
|
observation.Source = "local_vpn_fabric_session"
|
|
|
|
|
observation.ReporterNodeID = s.reporterNodeID
|
|
|
|
|
observation.SuccessCount++
|
|
|
|
|
observation.LastLatencyMs = latency.Milliseconds()
|
|
|
|
|
observation.ReliabilityScore = 100
|
|
|
|
@@ -550,6 +558,8 @@ func (s *vpnFabricEndpointObservationStore) ObserveFailure(endpointID string, re
|
|
|
|
|
defer s.mu.Unlock()
|
|
|
|
|
observation := s.observations[endpointID]
|
|
|
|
|
observation.EndpointID = endpointID
|
|
|
|
|
observation.Source = "local_vpn_fabric_session"
|
|
|
|
|
observation.ReporterNodeID = s.reporterNodeID
|
|
|
|
|
observation.FailureCount++
|
|
|
|
|
observation.LastFailureReason = strings.TrimSpace(reason)
|
|
|
|
|
observation.ReliabilityScore = 35
|
|
|
|
@@ -1082,7 +1092,7 @@ func startSyntheticMeshEndpoint(ctx context.Context, _ context.CancelFunc, cfg c
|
|
|
|
|
VPNFabricSessionPeers: vpnFabricSessionPeers,
|
|
|
|
|
VPNFabricTransport: mesh.NewWebSocketFabricTransport(vpnFabricSessionPeers),
|
|
|
|
|
VPNFabricSessionDialStats: newVPNFabricSessionDialStats(),
|
|
|
|
|
VPNFabricEndpointObservations: newVPNFabricEndpointObservationStore(),
|
|
|
|
|
VPNFabricEndpointObservations: newVPNFabricEndpointObservationStore(identity.NodeID),
|
|
|
|
|
PeerEndpoints: copyStringMap(peerEndpoints),
|
|
|
|
|
PeerEndpointCandidates: copyPeerEndpointCandidatesMap(loadedConfig.PeerEndpointCandidates),
|
|
|
|
|
PeerEndpointObservations: copyEndpointCandidateObservations(loadedConfig.PeerEndpointObservations),
|
|
|
|
@@ -1983,7 +1993,7 @@ func applyRefreshedSyntheticMeshConfig(ctx context.Context, cfg config.Config, i
|
|
|
|
|
meshState.VPNFabricSessionDialStats = newVPNFabricSessionDialStats()
|
|
|
|
|
}
|
|
|
|
|
if meshState.VPNFabricEndpointObservations == nil {
|
|
|
|
|
meshState.VPNFabricEndpointObservations = newVPNFabricEndpointObservationStore()
|
|
|
|
|
meshState.VPNFabricEndpointObservations = newVPNFabricEndpointObservationStore(identity.NodeID)
|
|
|
|
|
}
|
|
|
|
|
meshState.PeerEndpoints = copyStringMap(loadedConfig.PeerEndpoints)
|
|
|
|
|
meshState.PeerEndpointCandidates = copyPeerEndpointCandidatesMap(loadedConfig.PeerEndpointCandidates)
|
|
|
|
@@ -2303,6 +2313,8 @@ func endpointCandidateObservationsFromControlPlane(observations map[string]clien
|
|
|
|
|
}
|
|
|
|
|
out[endpointID] = mesh.EndpointCandidateHealthObservation{
|
|
|
|
|
EndpointID: firstNonEmpty(strings.TrimSpace(item.EndpointID), endpointID),
|
|
|
|
|
Source: item.Source,
|
|
|
|
|
ReporterNodeID: item.ReporterNodeID,
|
|
|
|
|
LastLatencyMs: item.LastLatencyMs,
|
|
|
|
|
SuccessCount: item.SuccessCount,
|
|
|
|
|
FailureCount: item.FailureCount,
|
|
|
|
@@ -2948,7 +2960,7 @@ func heartbeatPayload(cfg config.Config, identity state.Identity, meshState *syn
|
|
|
|
|
if meshState != nil && meshState.VPNFabricEndpointObservations != nil {
|
|
|
|
|
payload.Metadata["vpn_fabric_endpoint_health_report"] = meshState.VPNFabricEndpointObservations.Report(observedAt, maxVPNFabricEndpointHealthReportEntries)
|
|
|
|
|
} else {
|
|
|
|
|
payload.Metadata["vpn_fabric_endpoint_health_report"] = newVPNFabricEndpointObservationStore().Report(observedAt, maxVPNFabricEndpointHealthReportEntries)
|
|
|
|
|
payload.Metadata["vpn_fabric_endpoint_health_report"] = newVPNFabricEndpointObservationStore(identity.NodeID).Report(observedAt, maxVPNFabricEndpointHealthReportEntries)
|
|
|
|
|
}
|
|
|
|
|
payload.Capabilities["vpn_fabric_endpoint_health_feedback"] = true
|
|
|
|
|
}
|
|
|
|
@@ -4953,7 +4965,7 @@ func fabricSessionGatewayTransportForAssignment(ctx context.Context, identity st
|
|
|
|
|
meshState.VPNFabricSessionDialStats = newVPNFabricSessionDialStats()
|
|
|
|
|
}
|
|
|
|
|
if meshState.VPNFabricEndpointObservations == nil {
|
|
|
|
|
meshState.VPNFabricEndpointObservations = newVPNFabricEndpointObservationStore()
|
|
|
|
|
meshState.VPNFabricEndpointObservations = newVPNFabricEndpointObservationStore(identity.NodeID)
|
|
|
|
|
}
|
|
|
|
|
meshState.VPNFabricSessionDialStats.Attempts.Add(1)
|
|
|
|
|
if meshState.VPNFabricSessionPeers == nil {
|
|
|
|
|