summaryrefslogtreecommitdiffhomepage
path: root/wgengine/netstack/netstack.go
diff options
context:
space:
mode:
authorAndrew Dunham <andrew@du.nham.ca>2024-02-26 14:34:56 -0500
committerAndrew Dunham <andrew@du.nham.ca>2024-02-26 16:33:10 -0500
commit35dc1fea725f3b947870ca9994bfbead26433eaf (patch)
treeb987f413e7a1145be06c7926c243da5896ee17e0 /wgengine/netstack/netstack.go
parent50fb8b912324f8cfb17ba456ca9f0fff7fb58785 (diff)
downloadtailscale-andrew/netstack-forwarder-debug.tar.xz
tailscale-andrew/netstack-forwarder-debug.zip
wgengine/netstack: add debug page for TCP forwarderandrew/netstack-forwarder-debug
To help in debugging issues with subnet routers in userspace mode–for example, hitting the max inflight limit. Updates tailscale/corp#12184 Signed-off-by: Andrew Dunham <andrew@du.nham.ca> Change-Id: Idd922f4ae37695f6598a914c2d050574755ef309
Diffstat (limited to 'wgengine/netstack/netstack.go')
-rw-r--r--wgengine/netstack/netstack.go35
1 files changed, 35 insertions, 0 deletions
diff --git a/wgengine/netstack/netstack.go b/wgengine/netstack/netstack.go
index ae2513b33..ccb590fff 100644
--- a/wgengine/netstack/netstack.go
+++ b/wgengine/netstack/netstack.go
@@ -150,6 +150,18 @@ type Impl struct {
// TCP connections, so they can be unregistered when connections are
// closed.
connsOpenBySubnetIP map[netip.Addr]int
+
+ // Debug information for the TCP forwarding code; all fields protected
+ // by tcpDebugMu.
+ tcpDebugMu sync.Mutex
+ inFlightDialCtr int
+ inFlightDials map[int]tcpDialInfo // keyed by a random integer
+}
+
+type tcpDialInfo struct {
+ clientRemoteIP netip.Addr
+ dialAddr netip.AddrPort
+ start time.Time
}
const nicID = 1
@@ -242,6 +254,7 @@ func Create(logf logger.Logf, tundev *tstun.Wrapper, e wgengine.Engine, mc *magi
connsOpenBySubnetIP: make(map[netip.Addr]int),
dns: dns,
tailFSForLocal: tailFSForLocal,
+ inFlightDials: make(map[int]tcpDialInfo),
}
ns.ctx, ns.ctxCancel = context.WithCancel(context.Background())
ns.atomicIsLocalIPFunc.Store(tsaddr.FalseContainsIPFunc())
@@ -981,6 +994,24 @@ func (ns *Impl) acceptTCP(r *tcp.ForwarderRequest) {
}
}
+func (ns *Impl) debugForwardedTCP(clientRemoteIP netip.Addr, remote netip.AddrPort) func() {
+ ns.tcpDebugMu.Lock()
+ debugKey := ns.inFlightDialCtr
+ ns.inFlightDialCtr++
+ ns.inFlightDials[debugKey] = tcpDialInfo{
+ clientRemoteIP: clientRemoteIP,
+ dialAddr: remote,
+ start: time.Now(),
+ }
+ ns.tcpDebugMu.Unlock()
+
+ return func() {
+ ns.tcpDebugMu.Lock()
+ delete(ns.inFlightDials, debugKey)
+ ns.tcpDebugMu.Unlock()
+ }
+}
+
func (ns *Impl) forwardTCP(getClient func(...tcpip.SettableSocketOption) *gonet.TCPConn, clientRemoteIP netip.Addr, wq *waiter.Queue, dialAddr netip.AddrPort) (handled bool) {
dialAddrStr := dialAddr.String()
if debugNetstack() {
@@ -1008,9 +1039,13 @@ func (ns *Impl) forwardTCP(getClient func(...tcpip.SettableSocketOption) *gonet.
cancel()
}()
+ // Insert debug info, and remove it once we've dialed our outbound conn.
+ debugDialDone := ns.debugForwardedTCP(clientRemoteIP, dialAddr)
+
// Attempt to dial the outbound connection before we accept the inbound one.
var stdDialer net.Dialer
server, err := stdDialer.DialContext(ctx, "tcp", dialAddrStr)
+ debugDialDone()
if err != nil {
ns.logf("netstack: could not connect to local server at %s: %v", dialAddr.String(), err)
return