ipn/{ipnlocal,localapi},wgengine{,/magicsock}: plumb health.Tracker

Down to 25 health.Global users. After this remains controlclient &
net/dns & wgengine/router.

Updates #11874
Updates #4136

Change-Id: I6dd1856e3d9bf523bdd44b60fb3b8f7501d5dc0d
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2024-04-26 08:06:06 -07:00
committed by Brad Fitzpatrick
parent df8f40905b
commit 6d69fc137f
15 changed files with 79 additions and 46 deletions
+12 -12
View File
@@ -165,7 +165,7 @@ func (c *Conn) maybeSetNearestDERP(report *netcheck.Report) (preferredDERP int)
if testenv.InTest() && !checkControlHealthDuringNearestDERPInTests {
connectedToControl = true
} else {
connectedToControl = health.Global.GetInPollNetMap()
connectedToControl = c.health.GetInPollNetMap()
}
if !connectedToControl {
c.mu.Lock()
@@ -201,12 +201,12 @@ func (c *Conn) setNearestDERP(derpNum int) (wantDERP bool) {
defer c.mu.Unlock()
if !c.wantDerpLocked() {
c.myDerp = 0
health.Global.SetMagicSockDERPHome(0, c.homeless)
c.health.SetMagicSockDERPHome(0, c.homeless)
return false
}
if c.homeless {
c.myDerp = 0
health.Global.SetMagicSockDERPHome(0, c.homeless)
c.health.SetMagicSockDERPHome(0, c.homeless)
return false
}
if derpNum == c.myDerp {
@@ -217,7 +217,7 @@ func (c *Conn) setNearestDERP(derpNum int) (wantDERP bool) {
metricDERPHomeChange.Add(1)
}
c.myDerp = derpNum
health.Global.SetMagicSockDERPHome(derpNum, c.homeless)
c.health.SetMagicSockDERPHome(derpNum, c.homeless)
if c.privateKey.IsZero() {
// No private key yet, so DERP connections won't come up anyway.
@@ -400,7 +400,7 @@ func (c *Conn) derpWriteChanOfAddr(addr netip.AddrPort, peer key.NodePublic) cha
}
return derpMap.Regions[regionID]
})
dc.HealthTracker = health.Global
dc.HealthTracker = c.health
dc.SetCanAckPings(true)
dc.NotePreferred(c.myDerp == regionID)
@@ -526,8 +526,8 @@ func (c *Conn) runDerpReader(ctx context.Context, derpFakeAddr netip.AddrPort, d
return n
}
defer health.Global.SetDERPRegionConnectedState(regionID, false)
defer health.Global.SetDERPRegionHealth(regionID, "")
defer c.health.SetDERPRegionConnectedState(regionID, false)
defer c.health.SetDERPRegionHealth(regionID, "")
// peerPresent is the set of senders we know are present on this
// connection, based on messages we've received from the server.
@@ -539,7 +539,7 @@ func (c *Conn) runDerpReader(ctx context.Context, derpFakeAddr netip.AddrPort, d
for {
msg, connGen, err := dc.RecvDetail()
if err != nil {
health.Global.SetDERPRegionConnectedState(regionID, false)
c.health.SetDERPRegionConnectedState(regionID, false)
// Forget that all these peers have routes.
for peer := range peerPresent {
delete(peerPresent, peer)
@@ -577,14 +577,14 @@ func (c *Conn) runDerpReader(ctx context.Context, derpFakeAddr netip.AddrPort, d
now := time.Now()
if lastPacketTime.IsZero() || now.Sub(lastPacketTime) > frameReceiveRecordRate {
health.Global.NoteDERPRegionReceivedFrame(regionID)
c.health.NoteDERPRegionReceivedFrame(regionID)
lastPacketTime = now
}
switch m := msg.(type) {
case derp.ServerInfoMessage:
health.Global.SetDERPRegionConnectedState(regionID, true)
health.Global.SetDERPRegionHealth(regionID, "") // until declared otherwise
c.health.SetDERPRegionConnectedState(regionID, true)
c.health.SetDERPRegionHealth(regionID, "") // until declared otherwise
c.logf("magicsock: derp-%d connected; connGen=%v", regionID, connGen)
continue
case derp.ReceivedPacket:
@@ -624,7 +624,7 @@ func (c *Conn) runDerpReader(ctx context.Context, derpFakeAddr netip.AddrPort, d
}()
continue
case derp.HealthMessage:
health.Global.SetDERPRegionHealth(regionID, m.Problem)
c.health.SetDERPRegionHealth(regionID, m.Problem)
continue
case derp.PeerGoneMessage:
switch m.Reason {
+10 -4
View File
@@ -91,6 +91,7 @@ type Conn struct {
testOnlyPacketListener nettype.PacketListener
noteRecvActivity func(key.NodePublic) // or nil, see Options.NoteRecvActivity
netMon *netmon.Monitor // or nil
health *health.Tracker // or nil
controlKnobs *controlknobs.Knobs // or nil
// ================================================================
@@ -369,9 +370,13 @@ type Options struct {
NoteRecvActivity func(key.NodePublic)
// NetMon is the network monitor to use.
// With one, the portmapper won't be used.
// If nil, the portmapper won't be used.
NetMon *netmon.Monitor
// HealthTracker optionally specifies the health tracker to
// report errors and warnings to.
HealthTracker *health.Tracker
// ControlKnobs are the set of control knobs to use.
// If nil, they're ignored and not updated.
ControlKnobs *controlknobs.Knobs
@@ -463,6 +468,7 @@ func NewConn(opts Options) (*Conn, error) {
c.portMapper.SetGatewayLookupFunc(opts.NetMon.GatewayAndSelfIP)
}
c.netMon = opts.NetMon
c.health = opts.HealthTracker
c.onPortUpdate = opts.OnPortUpdate
c.getPeerByKey = opts.PeerByKeyFunc
@@ -666,7 +672,7 @@ func (c *Conn) updateNetInfo(ctx context.Context) (*netcheck.Report, error) {
// NOTE(andrew-d): I don't love that we're depending on the
// health package here, but I'd rather do that and not store
// the exact same state in two different places.
GetLastDERPActivity: health.Global.GetDERPRegionReceivedTime,
GetLastDERPActivity: c.health.GetDERPRegionReceivedTime,
})
if err != nil {
return nil, err
@@ -2471,7 +2477,7 @@ func (c *Conn) bindSocket(ruc *RebindingUDPConn, network string, curPortFate cur
}
ruc.setConnLocked(pconn, network, c.bind.BatchSize())
if network == "udp4" {
health.Global.SetUDP4Unbound(false)
c.health.SetUDP4Unbound(false)
}
return nil
}
@@ -2482,7 +2488,7 @@ func (c *Conn) bindSocket(ruc *RebindingUDPConn, network string, curPortFate cur
// we get a link change and we can try binding again.
ruc.setConnLocked(newBlockForeverConn(), "", c.bind.BatchSize())
if network == "udp4" {
health.Global.SetUDP4Unbound(true)
c.health.SetUDP4Unbound(true)
}
return fmt.Errorf("failed to bind any ports (tried %v)", ports)
}
+7 -5
View File
@@ -3113,21 +3113,23 @@ func TestMaybeSetNearestDERP(t *testing.T) {
}
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
ht := new(health.Tracker)
c := newConn()
c.logf = t.Logf
c.myDerp = tt.old
c.derpMap = derpMap
c.health = ht
report := &netcheck.Report{PreferredDERP: tt.reportDERP}
oldConnected := health.Global.GetInPollNetMap()
oldConnected := ht.GetInPollNetMap()
if tt.connectedToControl != oldConnected {
if tt.connectedToControl {
health.Global.GotStreamedMapResponse()
t.Cleanup(health.Global.SetOutOfPollNetMap)
ht.GotStreamedMapResponse()
t.Cleanup(ht.SetOutOfPollNetMap)
} else {
health.Global.SetOutOfPollNetMap()
t.Cleanup(health.Global.GotStreamedMapResponse)
ht.SetOutOfPollNetMap()
t.Cleanup(ht.GotStreamedMapResponse)
}
}