wgengine/monitor: don't call LinkChange when interfaces look unchanged

Basically, don't trust the OS-level link monitor to only tell you
interesting things. Sanity check it.

Also, move the interfaces package into the net directory now that we
have it.
This commit is contained in:
Brad Fitzpatrick 2020-03-10 11:02:30 -07:00
parent 39c0ae1dba
commit 5c1e443d34
7 changed files with 63 additions and 5 deletions

View File

@ -32,7 +32,7 @@ import (
"github.com/gliderlabs/ssh"
"github.com/kr/pty"
gossh "golang.org/x/crypto/ssh"
"tailscale.com/interfaces"
"tailscale.com/net/interfaces"
)
var (

View File

@ -137,6 +137,36 @@ func LocalAddresses() (regular, loopback []string, err error) {
return regular, loopback, nil
}
// Interface is a wrapper around Go's net.Interface with some extra methods.
type Interface struct {
*net.Interface
}
func (i Interface) IsLoopback() bool { return isLoopback(i.Interface) }
func (i Interface) IsUp() bool { return isUp(i.Interface) }
// ForeachInterfaceAddress calls fn for each interface's address on the machine.
func ForeachInterfaceAddress(fn func(Interface, net.IP)) error {
ifaces, err := net.Interfaces()
if err != nil {
return err
}
for i := range ifaces {
iface := &ifaces[i]
addrs, err := iface.Addrs()
if err != nil {
return err
}
for _, a := range addrs {
switch v := a.(type) {
case *net.IPNet:
fn(Interface{iface}, v.IP)
}
}
}
return nil
}
var cgNAT = func() *net.IPNet {
_, ipNet, err := net.ParseCIDR("100.64.0.0/10")
if err != nil {

View File

@ -18,8 +18,8 @@ import (
"golang.org/x/sync/errgroup"
"tailscale.com/derp/derpmap"
"tailscale.com/interfaces"
"tailscale.com/net/dnscache"
"tailscale.com/net/interfaces"
"tailscale.com/stun"
"tailscale.com/stunner"
"tailscale.com/types/logger"

View File

@ -20,8 +20,8 @@ import (
"strings"
"time"
"tailscale.com/interfaces"
"tailscale.com/metrics"
"tailscale.com/net/interfaces"
)
// DevMode controls whether extra output in shown, for when the binary is being run in dev mode.

View File

@ -31,8 +31,8 @@ import (
"tailscale.com/derp"
"tailscale.com/derp/derphttp"
"tailscale.com/derp/derpmap"
"tailscale.com/interfaces"
"tailscale.com/net/dnscache"
"tailscale.com/net/interfaces"
"tailscale.com/netcheck"
"tailscale.com/stun"
"tailscale.com/tailcfg"

View File

@ -7,9 +7,14 @@
package monitor
import (
"fmt"
"net"
"runtime"
"strings"
"sync"
"time"
"tailscale.com/net/interfaces"
"tailscale.com/types/logger"
)
@ -99,6 +104,7 @@ func (m *Mon) Close() error {
// the change channel of changes, and stopping when a stop is issued.
func (m *Mon) pump() {
defer m.goroutines.Done()
last := interfaceSummary()
for {
_, err := m.om.Receive()
if err != nil {
@ -113,9 +119,17 @@ func (m *Mon) pump() {
continue
}
cur := interfaceSummary()
if cur == last {
continue
}
m.logf("wgengine/monitor: now %v (was %v)", cur, last)
last = cur
select {
case m.change <- struct{}{}:
default:
case <-m.stop:
return
}
}
}
@ -140,3 +154,17 @@ func (m *Mon) debounce() {
}
}
}
func interfaceSummary() string {
var sb strings.Builder
_ = interfaces.ForeachInterfaceAddress(func(ni interfaces.Interface, addr net.IP) {
if runtime.GOOS == "linux" && strings.HasPrefix(ni.Name, "tailscale") {
// Skip tailscale0, etc on Linux.
return
}
if ni.IsUp() {
fmt.Fprintf(&sb, "%s=%s ", ni.Name, addr)
}
})
return strings.TrimSpace(sb.String())
}