From 387f7c461a16b28af2f19d31f9da2cc544e487c4 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Thu, 18 Nov 2021 15:37:24 -0800 Subject: [PATCH] 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 Signed-off-by: Jason A. Donenfeld --- device/uapi.go | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 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() + // 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()) - } + 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() + 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)) + 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 - }) + device.allowedips.EntriesForPeer(peer, func(prefix netip.Prefix) bool { + sendf("allowed_ip=%s", prefix.String()) + return true + }) + }() } }()