diff options
| author | Brad Fitzpatrick <bradfitz@tailscale.com> | 2025-09-09 13:18:25 -0700 |
|---|---|---|
| committer | Brad Fitzpatrick <bradfitz@tailscale.com> | 2025-09-09 13:18:25 -0700 |
| commit | a9c7aa702c98e678eda0dfa251eccb91dc9ce06d (patch) | |
| tree | c7667c361282ecc97713ed01eb0f79747b8accdb | |
| parent | 77250a301aee83d67c1bbe497391500f7c70e7b4 (diff) | |
| download | tailscale-bradfitz/lite-on-restart.tar.xz tailscale-bradfitz/lite-on-restart.zip | |
control/controlclient: don't send dup lite map update requestsbradfitz/lite-on-restart
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>
| -rw-r--r-- | control/controlclient/direct.go | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/control/controlclient/direct.go b/control/controlclient/direct.go index 47283a673..99d1df992 100644 --- a/control/controlclient/direct.go +++ b/control/controlclient/direct.go @@ -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) |
