net/udprelay: use batching.Conn (#16866)

This significantly improves throughput of a peer relay server on Linux.

Server.packetReadLoop no longer passes sockets down the stack. Instead,
packet handling methods return a netip.AddrPort and []byte, which
packetReadLoop gathers together for eventual batched writes on the
appropriate socket(s).

Updates tailscale/corp#31164

Signed-off-by: Jordan Whited <jordan@tailscale.com>
This commit is contained in:
Jordan Whited
2025-08-19 14:44:39 -07:00
committed by GitHub
parent 5c560d7489
commit d4b7200129
6 changed files with 153 additions and 63 deletions
-1
View File
@@ -32,7 +32,6 @@ type Conn interface {
// message may fall on either side of a nonzero.
//
// Each [ipv6.Message.OOB] must be sized to at least MinControlMessageSize().
// len(msgs) must be at least MinReadBatchMsgsLen().
ReadBatch(msgs []ipv6.Message, flags int) (n int, err error)
// WriteBatchTo writes buffs to addr.
//
+2
View File
@@ -19,3 +19,5 @@ var controlMessageSize = 0
func MinControlMessageSize() int {
return controlMessageSize
}
const IdealBatchSize = 1
+2 -4
View File
@@ -384,7 +384,7 @@ func setGSOSizeInControl(control *[]byte, gsoSize uint16) {
}
// TryUpgradeToConn probes the capabilities of the OS and pconn, and upgrades
// pconn to a [Conn] if appropriate. A batch size of MinReadBatchMsgsLen() is
// pconn to a [Conn] if appropriate. A batch size of [IdealBatchSize] is
// suggested for the best performance.
func TryUpgradeToConn(pconn nettype.PacketConn, network string, batchSize int) nettype.PacketConn {
if runtime.GOOS != "linux" {
@@ -457,6 +457,4 @@ func MinControlMessageSize() int {
return controlMessageSize
}
func MinReadBatchMsgsLen() int {
return 128
}
const IdealBatchSize = 128
+2 -2
View File
@@ -310,7 +310,7 @@ func TestMinReadBatchMsgsLen(t *testing.T) {
// So long as magicsock uses [Conn], and [wireguard-go/conn.Bind] API is
// shaped for wireguard-go to control packet memory, these values should be
// aligned.
if MinReadBatchMsgsLen() != conn.IdealBatchSize {
t.Fatalf("MinReadBatchMsgsLen():%d != conn.IdealBatchSize(): %d", MinReadBatchMsgsLen(), conn.IdealBatchSize)
if IdealBatchSize != conn.IdealBatchSize {
t.Fatalf("IdealBatchSize: %d != conn.IdealBatchSize(): %d", IdealBatchSize, conn.IdealBatchSize)
}
}