From b4897e7de8e063714daaed0e98509de4777c7f2a Mon Sep 17 00:00:00 2001 From: Avery Pennarun Date: Thu, 12 Mar 2020 23:01:08 -0400 Subject: [PATCH] controlclient/netmap: write our own b.ConciseDiffFrom(a) function. This removes the need for go-cmp, which is extremely bloaty so we had to leave it out of iOS. As a result, we had also left it out of macOS, and so we didn't print netmap diffs at all on darwin-based platforms. Oops. As a bonus, the output format of the new function is way better. Minor oddity: because I used the dumbest possible diff algorithm, the sort order is a bit dumb. We print all "removed" lines and then print all "added" lines, rather than doing the usual diff-like thing of interspersing them. This probably doesn't matter (maybe it's an improvement). --- cmd/relaynode/relaynode.go | 5 +---- control/controlclient/netmap.go | 28 ++++++++++++++++++++++++++++ ipn/ipnserver/server.go | 2 -- ipn/local.go | 22 +++------------------- 4 files changed, 32 insertions(+), 25 deletions(-) diff --git a/cmd/relaynode/relaynode.go b/cmd/relaynode/relaynode.go index c1c106a64..f9d76b465 100644 --- a/cmd/relaynode/relaynode.go +++ b/cmd/relaynode/relaynode.go @@ -23,7 +23,6 @@ import ( "time" "github.com/apenwarr/fixconsole" - "github.com/google/go-cmp/cmp" "github.com/klauspost/compress/zstd" "github.com/pborman/getopt/v2" "github.com/tailscale/wireguard-go/wgcfg" @@ -103,9 +102,7 @@ func main() { if m := new.NetMap; m != nil { if lastNetMap != nil { - s1 := strings.Split(lastNetMap.Concise(), "\n") - s2 := strings.Split(new.NetMap.Concise(), "\n") - logf("netmap diff:\n%v\n", cmp.Diff(s1, s2)) + logf("netmap diff:\n%v\n", new.NetMap.ConciseDiffFrom(lastNetMap)) } lastNetMap = m diff --git a/control/controlclient/netmap.go b/control/controlclient/netmap.go index 5818dafdf..f6319163d 100644 --- a/control/controlclient/netmap.go +++ b/control/controlclient/netmap.go @@ -115,6 +115,34 @@ func (nm *NetworkMap) Concise() string { return buf.String() } +func (b *NetworkMap) ConciseDiffFrom(a *NetworkMap) string { + out := []string{} + ra := strings.Split(a.Concise(), "\n") + rb := strings.Split(b.Concise(), "\n") + + ma := map[string]struct{}{} + for _, s := range ra { + ma[s] = struct{}{} + } + + mb := map[string]struct{}{} + for _, s := range rb { + mb[s] = struct{}{} + } + + for _, s := range ra { + if _, ok := mb[s]; !ok { + out = append(out, "-"+s) + } + } + for _, s := range rb { + if _, ok := ma[s]; !ok { + out = append(out, "+"+s) + } + } + return strings.Join(out, "\n") +} + func (nm *NetworkMap) JSON() string { b, err := json.MarshalIndent(*nm, "", " ") if err != nil { diff --git a/ipn/ipnserver/server.go b/ipn/ipnserver/server.go index 1b11ac307..5b258ae2d 100644 --- a/ipn/ipnserver/server.go +++ b/ipn/ipnserver/server.go @@ -18,7 +18,6 @@ import ( "syscall" "time" - "github.com/google/go-cmp/cmp" "github.com/klauspost/compress/zstd" "tailscale.com/control/controlclient" "tailscale.com/ipn" @@ -112,7 +111,6 @@ func Run(rctx context.Context, logf logger.Logf, logid string, opts Options, e w b.SetDecompressor(func() (controlclient.Decompressor, error) { return zstd.NewReader(nil) }) - b.SetCmpDiff(func(x, y interface{}) string { return cmp.Diff(x, y) }) var s net.Conn serverToClient := func(b []byte) { diff --git a/ipn/local.go b/ipn/local.go index a751b7d9f..64f73d59d 100644 --- a/ipn/local.go +++ b/ipn/local.go @@ -34,7 +34,6 @@ type LocalBackend struct { backendLogID string portpoll *portlist.Poller // may be nil newDecompressor func() (controlclient.Decompressor, error) - cmpDiff func(x, y interface{}) string // The mutex protects the following elements. mu sync.Mutex @@ -111,17 +110,6 @@ func (b *LocalBackend) SetDecompressor(fn func() (controlclient.Decompressor, er b.newDecompressor = fn } -// SetCmpDiff sets a comparison function used to generate logs of what -// has changed in the network map. -// -// Typically the comparison function comes from go-cmp. -// We don't wire it in directly here because the go-cmp package adds -// 1.77mb to the binary size of the iOS NetworkExtension, which takes -// away from its precious RSS limit. -func (b *LocalBackend) SetCmpDiff(cmpDiff func(x, y interface{}) string) { - b.cmpDiff = cmpDiff -} - func (b *LocalBackend) Start(opts Options) error { if opts.Prefs == nil && opts.StateKey == "" { return errors.New("no state key or prefs provided") @@ -224,13 +212,9 @@ func (b *LocalBackend) Start(opts Options) error { } if newSt.NetMap != nil { b.mu.Lock() - if b.netMapCache != nil && b.cmpDiff != nil { - s1 := strings.Split(b.netMapCache.Concise(), "\n") - s2 := strings.Split(newSt.NetMap.Concise(), "\n") - diff := b.cmpDiff(s1, s2) - if strings.TrimSpace(diff) != "" { - b.logf("netmap diff:\n%v\n", diff) - } + if b.netMapCache != nil { + diff := newSt.NetMap.ConciseDiffFrom(b.netMapCache) + b.logf("netmap diff:\n%v\n", diff) } b.netMapCache = newSt.NetMap b.mu.Unlock()