ipn/ipnlocal,wgengine/magicsock: re-report NetInfo to new control client (#20025)
magicsock de-duplicates NetInfo callbacks against c.netInfoLast, a cache that lives on the long-lived magicsock.Conn. That cache survives a control client swap (interactive login or profile switch), where only the control client (and its own per-client NetInfo dedup) is replaced. As a result, the first netcheck after the swap produces a structurally-identical NetInfo (same PreferredDERP, same NAT shape), magicsock suppresses it as unchanged, and the new control session never learns our home DERP. Peers can't reach the node over DERP until some unrelated NetInfo field happens to change. Add Conn.ResetNetInfoLast to clear the dedup cache, and call it from LocalBackend.setControlClientLocked whenever a control client is installed, so the next netcheck re-reports the current NetInfo to the new client. netInfoLast is only a dedup/optimization cache (all readers nil-guard, and it is recomputed by every netcheck), so clearing it can only add a delivery, never lose or misroute one; it is scoped to control-client lifecycle events, not steady-state operation. Updates #17887 Fixes #20024 Signed-off-by: Mike O'Driscoll <mikeo@tailscale.com>
This commit is contained in:
@@ -6696,6 +6696,12 @@ func (b *LocalBackend) setControlClientLocked(cc controlclient.Client) {
|
||||
b.cc = cc
|
||||
b.ccAuto, _ = cc.(*controlclient.Auto)
|
||||
b.ignoreControlClientUpdates.Store(cc == nil)
|
||||
|
||||
// magicsock de-dupes NetInfo against a cache that outlives the control
|
||||
// client; clear it on (re)install so the next netcheck re-reports our
|
||||
// NetInfo (notably PreferredDERP, our home DERP) to the new client rather
|
||||
// than suppressing it as unchanged.
|
||||
b.MagicConn().ResetNetInfoLast()
|
||||
}
|
||||
|
||||
// resetControlClientLocked sets b.cc to nil and returns the old value. If the
|
||||
|
||||
Reference in New Issue
Block a user