Skip to content

Commit 9e2f386

Browse files
jwhitedraggi
authored andcommitted
conn, device, tun: implement vectorized I/O on Linux
Implement TCP offloading via TSO and GRO for the Linux tun.Device, which is made possible by virtio extensions in the kernel's TUN driver. Delete conn.LinuxSocketEndpoint in favor of a collapsed conn.StdNetBind. conn.StdNetBind makes use of recvmmsg() and sendmmsg() on Linux. All platforms now fall under conn.StdNetBind, except for Windows, which remains in conn.WinRingBind, which still needs to be adjusted to handle multiple packets. Also refactor sticky sockets support to eventually be applicable on platforms other than just Linux. However Linux remains the sole platform that fully implements it for now. Co-authored-by: James Tucker <[email protected]> Signed-off-by: James Tucker <[email protected]> Signed-off-by: Jordan Whited <[email protected]> Signed-off-by: Jason A. Donenfeld <[email protected]>
1 parent 3bb8fec commit 9e2f386

24 files changed

+1870
-787
lines changed

conn/bind_linux.go

Lines changed: 0 additions & 587 deletions
This file was deleted.

conn/bind_std.go

Lines changed: 239 additions & 100 deletions
Large diffs are not rendered by default.

conn/boundif_android.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
package conn
77

8-
func (bind *StdNetBind) PeekLookAtSocketFd4() (fd int, err error) {
9-
sysconn, err := bind.ipv4.SyscallConn()
8+
func (s *StdNetBind) PeekLookAtSocketFd4() (fd int, err error) {
9+
sysconn, err := s.ipv4.SyscallConn()
1010
if err != nil {
1111
return -1, err
1212
}
@@ -19,8 +19,8 @@ func (bind *StdNetBind) PeekLookAtSocketFd4() (fd int, err error) {
1919
return
2020
}
2121

22-
func (bind *StdNetBind) PeekLookAtSocketFd6() (fd int, err error) {
23-
sysconn, err := bind.ipv6.SyscallConn()
22+
func (s *StdNetBind) PeekLookAtSocketFd6() (fd int, err error) {
23+
sysconn, err := s.ipv6.SyscallConn()
2424
if err != nil {
2525
return -1, err
2626
}

conn/conn.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
)
1717

1818
const (
19-
DefaultBatchSize = 1 // maximum number of packets handled per read and write
19+
DefaultBatchSize = 128 // maximum number of packets handled per read and write
2020
)
2121

2222
// A ReceiveFunc receives at least one packet from the network and writes them

conn/controlfns.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/* SPDX-License-Identifier: MIT
2+
*
3+
* Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
4+
*/
5+
6+
package conn
7+
8+
import (
9+
"net"
10+
"syscall"
11+
)
12+
13+
// controlFn is the callback function signature from net.ListenConfig.Control.
14+
// It is used to apply platform specific configuration to the socket prior to
15+
// bind.
16+
type controlFn func(network, address string, c syscall.RawConn) error
17+
18+
// controlFns is a list of functions that are called from the listen config
19+
// that can apply socket options.
20+
var controlFns = []controlFn{}
21+
22+
// listenConfig returns a net.ListenConfig that applies the controlFns to the
23+
// socket prior to bind. This is used to apply socket buffer sizing and packet
24+
// information OOB configuration for sticky sockets.
25+
func listenConfig() *net.ListenConfig {
26+
return &net.ListenConfig{
27+
Control: func(network, address string, c syscall.RawConn) error {
28+
for _, fn := range controlFns {
29+
if err := fn(network, address, c); err != nil {
30+
return err
31+
}
32+
}
33+
return nil
34+
},
35+
}
36+
}

conn/controlfns_linux.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/* SPDX-License-Identifier: MIT
2+
*
3+
* Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
4+
*/
5+
6+
package conn
7+
8+
import (
9+
"fmt"
10+
"syscall"
11+
12+
"golang.org/x/sys/unix"
13+
)
14+
15+
func init() {
16+
controlFns = append(controlFns,
17+
18+
// Enable receiving of the packet information (IP_PKTINFO for IPv4,
19+
// IPV6_PKTINFO for IPv6) that is used to implement sticky socket support.
20+
func(network, address string, c syscall.RawConn) error {
21+
var err error
22+
switch network {
23+
case "udp4":
24+
c.Control(func(fd uintptr) {
25+
err = unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_PKTINFO, 1)
26+
})
27+
case "udp6":
28+
c.Control(func(fd uintptr) {
29+
err = unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_RECVPKTINFO, 1)
30+
if err != nil {
31+
return
32+
}
33+
err = unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_V6ONLY, 1)
34+
})
35+
default:
36+
err = fmt.Errorf("unhandled network: %s: %w", network, unix.EINVAL)
37+
}
38+
return err
39+
},
40+
)
41+
}

conn/controlfns_unix.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//go:build !windows && !linux && !js
2+
3+
/* SPDX-License-Identifier: MIT
4+
*
5+
* Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
6+
*/
7+
8+
package conn
9+
10+
import (
11+
"syscall"
12+
13+
"golang.org/x/sys/unix"
14+
)
15+
16+
func init() {
17+
controlFns = append(controlFns,
18+
func(network, address string, c syscall.RawConn) error {
19+
var err error
20+
if network == "udp6" {
21+
c.Control(func(fd uintptr) {
22+
err = unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_V6ONLY, 1)
23+
})
24+
}
25+
return err
26+
},
27+
)
28+
}

conn/default.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build !linux && !windows
1+
//go:build !windows
22

33
/* SPDX-License-Identifier: MIT
44
*

conn/mark_default.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77

88
package conn
99

10-
func (bind *StdNetBind) SetMark(mark uint32) error {
10+
func (s *StdNetBind) SetMark(mark uint32) error {
1111
return nil
1212
}

conn/mark_unix.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ func init() {
2626
}
2727
}
2828

29-
func (bind *StdNetBind) SetMark(mark uint32) error {
29+
func (s *StdNetBind) SetMark(mark uint32) error {
3030
var operr error
3131
if fwmarkIoctl == 0 {
3232
return nil
3333
}
34-
if bind.ipv4 != nil {
35-
fd, err := bind.ipv4.SyscallConn()
34+
if s.ipv4 != nil {
35+
fd, err := s.ipv4.SyscallConn()
3636
if err != nil {
3737
return err
3838
}
@@ -46,8 +46,8 @@ func (bind *StdNetBind) SetMark(mark uint32) error {
4646
return err
4747
}
4848
}
49-
if bind.ipv6 != nil {
50-
fd, err := bind.ipv6.SyscallConn()
49+
if s.ipv6 != nil {
50+
fd, err := s.ipv6.SyscallConn()
5151
if err != nil {
5252
return err
5353
}

0 commit comments

Comments
 (0)