wgengine/magicsock: add start of alternate send path

During development of silent disco (#540), an alternate send policy
for magicsock that doesn't wake up the radio frequently with
heartbeats, we want the old & new policies to coexist, like we did
previously pre- and post-disco.

We started to do that earlier in 5c42990c2f but only set up the
env+control knob plumbing to set a bool about which path should be
used.

This starts to add a way for the silent disco code to update the send
path from a separate goroutine. (Part of the effort is going to
de-state-machinify the event based soup that is the current disco
code and make it more Go synchronous style.)

So far this does nothing. (It does add an atomic load on each send
but that should be noise in the grand scheme of things, and a even more
rare atomic store of nil on node config changes.)

Baby steps.

Updates #540

Co-authored-by: Jenny Zhang <jz@tailscale.com>
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
pull/5994/head
Brad Fitzpatrick 2 years ago committed by Brad Fitzpatrick
parent 69f61dcad8
commit deac82231c

@ -3304,6 +3304,19 @@ func ippDebugString(ua netip.AddrPort) string {
return ua.String()
}
// endpointSendFunc is a func that writes an encrypted Wireguard payload from
// WireGuard to a peer. It might write via UDP, DERP, both, or neither.
//
// What these funcs should NOT do is too much work. Minimize use of mutexes, map
// lookups, etc. The idea is that selecting the path to use is done infrequently
// and mostly async from sending packets. When conditions change (including the
// passing of time and loss of confidence in certain routes), then a new send
// func gets set on an sendpoint.
//
// A nil value means the current fast path has expired and needs to be
// recalculated.
type endpointSendFunc func([]byte) error
// discoEndpoint is a wireguard/conn.Endpoint that picks the best
// available path to communicate with a peer, based on network
// conditions and what the peer supports.
@ -3311,6 +3324,7 @@ type endpoint struct {
// atomically accessed; declared first for alignment reasons
lastRecv mono.Time
numStopAndResetAtomic int64
sendFunc syncs.AtomicValue[endpointSendFunc] // nil or unset means unused
// These fields are initialized once and never modified.
c *Conn
@ -3630,6 +3644,10 @@ func (de *endpoint) cliPing(res *ipnstate.PingResult, cb func(*ipnstate.PingResu
}
func (de *endpoint) send(b []byte) error {
if fn := de.sendFunc.Load(); fn != nil {
return fn(b)
}
now := mono.Now()
de.mu.Lock()
@ -3836,6 +3854,9 @@ func (de *endpoint) updateFromNode(n *tailcfg.Node, heartbeatDisabled bool) {
de.deleteEndpointLocked(ep)
}
}
// Node changed. Invalidate its sending fast path, if any.
de.sendFunc.Store(nil)
}
// addCandidateEndpoint adds ep as an endpoint to which we should send

Loading…
Cancel
Save