wgengine: separately dedupe wireguard configs and router configs.
Otherwise iOS/macOS will reconfigure their routing every time anything minor changes in the netmap (in particular, endpoints and DERP homes), which is way too often. Some users reported "network reconfigured" errors from Chrome when this happens. Signed-off-by: Avery Pennarun <apenwarr@tailscale.com>reviewable/pr427/r1
parent
f0b6ba78e8
commit
e46238a2af
|
@ -58,7 +58,8 @@ type userspaceEngine struct {
|
||||||
linkMon *monitor.Mon
|
linkMon *monitor.Mon
|
||||||
|
|
||||||
wgLock sync.Mutex // serializes all wgdev operations; see lock order comment below
|
wgLock sync.Mutex // serializes all wgdev operations; see lock order comment below
|
||||||
lastReconfig string
|
lastEngineSig string
|
||||||
|
lastRouterSig string
|
||||||
lastCfg wgcfg.Config
|
lastCfg wgcfg.Config
|
||||||
|
|
||||||
mu sync.Mutex // guards following; see lock order comment below
|
mu sync.Mutex // guards following; see lock order comment below
|
||||||
|
@ -359,17 +360,18 @@ func (e *userspaceEngine) pinger(peerKey wgcfg.Key, ips []wgcfg.IP) {
|
||||||
p.run(ctx, peerKey, ips, srcIP)
|
p.run(ctx, peerKey, ips, srcIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
func configSignature(cfg *wgcfg.Config, routerCfg *router.Config) (string, error) {
|
func configSignatures(cfg *wgcfg.Config, routerCfg *router.Config) (string, string, error) {
|
||||||
// TODO(apenwarr): get rid of uapi stuff for in-process comms
|
// TODO(apenwarr): get rid of uapi stuff for in-process comms
|
||||||
uapi, err := cfg.ToUAPI()
|
uapi, err := cfg.ToUAPI()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%s %v", uapi, routerCfg), nil
|
return uapi, fmt.Sprintf("%v", routerCfg), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, routerCfg *router.Config) error {
|
func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, routerCfg *router.Config) error {
|
||||||
|
e.logf("Reconfig: router.Set: %p %p", cfg, routerCfg)
|
||||||
if routerCfg == nil {
|
if routerCfg == nil {
|
||||||
panic("routerCfg must not be nil")
|
panic("routerCfg must not be nil")
|
||||||
}
|
}
|
||||||
|
@ -386,18 +388,22 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, routerCfg *router.Config)
|
||||||
}
|
}
|
||||||
e.mu.Unlock()
|
e.mu.Unlock()
|
||||||
|
|
||||||
rc, err := configSignature(cfg, routerCfg)
|
ec, rc, err := configSignatures(cfg, routerCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if rc == e.lastReconfig {
|
engineChanged := ec != e.lastEngineSig
|
||||||
|
routerChanged := rc != e.lastRouterSig
|
||||||
|
if !engineChanged && !routerChanged {
|
||||||
return ErrNoChanges
|
return ErrNoChanges
|
||||||
}
|
}
|
||||||
|
e.lastEngineSig = ec
|
||||||
e.logf("wgengine: Reconfig: configuring userspace wireguard engine")
|
e.lastRouterSig = rc
|
||||||
e.lastReconfig = rc
|
|
||||||
e.lastCfg = cfg.Copy()
|
e.lastCfg = cfg.Copy()
|
||||||
|
|
||||||
|
e.logf("wgengine: Reconfig: configuring userspace wireguard engine")
|
||||||
|
|
||||||
|
if engineChanged {
|
||||||
// Tell magicsock about the new (or initial) private key
|
// Tell magicsock about the new (or initial) private key
|
||||||
// (which is needed by DERP) before wgdev gets it, as wgdev
|
// (which is needed by DERP) before wgdev gets it, as wgdev
|
||||||
// will start trying to handshake, which we want to be able to
|
// will start trying to handshake, which we want to be able to
|
||||||
|
@ -412,10 +418,13 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, routerCfg *router.Config)
|
||||||
}
|
}
|
||||||
|
|
||||||
e.magicConn.UpdatePeers(peerSet)
|
e.magicConn.UpdatePeers(peerSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
if routerChanged {
|
||||||
if err := e.router.Set(routerCfg); err != nil {
|
if err := e.router.Set(routerCfg); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
e.logf("wgengine: Reconfig done")
|
e.logf("wgengine: Reconfig done")
|
||||||
return nil
|
return nil
|
||||||
|
|
Loading…
Reference in New Issue