Skip to content

Commit aeed2ba

Browse files
jwhitedraggi
andcommitted
conn: set SO_{SND,RCV}BUF to 7MB on the Bind UDP socket
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 <[email protected]> Signed-off-by: James Tucker <[email protected]> Co-authored-by: James Tucker <[email protected]>
1 parent e6bfbdf commit aeed2ba

File tree

4 files changed

+52
-0
lines changed

4 files changed

+52
-0
lines changed

conn/controlfns.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ import (
1010
"syscall"
1111
)
1212

13+
// UDP socket read/write buffer size (7MB). The value of 7MB is chosen as it is
14+
// the max supported by a default configuration of macOS. Some platforms will
15+
// silently clamp the value to other maximums, such as linux clamping to
16+
// net.core.{r,w}mem_max (see _linux.go for additional implementation that works
17+
// around this limitation)
18+
const socketBufferSize = 7 << 20
19+
1320
// controlFn is the callback function signature from net.ListenConfig.Control.
1421
// It is used to apply platform specific configuration to the socket prior to
1522
// bind.

conn/controlfns_linux.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,21 @@ import (
1515
func init() {
1616
controlFns = append(controlFns,
1717

18+
// Attempt to set the socket buffer size beyond net.core.{r,w}mem_max by
19+
// using SO_*BUFFORCE. This requires CAP_NET_ADMIN, and is allowed here to
20+
// fail silently - the result of failure is lower performance on very fast
21+
// links or high latency links.
22+
func(network, address string, c syscall.RawConn) error {
23+
return c.Control(func(fd uintptr) {
24+
// Set up to *mem_max
25+
_ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_RCVBUF, socketBufferSize)
26+
_ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_SNDBUF, socketBufferSize)
27+
// Set beyond *mem_max if CAP_NET_ADMIN
28+
_ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_RCVBUFFORCE, socketBufferSize)
29+
_ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_SNDBUFFORCE, socketBufferSize)
30+
})
31+
},
32+
1833
// Enable receiving of the packet information (IP_PKTINFO for IPv4,
1934
// IPV6_PKTINFO for IPv6) that is used to implement sticky socket support.
2035
func(network, address string, c syscall.RawConn) error {

conn/controlfns_unix.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,15 @@ import (
1515

1616
func init() {
1717
controlFns = append(controlFns,
18+
// Set SO_RCVBUF/SO_SNDBUF - this could be common with the _windows code except
19+
// for the unfortunate type specificity of syscall.Handle.
20+
func(network, address string, c syscall.RawConn) error {
21+
return c.Control(func(fd uintptr) {
22+
_ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_RCVBUF, socketBufferSize)
23+
_ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_SNDBUF, socketBufferSize)
24+
})
25+
},
26+
1827
func(network, address string, c syscall.RawConn) error {
1928
var err error
2029
if network == "udp6" {

conn/controlfns_windows.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/* SPDX-License-Identifier: MIT
2+
*
3+
* Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
4+
*/
5+
6+
package conn
7+
8+
import "syscall"
9+
10+
func init() {
11+
controlFns = append(controlFns,
12+
// Set SO_RCVBUF/SO_SNDBUF - this could be common with the _unix code except
13+
// for the unfortunate type specificity of syscall.Handle.
14+
func(network, address string, c syscall.RawConn) error {
15+
return c.Control(func(fd uintptr) {
16+
_ = syscall.SetsockoptInt(syscall.Handle(fd), syscall.SOL_SOCKET, syscall.SO_RCVBUF, socketBufferSize)
17+
_ = syscall.SetsockoptInt(syscall.Handle(fd), syscall.SOL_SOCKET, syscall.SO_SNDBUF, socketBufferSize)
18+
})
19+
},
20+
)
21+
}

0 commit comments

Comments
 (0)