mirror of
https://github.com/tailscale/tailscale.git
synced 2025-02-18 02:48:40 +00:00
net/portmapper, wgengine/monitor: cache gateway IP info until link changes
Cuts down allocs & CPU in steady state (on regular STUN probes) when network is unchanging. Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
d580b3f09e
commit
44ab0acbdb
@ -50,7 +50,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
|
||||
tailscale.com/types/wgkey from tailscale.com/types/netmap+
|
||||
tailscale.com/util/dnsname from tailscale.com/cmd/tailscale/cli+
|
||||
W tailscale.com/util/endian from tailscale.com/net/netns
|
||||
tailscale.com/util/lineread from tailscale.com/net/interfaces
|
||||
LW tailscale.com/util/lineread from tailscale.com/net/interfaces
|
||||
tailscale.com/version from tailscale.com/cmd/tailscale/cli+
|
||||
tailscale.com/version/distro from tailscale.com/cmd/tailscale/cli
|
||||
tailscale.com/wgengine/filter from tailscale.com/types/netmap
|
||||
|
@ -126,7 +126,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
||||
tailscale.com/types/wgkey from tailscale.com/control/controlclient+
|
||||
tailscale.com/util/dnsname from tailscale.com/wgengine/tsdns+
|
||||
LW tailscale.com/util/endian from tailscale.com/net/netns+
|
||||
tailscale.com/util/lineread from tailscale.com/control/controlclient+
|
||||
LW tailscale.com/util/lineread from tailscale.com/control/controlclient+
|
||||
tailscale.com/util/pidowner from tailscale.com/ipn/ipnserver
|
||||
tailscale.com/util/racebuild from tailscale.com/logpolicy
|
||||
tailscale.com/util/systemd from tailscale.com/control/controlclient+
|
||||
|
@ -42,7 +42,8 @@ const trustServiceStillAvailableDuration = 10 * time.Minute
|
||||
|
||||
// Client is a port mapping client.
|
||||
type Client struct {
|
||||
logf logger.Logf
|
||||
logf logger.Logf
|
||||
ipAndGateway func() (gw, ip netaddr.IP, ok bool)
|
||||
|
||||
mu sync.Mutex // guards following, and all fields thereof
|
||||
|
||||
@ -100,10 +101,18 @@ func (m *pmpMapping) release() {
|
||||
// NewClient returns a new portmapping client.
|
||||
func NewClient(logf logger.Logf) *Client {
|
||||
return &Client{
|
||||
logf: logf,
|
||||
logf: logf,
|
||||
ipAndGateway: interfaces.LikelyHomeRouterIP,
|
||||
}
|
||||
}
|
||||
|
||||
// SetGatewayLookupFunc set the func that returns the machine's default gateway IP, and
|
||||
// the primary IP address for that gateway. It must be called before the client is used.
|
||||
// If not called, interfaces.LikelyHomeRouterIP is used.
|
||||
func (c *Client) SetGatewayLookupFunc(f func() (gw, myIP netaddr.IP, ok bool)) {
|
||||
c.ipAndGateway = f
|
||||
}
|
||||
|
||||
// NoteNetworkDown should be called when the network has transitioned to a down state.
|
||||
// It's too late to release port mappings at this point (the user might've just turned off
|
||||
// their wifi), but we can make sure we invalidate mappings for later when the network
|
||||
@ -140,7 +149,7 @@ func (c *Client) SetLocalPort(localPort uint16) {
|
||||
}
|
||||
|
||||
func (c *Client) gatewayAndSelfIP() (gw, myIP netaddr.IP, ok bool) {
|
||||
gw, myIP, ok = interfaces.LikelyHomeRouterIP()
|
||||
gw, myIP, ok = c.ipAndGateway()
|
||||
if !ok {
|
||||
gw = netaddr.IP{}
|
||||
myIP = netaddr.IP{}
|
||||
|
@ -55,6 +55,7 @@ import (
|
||||
"tailscale.com/types/pad32"
|
||||
"tailscale.com/types/wgkey"
|
||||
"tailscale.com/version"
|
||||
"tailscale.com/wgengine/monitor"
|
||||
"tailscale.com/wgengine/wgcfg"
|
||||
)
|
||||
|
||||
@ -423,6 +424,10 @@ type Options struct {
|
||||
// enabled, only active discovery-aware nodes will be able to
|
||||
// communicate with Conn.
|
||||
DisableLegacyNetworking bool
|
||||
|
||||
// LinkMonitor is the link monitor to use.
|
||||
// With one, the portmapper won't be used.
|
||||
LinkMonitor *monitor.Mon
|
||||
}
|
||||
|
||||
func (o *Options) logf() logger.Logf {
|
||||
@ -483,6 +488,9 @@ func NewConn(opts Options) (*Conn, error) {
|
||||
c.simulatedNetwork = opts.SimulatedNetwork
|
||||
c.disableLegacy = opts.DisableLegacyNetworking
|
||||
c.portMapper = portmapper.NewClient(logger.WithPrefix(c.logf, "portmapper: "))
|
||||
if opts.LinkMonitor != nil {
|
||||
c.portMapper.SetGatewayLookupFunc(opts.LinkMonitor.GatewayAndSelfIP)
|
||||
}
|
||||
|
||||
if err := c.initialBind(); err != nil {
|
||||
return nil, err
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"inet.af/netaddr"
|
||||
"tailscale.com/net/interfaces"
|
||||
"tailscale.com/types/logger"
|
||||
)
|
||||
@ -51,9 +52,12 @@ type Mon struct {
|
||||
change chan struct{}
|
||||
stop chan struct{}
|
||||
|
||||
mu sync.Mutex // guards cbs
|
||||
cbs map[*callbackHandle]ChangeFunc
|
||||
ifState *interfaces.State
|
||||
mu sync.Mutex // guards cbs
|
||||
cbs map[*callbackHandle]ChangeFunc
|
||||
ifState *interfaces.State
|
||||
gwValid bool // whether gw and gwSelfIP are valid (cached)x
|
||||
gw netaddr.IP
|
||||
gwSelfIP netaddr.IP
|
||||
|
||||
onceStart sync.Once
|
||||
started bool
|
||||
@ -105,6 +109,24 @@ func (m *Mon) interfaceStateUncached() (*interfaces.State, error) {
|
||||
return s, err
|
||||
}
|
||||
|
||||
// GatewayAndSelfIP returns the current network's default gateway, and
|
||||
// the machine's default IP for that gateway.
|
||||
//
|
||||
// It's the same as interfaces.LikelyHomeRouterIP, but it caches the
|
||||
// result until the monitor detects a network change.
|
||||
func (m *Mon) GatewayAndSelfIP() (gw, myIP netaddr.IP, ok bool) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if m.gwValid {
|
||||
return m.gw, m.gwSelfIP, true
|
||||
}
|
||||
gw, myIP, ok = interfaces.LikelyHomeRouterIP()
|
||||
if ok {
|
||||
m.gw, m.gwSelfIP, m.gwValid = gw, myIP, true
|
||||
}
|
||||
return gw, myIP, ok
|
||||
}
|
||||
|
||||
// RegisterChangeCallback adds callback to the set of parties to be
|
||||
// notified (in their own goroutine) when the network state changes.
|
||||
// To remove this callback, call unregister (or close the monitor).
|
||||
@ -213,6 +235,7 @@ func (m *Mon) debounce() {
|
||||
oldState := m.ifState
|
||||
changed := !curState.Equal(oldState)
|
||||
if changed {
|
||||
m.gwValid = false
|
||||
m.ifState = curState
|
||||
|
||||
if s1, s2 := oldState.String(), curState.String(); s1 == s2 {
|
||||
|
@ -270,6 +270,7 @@ func newUserspaceEngine(logf logger.Logf, rawTUNDev tun.Device, conf Config) (_
|
||||
DERPActiveFunc: e.RequestStatus,
|
||||
IdleFunc: e.tundev.IdleDuration,
|
||||
NoteRecvActivity: e.noteReceiveActivity,
|
||||
LinkMonitor: e.linkMon,
|
||||
}
|
||||
var err error
|
||||
e.magicConn, err = magicsock.NewConn(magicsockOpts)
|
||||
|
Loading…
x
Reference in New Issue
Block a user