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.
pull/169/head
Brad Fitzpatrick 5 years ago
parent 39c0ae1dba
commit 5c1e443d34

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

@ -137,6 +137,36 @@ func LocalAddresses() (regular, loopback []string, err error) {
return regular, loopback, nil 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 { var cgNAT = func() *net.IPNet {
_, ipNet, err := net.ParseCIDR("100.64.0.0/10") _, ipNet, err := net.ParseCIDR("100.64.0.0/10")
if err != nil { if err != nil {

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

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

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

@ -7,9 +7,14 @@
package monitor package monitor
import ( import (
"fmt"
"net"
"runtime"
"strings"
"sync" "sync"
"time" "time"
"tailscale.com/net/interfaces"
"tailscale.com/types/logger" "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. // the change channel of changes, and stopping when a stop is issued.
func (m *Mon) pump() { func (m *Mon) pump() {
defer m.goroutines.Done() defer m.goroutines.Done()
last := interfaceSummary()
for { for {
_, err := m.om.Receive() _, err := m.om.Receive()
if err != nil { if err != nil {
@ -113,9 +119,17 @@ func (m *Mon) pump() {
continue continue
} }
cur := interfaceSummary()
if cur == last {
continue
}
m.logf("wgengine/monitor: now %v (was %v)", cur, last)
last = cur
select { select {
case m.change <- struct{}{}: 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())
}

Loading…
Cancel
Save