When a FullUpdate produces zero visible peers (e.g., a restrictive policy isolates a node), the MapResponse has Peers: [] (empty non-nil). The Tailscale client only processes Peers as a full replacement when len(Peers) > 0 (controlclient/map.go:462), so an empty list is silently ignored and stale peers persist. This triggers when a FullUpdate() replaces a pending PolicyChange() in the batcher. The PolicyChange would have used computePeerDiff to send explicit PeersRemoved, but the FullUpdate goes through buildFromChange which sets Peers: [] that the client ignores. When a full update produces zero peers, compute the peer diff against lastSentPeers and add explicit PeersRemoved entries so the client correctly clears its stale peer state. |
||
|---|---|---|
| .. | ||
| batcher.go | ||
| batcher_bench_test.go | ||
| batcher_concurrency_test.go | ||
| batcher_scale_bench_test.go | ||
| batcher_test.go | ||
| batcher_unit_test.go | ||
| builder.go | ||
| builder_test.go | ||
| mapper.go | ||
| mapper_test.go | ||
| node_conn.go | ||
| tail_test.go | ||