]> git.ipfire.org Git - thirdparty/wireguard-go.git/commitdiff
device: reduce redundant per-packet overhead in RX path
authorJordan Whited <jordan@tailscale.com>
Tue, 7 Nov 2023 23:24:21 +0000 (15:24 -0800)
committerJason A. Donenfeld <Jason@zx2c4.com>
Mon, 11 Dec 2023 15:34:09 +0000 (16:34 +0100)
Peer.RoutineSequentialReceiver() deals with packet vectors and does not
need to perform timer and endpoint operations for every packet in a
given vector. Changing these per-packet operations to per-vector
improves throughput by as much as 10% in some environments.

Signed-off-by: Jordan Whited <jordan@tailscale.com>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
device/receive.go

index 4b32dc5871c72b0d16402112bcfbedd00e0efa02..98e2024dcba44020d146f22d66d57fe4babe26e0 100644 (file)
@@ -445,7 +445,9 @@ func (peer *Peer) RoutineSequentialReceiver(maxBatchSize int) {
                        return
                }
                elemsContainer.Lock()
-               for _, elem := range elemsContainer.elems {
+               validTailPacket := -1
+               dataPacketReceived := false
+               for i, elem := range elemsContainer.elems {
                        if elem.packet == nil {
                                // decryption failed
                                continue
@@ -455,21 +457,19 @@ func (peer *Peer) RoutineSequentialReceiver(maxBatchSize int) {
                                continue
                        }
 
-                       peer.SetEndpointFromPacket(elem.endpoint)
+                       validTailPacket = i
                        if peer.ReceivedWithKeypair(elem.keypair) {
+                               peer.SetEndpointFromPacket(elem.endpoint)
                                peer.timersHandshakeComplete()
                                peer.SendStagedPackets()
                        }
-                       peer.keepKeyFreshReceiving()
-                       peer.timersAnyAuthenticatedPacketTraversal()
-                       peer.timersAnyAuthenticatedPacketReceived()
                        peer.rxBytes.Add(uint64(len(elem.packet) + MinMessageSize))
 
                        if len(elem.packet) == 0 {
                                device.log.Verbosef("%v - Receiving keepalive packet", peer)
                                continue
                        }
-                       peer.timersDataReceived()
+                       dataPacketReceived = true
 
                        switch elem.packet[0] >> 4 {
                        case 4:
@@ -512,6 +512,15 @@ func (peer *Peer) RoutineSequentialReceiver(maxBatchSize int) {
 
                        bufs = append(bufs, elem.buffer[:MessageTransportOffsetContent+len(elem.packet)])
                }
+               if validTailPacket >= 0 {
+                       peer.SetEndpointFromPacket(elemsContainer.elems[validTailPacket].endpoint)
+                       peer.keepKeyFreshReceiving()
+                       peer.timersAnyAuthenticatedPacketTraversal()
+                       peer.timersAnyAuthenticatedPacketReceived()
+               }
+               if dataPacketReceived {
+                       peer.timersDataReceived()
+               }
                if len(bufs) > 0 {
                        _, err := device.tun.device.Write(bufs, MessageTransportOffsetContent)
                        if err != nil && !device.isClosed() {