]> git.ipfire.org Git - thirdparty/wireguard-go.git/commitdiff
device: reduce peer lock critical section in UAPI
authorJosh Bleecher Snyder <josh@tailscale.com>
Thu, 18 Nov 2021 23:37:24 +0000 (15:37 -0800)
committerJason A. Donenfeld <Jason@zx2c4.com>
Tue, 23 Nov 2021 21:03:15 +0000 (22:03 +0100)
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>
device/uapi.go

index 98e83110483162d05cb78ca2c5b0e0c819af5273..f3acf819213769e17e4999ca12ccb2179d2a0b69 100644 (file)
@@ -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
+                               })
+                       }()
                }
        }()