net/netcheck,wgengine/magicsock: don't rebind when IPv4 was never probed - #20722
Open
BastienClement wants to merge 1 commit into
Open
net/netcheck,wgengine/magicsock: don't rebind when IPv4 was never probed#20722BastienClement wants to merge 1 commit into
BastienClement wants to merge 1 commit into
Conversation
On a host with no usable IPv4 address, makeProbePlan plans no IPv4 STUN probes, so Report.IPv4CanSend can never become true. magicsock read that as "the IPv4 socket cannot transmit" and rebound every 20-26s for the life of the process. Record whether an IPv4 send was attempted at all, and treat only a send that was tried and failed as a broken socket. The rebind still fires in the case it was added for: a socket left bound to a departed interface still has IPv4 probes planned, so the send is attempted and fails. RELNOTE: stop magicsock from rebinding every ~20s on hosts with no usable IPv4 address Fixes tailscale#16755 Updates tailscale#19791 Change-Id: I93359937485d475b4197278e778123b4e0435117 Signed-off-by: Bastien Clément <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
Adds
netcheck.Report.IPv4SendAttempted, recording whether an IPv4 STUN send was actually tried, and changes magicsock to setnoV4Sendonly when a send was tried and failed.Fixes #16755
Updates #19791
Why
On a host with no usable IPv4 address,
makeProbePlangates IPv4 probes onifState.HaveV4and plans none.Report.IPv4CanSendis writtentruein exactly one place, inrunProbeafter a send, so it can never become true on such a host. magicsock storednoV4Send = !report.IPv4CanSendandupdateEndpointsread that as "the IPv4 socket cannot transmit", so every netcheck calledRebind(). From an IPv6-only EKS pod on #16755:Periodic re-STUN is suppressed once the node has been idle past
sessionActiveTimeout, so the loop runs at 20-26s intervals precisely while there is traffic. Where the default route sits on an interface that does not hold the socket's address, each cycle also closes every DERP connection and new connections stall while the loop runs.Reported on IPv6-only VMs (#16755), Google Cloud Run (#19791, #20330), and IPv6-only EKS pods where
aws-vpc-cniprovides IPv4 egress through a link-local address. The thread on #16755 has a measurement of 12 rebinds in 5 minutes against 0 once the link is made to report IPv4.The rebind exists for #2994, where a socket is left bound to a departed interface after a network reconfiguration. That case is unaffected: the link still has a usable IPv4 address, so probes are planned, the send is attempted and fails, and
noV4Sendis still set.Tests
Two new tests, both mutation-checked with
go test -overlay(working tree left untouched):TestIPv4SendAttempted(net/netcheck) covers send-ok, send-failed, EPERM and no-IPv4-node. Dropping therunProbechange fails the first three; dropping theTreatAsLostUDPtolerance fails the EPERM case.TestUpdateNetInfoNoV4Send(wgengine/magicsock) assertsnoV4Sendend to end throughupdateNetInfo. RestoringnoV4Send = !report.IPv4CanSendfailsno_v4_probewithnoV4Send = true; want false.netmon.Monitorexposes no way to inject interface state, so the new tests reach the empty IPv4 probe set through a DERP node without an IPv4 address rather than throughHaveV4. The existingTestMakeProbePlan/only_v6_initialcovers the other half, thatHaveV4 == falseyields a plan with no IPv4 probes.Also run locally:
go test -race -count=2over net/netcheck and wgengine/magicsock,go test -raceover cmd/tailscale/cli and ipn/ipnlocal (the othernetcheck.Reportconsumers),staticcheckfor darwin/arm64, windows/amd64 and linux/amd64,make depaware,go mod tidywith no diff, and cross-builds for plan9, solaris, illumos, aix, js/wasm, windows amd64 and arm64, darwin, freebsd, openbsd and linux/arm.