diff --git a/wgengine/magicsock/endpoint.go b/wgengine/magicsock/endpoint.go index 2795a15c4..2f144d0ea 100644 --- a/wgengine/magicsock/endpoint.go +++ b/wgengine/magicsock/endpoint.go @@ -1362,8 +1362,12 @@ func (de *endpoint) startDiscoPingLocked(ep epAddr, now mono.Time, purpose disco } -// sendDiscoPingsLocked starts pinging all of ep's endpoints. +// sendDiscoPingsLocked starts pinging all of ep's direct endpoints. +// Sibling of discoverUDPRelayPathsLocked for udprelay. func (de *endpoint) sendDiscoPingsLocked(now mono.Time, sendCallMeMaybe bool) { + if debugNeverDirectUDP() { + return // skip when direct UDP is disabled + } de.lastFullPing = now var sentAny bool for ep, st := range de.endpointState { diff --git a/wgengine/magicsock/endpoint_test.go b/wgengine/magicsock/endpoint_test.go index 593cf1455..0df59bbc4 100644 --- a/wgengine/magicsock/endpoint_test.go +++ b/wgengine/magicsock/endpoint_test.go @@ -4,12 +4,14 @@ package magicsock import ( + "fmt" "net/netip" "testing" "testing/synctest" "time" "tailscale.com/disco" + "tailscale.com/envknob" "tailscale.com/net/packet" "tailscale.com/net/stun" "tailscale.com/tailcfg" @@ -562,6 +564,42 @@ func Test_endpoint_discoPingTimeout(t *testing.T) { } } +func Test_endpoint_sendDiscoPingsLocked_neverDirectUDP(t *testing.T) { + directAddr := netip.MustParseAddrPort("192.0.2.1:7") + for _, neverDirectUDP := range []bool{false, true} { + t.Run(fmt.Sprintf("neverDirectUDP=%v", neverDirectUDP), func(t *testing.T) { + prev := envknob.String("TS_DEBUG_NEVER_DIRECT_UDP") + if neverDirectUDP { + envknob.Setenv("TS_DEBUG_NEVER_DIRECT_UDP", "true") + } else { + envknob.Setenv("TS_DEBUG_NEVER_DIRECT_UDP", "") + } + t.Cleanup(func() { envknob.Setenv("TS_DEBUG_NEVER_DIRECT_UDP", prev) }) + now := mono.Now() + c := &Conn{ + logf: func(msg string, args ...any) {}, + } + c.discoAtomic.Set(key.NewDisco()) + de := &endpoint{ + c: c, + sentPing: make(map[stun.TxID]sentPing), + endpointState: make(map[netip.AddrPort]*endpointState), + } + de.disco.Store(&endpointDisco{key: key.NewDisco().Public()}) + de.endpointState[directAddr] = &endpointState{} + de.sendDiscoPingsLocked(now, true) + + wantPing := !neverDirectUDP + if gotPing := de.lastFullPing == now; gotPing != wantPing { + t.Errorf("lastFullPing set = %v, want %v", gotPing, wantPing) + } + if gotPing := de.endpointState[directAddr].lastPing == now; gotPing != wantPing { + t.Errorf("direct endpoint lastPing set = %v, want %v", gotPing, wantPing) + } + }) + } +} + func Test_endpoint_handlePongConnLocked(t *testing.T) { goodLatency := 50 * time.Millisecond badLatency := 100 * time.Millisecond