control/controlclient: don't send dup lite map update requests

On control server connection break, the updateRoutine loops and sends
the same lite update.

This stops that, to be nicer to the server.

Updates tailscale/corp#32114

Change-Id: I3acf4b5de4514cd4ce109a31cc424d916bdeba3f
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
bradfitz/lite-on-restart
Brad Fitzpatrick 3 months ago
parent 77250a301a
commit a9c7aa702c

@ -8,6 +8,7 @@ import (
"bytes"
"cmp"
"context"
"crypto/sha256"
"encoding/binary"
"encoding/json"
"errors"
@ -93,6 +94,7 @@ type Direct struct {
mu sync.Mutex // mutex guards the following fields
serverLegacyKey key.MachinePublic // original ("legacy") nacl crypto_box-based public key; only used for signRegisterRequest on Windows now
serverNoiseKey key.MachinePublic
lastLiteHash [sha256.Size]byte // last hash of lite map request we sent to control for which we got a 200 OK
sfGroup singleflight.Group[struct{}, *NoiseClient] // protects noiseClient creation.
noiseClient *NoiseClient
@ -939,6 +941,12 @@ func (c *Direct) sendMapRequest(ctx context.Context, isStreaming bool, nu Netmap
return err
}
bodyHash := sha256.Sum256(bodyData)
if !isStreaming && nu == nil && c.lastLiteHashEquals(bodyHash) {
vlogf("netmap: skipping lite update; previous was identical and succeeded")
return nil
}
ctx, cancel := context.WithCancel(ctx)
defer cancel()
@ -1000,6 +1008,10 @@ func (c *Direct) sendMapRequest(ctx context.Context, isStreaming bool, nu Netmap
watchdogTimer.Reset(watchdogTimeout)
if nu == nil {
c.mu.Lock()
c.lastLiteHash = bodyHash
c.mu.Unlock()
io.Copy(io.Discard, res.Body)
return nil
}
@ -1138,6 +1150,14 @@ func (c *Direct) sendMapRequest(ctx context.Context, isStreaming bool, nu Netmap
return nil
}
// lastLiteHashEquals reports whether the last sent lite map request hash
// is equal to the given hash.
func (c *Direct) lastLiteHashEquals(hash [sha256.Size]byte) bool {
c.mu.Lock()
defer c.mu.Unlock()
return c.lastLiteHash == hash
}
func (c *Direct) handleDebugMessage(ctx context.Context, debug *tailcfg.Debug) error {
if code := debug.Exit; code != nil {
c.logf("exiting process with status %v per controlplane", *code)

Loading…
Cancel
Save