summaryrefslogtreecommitdiffhomepage
path: root/device
diff options
context:
space:
mode:
authorJosh Bleecher Snyder <josh@tailscale.com>2021-11-18 15:37:24 -0800
committerJason A. Donenfeld <Jason@zx2c4.com>2021-11-23 22:03:15 +0100
commit387f7c461a16b28af2f19d31f9da2cc544e487c4 (patch)
tree550db377e7e5243e61ab9f67564db03eefd23ef0 /device
parent4d87c9e8246072d4880e6f198f81ad4675872d86 (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>
Diffstat (limited to 'device')
-rw-r--r--device/uapi.go54
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
+ })
+ }()
}
}()