net/udprelay: bind multiple sockets per af on Linux

This commit uses SO_REUSEPORT (when supported) to bind multiple sockets
per address family. Increasing the number of sockets can increase
aggregate throughput when serving many peer relay client flows.
Benchmarks show 3x improvement in max aggregate bitrate in some
environments.

Updates tailscale/corp#34745

Signed-off-by: Jordan Whited <jordan@tailscale.com>
This commit is contained in:
Jordan Whited
2025-12-02 11:38:47 -08:00
committed by Jordan Whited
parent e33f6aa3ba
commit 6a44990b09
3 changed files with 165 additions and 58 deletions

View File

@@ -0,0 +1,35 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
//go:build linux
package udprelay
import (
"net"
"syscall"
"golang.org/x/sys/unix"
)
func listenControl(_ string, _ string, c syscall.RawConn) error {
c.Control(func(fd uintptr) {
unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1)
})
return nil
}
func isReusableSocket(uc *net.UDPConn) bool {
rc, err := uc.SyscallConn()
if err != nil {
return false
}
var reusable bool
rc.Control(func(fd uintptr) {
val, err := unix.GetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT)
if err == nil && val == 1 {
reusable = true
}
})
return reusable
}