diff options
| -rw-r--r-- | wgengine/magicsock/magicsock.go | 4 | ||||
| -rw-r--r-- | wgengine/pendopen.go | 8 | ||||
| -rw-r--r-- | wgengine/userspace.go | 15 |
3 files changed, 27 insertions, 0 deletions
diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index 107df0388..d8b278cd8 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -190,6 +190,9 @@ type Conn struct { // havePrivateKey is whether privateKey is non-zero. havePrivateKey syncs.AtomicBool + // DERPCount is the number of DERP connections created. + DERPCount uint32 + // port is the preferred port from opts.Port; 0 means auto. port syncs.AtomicUint32 @@ -350,6 +353,7 @@ func (c *Conn) addDerpPeerRoute(peer key.Public, derpID int, dc *derphttp.Client if c.derpRoute == nil { c.derpRoute = make(map[key.Public]derpRoute) } + atomic.AddUint32(&c.DERPCount, 1) r := derpRoute{derpID, dc} c.derpRoute[peer] = r } diff --git a/wgengine/pendopen.go b/wgengine/pendopen.go index f473591b9..a87b0f92a 100644 --- a/wgengine/pendopen.go +++ b/wgengine/pendopen.go @@ -9,6 +9,7 @@ import ( "os" "runtime" "strconv" + "sync/atomic" "time" "tailscale.com/ipn/ipnstate" @@ -122,6 +123,9 @@ func (e *userspaceEngine) trackOpenPostFilterOut(pp *packet.Parsed, t *tstun.Wra } } + // Accepted a flow, log the flow kind + atomic.AddUint32(&e.connMetrics.direct, 1) + timer := time.AfterFunc(tcpTimeoutBeforeDebug, func() { e.onOpenTimeout(flow) }) @@ -153,6 +157,7 @@ func (e *userspaceEngine) onOpenTimeout(flow flowtrack.Tuple) { e.mu.Unlock() if !problem.IsZero() { + atomic.AddUint32(&e.connMetrics.unreachable, 1) e.logf("open-conn-track: timeout opening %v; peer reported problem: %v", flow, problem) } @@ -160,14 +165,17 @@ func (e *userspaceEngine) onOpenTimeout(flow flowtrack.Tuple) { n, err := e.peerForIP(flow.Dst.IP()) if err != nil { e.logf("open-conn-track: timeout opening %v; peerForIP: %v", flow, err) + atomic.AddUint32(&e.connMetrics.unreachable, 1) return } if n == nil { e.logf("open-conn-track: timeout opening %v; no associated peer node", flow) + atomic.AddUint32(&e.connMetrics.unreachable, 1) return } if n.DiscoKey.IsZero() { e.logf("open-conn-track: timeout opening %v; peer node %v running pre-0.100", flow, n.Key.ShortString()) + atomic.AddUint32(&e.connMetrics.unreachable, 1) return } if n.DERP == "" { diff --git a/wgengine/userspace.go b/wgengine/userspace.go index 4a22c888a..820e40f0e 100644 --- a/wgengine/userspace.go +++ b/wgengine/userspace.go @@ -119,6 +119,8 @@ type userspaceEngine struct { statusBufioReader *bufio.Reader // reusable for UAPI lastStatusPollTime mono.Time // last time we polled the engine status + connMetrics metrics // counts for success/failure/kinds of connections. + mu sync.Mutex // guards following; see lock order comment below netMap *netmap.NetworkMap // or nil closing bool // Close was called (even if we're still closing) @@ -133,6 +135,19 @@ type userspaceEngine struct { // Lock ordering: magicsock.Conn.mu, wgLock, then mu. } +type metrics struct { + // offline is the number of flows magicsock attempted to connect to which are offline. + offline uint32 + // relayed is the number of flows magicsock connected thru over DERP. + relayed uint32 + // direct is the number of flows connected to directly. + direct uint32 + // unreachable is the number of flows which were expected to be online but could not be + // connected to. This is expected to be small, as there is only a brief window where flows are + // offline but have not yet notified control. + unreachable uint32 +} + // InternalsGetter is implemented by Engines that can export their internals. type InternalsGetter interface { GetInternals() (_ *tstun.Wrapper, _ *magicsock.Conn, ok bool) |
