This commit is contained in:
bluepython508 committed 2026-10-22 12:27:19 +01:00
1 parent 3530afb854
commit 6903fcff27
2146 files changed
+112256 -190703

No files matched your search

+76 -16
View File
@@ -1,4 +1,4 @@
// Copyright (c) Tailscale Inc & AUTHORS
// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause
// Package health is a registry for other packages to report & check
@@ -115,11 +115,11 @@ type Tracker struct {
lastMapPollEndedAt time.Time
lastStreamedMapResponse time.Time
lastNoiseDial time.Time
derpHomeRegion int
derpHomeRegion tailcfg.DERPRegionID
derpHomeless bool
derpRegionConnected map[int]bool
derpRegionHealthProblem map[int]string
derpRegionLastFrame map[int]time.Time
derpRegionConnected map[tailcfg.DERPRegionID]bool
derpRegionHealthProblem map[tailcfg.DERPRegionID]string
derpRegionLastFrame map[tailcfg.DERPRegionID]time.Time
derpMap *tailcfg.DERPMap // last DERP map from control, could be nil if never received one
lastMapRequestHeard time.Time // time we got a 200 from control for a MapRequest
ipnState string
@@ -132,6 +132,11 @@ type Tracker struct {
localLogConfigErr error
tlsConnectionErrors map[string]error // map[ServerName]error
metricHealthMessage any // nil or *metrics.MultiLabelMap[metricHealthMessageLabel]
// IP forwarding check
// If non-nil, called periodically to check if IP forwarding is broken.
// Should return true if broken, false if healthy.
isIPForwardingBroken func() bool
}
// NewTracker contructs a new [Tracker] and attaches the given eventbus.
@@ -348,6 +353,15 @@ func (t *Tracker) nil() bool {
return true
}
// ProbeLocks acquires and releases the tracker's internal mutex.
func (t *Tracker) ProbeLocks() {
if t.nil() {
return
}
t.mu.Lock()
t.mu.Unlock()
}
// Severity represents how serious an error is. Each GUI interprets this severity value in different ways,
// to surface the error in a more or less visible way. For instance, the macOS GUI could change its menubar
// icon to display an exclamation mark and present a modal notification for SeverityHigh warnings, but not
@@ -487,7 +501,12 @@ func (t *Tracker) SetHealthy(w *Warnable) {
}
func (t *Tracker) setHealthyLocked(w *Warnable) {
if !buildfeatures.HasHealth || t.warnableVal[w] == nil {
if !buildfeatures.HasHealth {
return
}
ws := t.warnableVal[w]
if ws == nil {
// Nothing to remove
return
}
@@ -496,15 +515,28 @@ func (t *Tracker) setHealthyLocked(w *Warnable) {
// Stop any pending visiblity timers for this Warnable
if canc, ok := t.pendingVisibleTimers[w]; ok {
// We removed the warningState for this Warnable,
// and we hold the lock, so even if the timer callback
// has already started, it won't find a warningState
// for this Warnable and won't publish any changes.
canc.Stop()
delete(t.pendingVisibleTimers, w)
}
change := Change{
WarnableChanged: true,
Warnable: w,
// Only publish a change if the Warnable was unhealthy long
// enough to become visible to the user. Otherwise, it would
// not have been published as unhealthy, so there is no need
// to publish it as healthy. This prevents eventbus (and by
// extension the IPN bus) churn for Warnables that are marked
// unhealthy and then healthy again. Notably, this includes
// warnables touched by [Tracker.updateBuiltinWarnablesLocked].
if w.IsVisible(ws, t.now) {
change := Change{
WarnableChanged: true,
Warnable: w,
}
t.changePub.Publish(change)
}
t.changePub.Publish(change)
}
// notifyWatchersControlChangedLocked calls each watcher to signal that control
@@ -750,7 +782,7 @@ func (t *Tracker) GetInPollNetMap() bool {
//
// The homeless parameter is whether magicsock is running in DERP-disconnected
// mode, without discovering and maintaining a connection to its home DERP.
func (t *Tracker) SetMagicSockDERPHome(region int, homeless bool) {
func (t *Tracker) SetMagicSockDERPHome(region tailcfg.DERPRegionID, homeless bool) {
if t.nil() {
return
}
@@ -777,7 +809,7 @@ func (t *Tracker) NoteMapRequestHeard(mr *tailcfg.MapRequest) {
t.selfCheckLocked()
}
func (t *Tracker) SetDERPRegionConnectedState(region int, connected bool) {
func (t *Tracker) SetDERPRegionConnectedState(region tailcfg.DERPRegionID, connected bool) {
if t.nil() {
return
}
@@ -789,7 +821,7 @@ func (t *Tracker) SetDERPRegionConnectedState(region int, connected bool) {
// SetDERPRegionHealth sets or clears any problem associated with the
// provided DERP region.
func (t *Tracker) SetDERPRegionHealth(region int, problem string) {
func (t *Tracker) SetDERPRegionHealth(region tailcfg.DERPRegionID, problem string) {
if t.nil() {
return
}
@@ -805,7 +837,7 @@ func (t *Tracker) SetDERPRegionHealth(region int, problem string) {
// NoteDERPRegionReceivedFrame is called to note that a frame was received from
// the given DERP region at the current time.
func (t *Tracker) NoteDERPRegionReceivedFrame(region int) {
func (t *Tracker) NoteDERPRegionReceivedFrame(region tailcfg.DERPRegionID) {
if t.nil() {
return
}
@@ -818,7 +850,7 @@ func (t *Tracker) NoteDERPRegionReceivedFrame(region int) {
// GetDERPRegionReceivedTime returns the last time that a frame was received
// from the given DERP region, or the zero time if no communication with that
// region has occurred.
func (t *Tracker) GetDERPRegionReceivedTime(region int) time.Time {
func (t *Tracker) GetDERPRegionReceivedTime(region tailcfg.DERPRegionID) time.Time {
if t.nil() {
return time.Time{}
}
@@ -841,7 +873,7 @@ func (t *Tracker) SetDERPMap(dm *tailcfg.DERPMap) {
// derpRegionNameLocked returns the name of the DERP region with the given ID
// or the empty string if unknown.
func (t *Tracker) derpRegionNameLocked(regID int) string {
func (t *Tracker) derpRegionNameLocked(regID tailcfg.DERPRegionID) string {
if t.derpMap == nil {
return ""
}
@@ -1097,6 +1129,8 @@ func (t *Tracker) updateBuiltinWarnablesLocked() {
t.setHealthyLocked(NetworkStatusWarnable)
}
t.updateIPForwardingWarnableLocked()
if t.localLogConfigErr != nil {
t.setUnhealthyLocked(localLogWarnable, Args{
ArgError: t.localLogConfigErr.Error(),
@@ -1389,3 +1423,29 @@ func (t *Tracker) LastNoiseDialWasRecent() bool {
t.lastNoiseDial = now
return dur < 2*time.Minute
}
// SetIPForwardingCheck sets the function to check if IP forwarding is broken.
// The function should return true if IP forwarding is broken, false if healthy.
// Pass nil to disable IP forwarding checks.
func (t *Tracker) SetIPForwardingCheck(checkFunc func() bool) {
if t.nil() {
return
}
t.mu.Lock()
defer t.mu.Unlock()
t.isIPForwardingBroken = checkFunc
// Run an immediate check to set initial state
t.updateIPForwardingWarnableLocked()
}
// updateIPForwardingWarnableLocked checks the IP forwarding state and
// sets or clears the ipForwardingWarnable accordingly.
func (t *Tracker) updateIPForwardingWarnableLocked() {
if t.isIPForwardingBroken != nil && t.isIPForwardingBroken() {
t.setUnhealthyLocked(ipForwardingWarnable, Args{})
} else {
t.setHealthyLocked(ipForwardingWarnable)
}
}