wgengine/magicsock,ipn/ipnlocal: store and load homeDERP from cache (#19491)

With netmap caching, the home DERP of the self node was neither saved to
the cache or loaded from it, making nodes not stick to a DERP when
starting without a connection to control.

Instead, make sure that when a cache is available, load that cache,
before looking for DERP servers. This is implemented by allowing a skip
of ReSTUN in setting the DERP map (we must have a DERP map before
setting the home DERP), so the DERP from cache will set itself and be
sticky until a connection to control is established.

Making DERP only change when connected to control is handled by existing
code from f072d017bd.

Updates #19490

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
This commit is contained in:
Claus Lensbøl
2026-04-29 10:24:09 -04:00
committed by GitHub
parent 1841a93ab2
commit 78627c132f
9 changed files with 493 additions and 20 deletions
+13 -1
View File
@@ -35,7 +35,19 @@ func (b *LocalBackend) writeNetmapToDiskLocked(nm *netmap.NetworkMap) error {
b.diskCache.cache = netmapcache.NewCache(netmapcache.FileStore(dir))
b.diskCache.dir = dir
}
return b.diskCache.cache.Store(b.currentNode().Context(), nm)
// Set the homeDERP on the self node before saving. The self node homeDERP is
// generally not used since the homeDERP for self is stored in magicsock, but
// to be able to load it during loading the cache, we use the existing field
// to save it.
// Make a shallow copy and mutate a copy of the selfNode.
nmCopy := *nm
selfNode := nm.SelfNode.AsStruct()
selfNode.HomeDERP = int(b.currentNode().homeDERP.Load())
nmCopy.SelfNode = selfNode.View()
return b.diskCache.cache.Store(b.currentNode().Context(), &nmCopy)
}
func (b *LocalBackend) loadDiskCacheLocked() (om *netmap.NetworkMap, ok bool) {