wgengine, internal/deepprint: replace UAPI usage as hash func; add deepprint

The new deepprint package just walks a Go data structure and writes to
an io.Writer. It's not pretty like go-spew, etc.

We then use it to replace the use of UAPI (which we have a TODO to
remove) to generate signatures of data structures to detect whether
anything changed (without retaining the old copy).

This was necessary because the UAPI conversion ends up trying to do
DNS lookups which an upcoming change depends on not happening.
This commit is contained in:
Brad Fitzpatrick
2020-06-28 10:58:21 -07:00
parent 103c06cc68
commit 6f73f2c15a
4 changed files with 379 additions and 18 deletions

View File

@@ -26,6 +26,7 @@ import (
"github.com/tailscale/wireguard-go/wgcfg"
"go4.org/mem"
"tailscale.com/control/controlclient"
"tailscale.com/internal/deepprint"
"tailscale.com/ipn/ipnstate"
"tailscale.com/net/interfaces"
"tailscale.com/tailcfg"
@@ -488,17 +489,13 @@ func (e *userspaceEngine) pinger(peerKey wgcfg.Key, ips []wgcfg.IP) {
p.run(ctx, peerKey, ips, srcIP)
}
// configSignatures returns string signatures for the given configs.
// The exact strings should be considered opaque; the only guarantee is that
// if cfg or routerCfg change, so do their signatures.
func configSignatures(cfg *wgcfg.Config, routerCfg *router.Config) (configSig, engineSig string, err error) {
// TODO(apenwarr): get rid of uapi stuff for in-process comms
uapi, err := cfg.ToUAPI()
if err != nil {
return "", "", err
func updateSig(last *string, v interface{}) (changed bool) {
sig := deepprint.Hash(v)
if *last != sig {
*last = sig
return true
}
return uapi, fmt.Sprintf("%v", routerCfg), nil
return false
}
func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, routerCfg *router.Config) error {
@@ -529,17 +526,11 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, routerCfg *router.Config)
}
e.mu.Unlock()
ec, rc, err := configSignatures(cfg, routerCfg)
if err != nil {
return err
}
engineChanged := ec != e.lastEngineSig
routerChanged := rc != e.lastRouterSig
engineChanged := updateSig(&e.lastEngineSig, cfg)
routerChanged := updateSig(&e.lastRouterSig, routerCfg)
if !engineChanged && !routerChanged {
return ErrNoChanges
}
e.lastEngineSig = ec
e.lastRouterSig = rc
e.lastCfg = cfg.Copy()
if engineChanged {