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).
reviewable/pr185/r1
Avery Pennarun 5 years ago
parent 96bb05ce2f
commit b4897e7de8

@ -23,7 +23,6 @@ import (
"time" "time"
"github.com/apenwarr/fixconsole" "github.com/apenwarr/fixconsole"
"github.com/google/go-cmp/cmp"
"github.com/klauspost/compress/zstd" "github.com/klauspost/compress/zstd"
"github.com/pborman/getopt/v2" "github.com/pborman/getopt/v2"
"github.com/tailscale/wireguard-go/wgcfg" "github.com/tailscale/wireguard-go/wgcfg"
@ -103,9 +102,7 @@ func main() {
if m := new.NetMap; m != nil { if m := new.NetMap; m != nil {
if lastNetMap != nil { if lastNetMap != nil {
s1 := strings.Split(lastNetMap.Concise(), "\n") logf("netmap diff:\n%v\n", new.NetMap.ConciseDiffFrom(lastNetMap))
s2 := strings.Split(new.NetMap.Concise(), "\n")
logf("netmap diff:\n%v\n", cmp.Diff(s1, s2))
} }
lastNetMap = m lastNetMap = m

@ -115,6 +115,34 @@ func (nm *NetworkMap) Concise() string {
return buf.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 { func (nm *NetworkMap) JSON() string {
b, err := json.MarshalIndent(*nm, "", " ") b, err := json.MarshalIndent(*nm, "", " ")
if err != nil { if err != nil {

@ -18,7 +18,6 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/google/go-cmp/cmp"
"github.com/klauspost/compress/zstd" "github.com/klauspost/compress/zstd"
"tailscale.com/control/controlclient" "tailscale.com/control/controlclient"
"tailscale.com/ipn" "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) { b.SetDecompressor(func() (controlclient.Decompressor, error) {
return zstd.NewReader(nil) return zstd.NewReader(nil)
}) })
b.SetCmpDiff(func(x, y interface{}) string { return cmp.Diff(x, y) })
var s net.Conn var s net.Conn
serverToClient := func(b []byte) { serverToClient := func(b []byte) {

@ -34,7 +34,6 @@ type LocalBackend struct {
backendLogID string backendLogID string
portpoll *portlist.Poller // may be nil portpoll *portlist.Poller // may be nil
newDecompressor func() (controlclient.Decompressor, error) newDecompressor func() (controlclient.Decompressor, error)
cmpDiff func(x, y interface{}) string
// The mutex protects the following elements. // The mutex protects the following elements.
mu sync.Mutex mu sync.Mutex
@ -111,17 +110,6 @@ func (b *LocalBackend) SetDecompressor(fn func() (controlclient.Decompressor, er
b.newDecompressor = fn 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 { func (b *LocalBackend) Start(opts Options) error {
if opts.Prefs == nil && opts.StateKey == "" { if opts.Prefs == nil && opts.StateKey == "" {
return errors.New("no state key or prefs provided") return errors.New("no state key or prefs provided")
@ -224,13 +212,9 @@ func (b *LocalBackend) Start(opts Options) error {
} }
if newSt.NetMap != nil { if newSt.NetMap != nil {
b.mu.Lock() b.mu.Lock()
if b.netMapCache != nil && b.cmpDiff != nil { if b.netMapCache != nil {
s1 := strings.Split(b.netMapCache.Concise(), "\n") diff := newSt.NetMap.ConciseDiffFrom(b.netMapCache)
s2 := strings.Split(newSt.NetMap.Concise(), "\n") b.logf("netmap diff:\n%v\n", diff)
diff := b.cmpDiff(s1, s2)
if strings.TrimSpace(diff) != "" {
b.logf("netmap diff:\n%v\n", diff)
}
} }
b.netMapCache = newSt.NetMap b.netMapCache = newSt.NetMap
b.mu.Unlock() b.mu.Unlock()

Loading…
Cancel
Save