diff options
author | Josh Bleecher Snyder <josh@tailscale.com> | 2021-11-18 15:37:24 -0800 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2021-11-23 22:03:15 +0100 |
commit | 387f7c461a16b28af2f19d31f9da2cc544e487c4 (patch) | |
tree | 550db377e7e5243e61ab9f67564db03eefd23ef0 | |
parent | 4d87c9e8246072d4880e6f198f81ad4675872d86 (diff) |
device: reduce peer lock critical section in UAPI
The deferred RUnlock calls weren't executing until all peers
had been processed. Add an anonymous function so that each
peer may be unlocked as soon as it is completed.
Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r-- | device/uapi.go | 54 |
1 files changed, 28 insertions, 26 deletions
diff --git a/device/uapi.go b/device/uapi.go index 98e8311..f3acf81 100644 --- a/device/uapi.go +++ b/device/uapi.go @@ -99,33 +99,35 @@ func (device *Device) IpcGetOperation(w io.Writer) error { sendf("fwmark=%d", device.net.fwmark) } - // serialize each peer state - for _, peer := range device.peers.keyMap { - peer.RLock() - defer peer.RUnlock() - - keyf("public_key", (*[32]byte)(&peer.handshake.remoteStatic)) - keyf("preshared_key", (*[32]byte)(&peer.handshake.presharedKey)) - sendf("protocol_version=1") - if peer.endpoint != nil { - sendf("endpoint=%s", peer.endpoint.DstToString()) - } - - nano := atomic.LoadInt64(&peer.stats.lastHandshakeNano) - secs := nano / time.Second.Nanoseconds() - nano %= time.Second.Nanoseconds() - - sendf("last_handshake_time_sec=%d", secs) - sendf("last_handshake_time_nsec=%d", nano) - sendf("tx_bytes=%d", atomic.LoadUint64(&peer.stats.txBytes)) - sendf("rx_bytes=%d", atomic.LoadUint64(&peer.stats.rxBytes)) - sendf("persistent_keepalive_interval=%d", atomic.LoadUint32(&peer.persistentKeepaliveInterval)) - - device.allowedips.EntriesForPeer(peer, func(prefix netip.Prefix) bool { - sendf("allowed_ip=%s", prefix.String()) - return true - }) + // Serialize peer state. + // Do the work in an anonymous function so that we can use defer. + func() { + peer.RLock() + defer peer.RUnlock() + + keyf("public_key", (*[32]byte)(&peer.handshake.remoteStatic)) + keyf("preshared_key", (*[32]byte)(&peer.handshake.presharedKey)) + sendf("protocol_version=1") + if peer.endpoint != nil { + sendf("endpoint=%s", peer.endpoint.DstToString()) + } + + nano := atomic.LoadInt64(&peer.stats.lastHandshakeNano) + secs := nano / time.Second.Nanoseconds() + nano %= time.Second.Nanoseconds() + + sendf("last_handshake_time_sec=%d", secs) + sendf("last_handshake_time_nsec=%d", nano) + sendf("tx_bytes=%d", atomic.LoadUint64(&peer.stats.txBytes)) + sendf("rx_bytes=%d", atomic.LoadUint64(&peer.stats.rxBytes)) + sendf("persistent_keepalive_interval=%d", atomic.LoadUint32(&peer.persistentKeepaliveInterval)) + + device.allowedips.EntriesForPeer(peer, func(prefix netip.Prefix) bool { + sendf("allowed_ip=%s", prefix.String()) + return true + }) + }() } }() |