From fee74e7ea7fd489456251d916a65b62cd32c83b0 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 8 Mar 2021 20:41:23 -0800 Subject: [PATCH] net/interfaces, wgengine/monitor: fix false positives link changes interfaces.State.String tries to print a concise summary of the network state, removing any interfaces that don't have any or any interesting IP addresses. On macOS and iOS, for instance, there are a ton of misc things. But the link monitor based its are-there-changes decision on interfaces.State.Equal, which just used reflect.DeepEqual, including comparing all the boring interfaces. On macOS, when turning wifi on or off, there are a ton of misc boring interface changes, resulting in hitting an earlier check I'd added on suspicion this was happening: [unexpected] network state changed, but stringification didn't This fixes that by instead adding a new interfaces.State.RemoveUninterestingInterfacesAndAddresses method that does, uh, that. Then use that in the monitor. So then when Equal is used later, it's DeepEqualing the already-cleaned version with only interesting interfaces. This makes cmd/tailscaled debug --monitor much less noisy. Signed-off-by: Brad Fitzpatrick --- net/interfaces/interfaces.go | 24 ++++++++++++++++++++++++ wgengine/monitor/monitor.go | 1 + 2 files changed, 25 insertions(+) diff --git a/net/interfaces/interfaces.go b/net/interfaces/interfaces.go index 4d48ef6be..19d97787d 100644 --- a/net/interfaces/interfaces.go +++ b/net/interfaces/interfaces.go @@ -297,6 +297,29 @@ func (s *State) AnyInterfaceUp() bool { return s != nil && (s.HaveV4 || s.HaveV6Global) } +// RemoveUninterestingInterfacesAndAddresses removes uninteresting IPs +// from InterfaceIPs, also removing from both the InterfaceIPs and +// InterfaceUp map any interfaces that don't have any interesting IPs. +func (s *State) RemoveUninterestingInterfacesAndAddresses() { + for ifName := range s.InterfaceUp { + ips := s.InterfaceIPs[ifName] + keep := ips[:0] + for _, pfx := range ips { + if isInterestingIP(pfx.IP) { + keep = append(keep, pfx) + } + } + if len(keep) == 0 { + delete(s.InterfaceUp, ifName) + delete(s.InterfaceIPs, ifName) + continue + } + if len(keep) < len(ips) { + s.InterfaceIPs[ifName] = keep + } + } +} + // RemoveTailscaleInterfaces modifes s to remove any interfaces that // are owned by this process. (TODO: make this true; currently it // uses some heuristics) @@ -360,6 +383,7 @@ func GetState() (*State, error) { }); err != nil { return nil, err } + s.DefaultRouteInterface, _ = DefaultRouteInterface() if s.AnyInterfaceUp() { diff --git a/wgengine/monitor/monitor.go b/wgengine/monitor/monitor.go index 13c28451d..65c06ed1b 100644 --- a/wgengine/monitor/monitor.go +++ b/wgengine/monitor/monitor.go @@ -100,6 +100,7 @@ func (m *Mon) interfaceStateUncached() (*interfaces.State, error) { s, err := interfaces.GetState() if s != nil { s.RemoveTailscaleInterfaces() + s.RemoveUninterestingInterfacesAndAddresses() } return s, err }