Skip to content

Commit

Permalink
conn: set SO_{SND,RCV}BUF to 7MB on the Bind UDP socket
Browse files Browse the repository at this point in the history
The conn.Bind UDP socket send and receive buffers are now being sized to
7MB, whereas they were previously inheriting the system defaults. The
value of 7MB is chosen as it is the max supported by a default
configuration of macOS. Some platforms will silently clamp the value to
other maximums. On Linux, we use SO_{SND,RCV}BUFFORCE in case 7MB is
beyond net.core.{r,w}mem_max.

Signed-off-by: Jordan Whited <jordan@tailscale.com>
Signed-off-by: James Tucker <james@tailscale.com>
Co-authored-by: James Tucker <james@tailscale.com>
  • Loading branch information
jwhited and raggi committed Mar 2, 2023
1 parent e6bfbdf commit aeed2ba
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 0 deletions.
7 changes: 7 additions & 0 deletions conn/controlfns.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ import (
"syscall"
)

// UDP socket read/write buffer size (7MB). The value of 7MB is chosen as it is
// the max supported by a default configuration of macOS. Some platforms will
// silently clamp the value to other maximums, such as linux clamping to
// net.core.{r,w}mem_max (see _linux.go for additional implementation that works
// around this limitation)
const socketBufferSize = 7 << 20

// controlFn is the callback function signature from net.ListenConfig.Control.
// It is used to apply platform specific configuration to the socket prior to
// bind.
Expand Down
15 changes: 15 additions & 0 deletions conn/controlfns_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@ import (
func init() {
controlFns = append(controlFns,

// Attempt to set the socket buffer size beyond net.core.{r,w}mem_max by
// using SO_*BUFFORCE. This requires CAP_NET_ADMIN, and is allowed here to
// fail silently - the result of failure is lower performance on very fast
// links or high latency links.
func(network, address string, c syscall.RawConn) error {
return c.Control(func(fd uintptr) {
// Set up to *mem_max
_ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_RCVBUF, socketBufferSize)
_ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_SNDBUF, socketBufferSize)
// Set beyond *mem_max if CAP_NET_ADMIN
_ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_RCVBUFFORCE, socketBufferSize)
_ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_SNDBUFFORCE, socketBufferSize)
})
},

// Enable receiving of the packet information (IP_PKTINFO for IPv4,
// IPV6_PKTINFO for IPv6) that is used to implement sticky socket support.
func(network, address string, c syscall.RawConn) error {
Expand Down
9 changes: 9 additions & 0 deletions conn/controlfns_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ import (

func init() {
controlFns = append(controlFns,
// Set SO_RCVBUF/SO_SNDBUF - this could be common with the _windows code except
// for the unfortunate type specificity of syscall.Handle.
func(network, address string, c syscall.RawConn) error {
return c.Control(func(fd uintptr) {
_ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_RCVBUF, socketBufferSize)
_ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_SNDBUF, socketBufferSize)
})
},

func(network, address string, c syscall.RawConn) error {
var err error
if network == "udp6" {
Expand Down
21 changes: 21 additions & 0 deletions conn/controlfns_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
*/

package conn

import "syscall"

func init() {
controlFns = append(controlFns,
// Set SO_RCVBUF/SO_SNDBUF - this could be common with the _unix code except
// for the unfortunate type specificity of syscall.Handle.
func(network, address string, c syscall.RawConn) error {
return c.Control(func(fd uintptr) {
_ = syscall.SetsockoptInt(syscall.Handle(fd), syscall.SOL_SOCKET, syscall.SO_RCVBUF, socketBufferSize)
_ = syscall.SetsockoptInt(syscall.Handle(fd), syscall.SOL_SOCKET, syscall.SO_SNDBUF, socketBufferSize)
})
},
)
}

0 comments on commit aeed2ba

Please sign in to comment.