summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2023-10-21 18:41:27 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2023-10-21 18:44:01 +0200
commit5d37bd24e14e3fff6c1ce61e299480beb3d68c00 (patch)
tree8daafeec3f91a4842ae7aa8fdba49f75c5db4d08
parent24ea13351eb7a06c3760f2eae18a484ce009fcf9 (diff)
conn: separate gso and sticky control
Android wants GSO but not sticky. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--conn/bind_std.go2
-rw-r--r--conn/gso_default.go21
-rw-r--r--conn/gso_linux.go65
-rw-r--r--conn/sticky_default.go (renamed from conn/control_default.go)13
-rw-r--r--conn/sticky_linux.go (renamed from conn/control_linux.go)51
-rw-r--r--conn/sticky_linux_test.go (renamed from conn/control_linux_test.go)10
6 files changed, 96 insertions, 66 deletions
diff --git a/conn/bind_std.go b/conn/bind_std.go
index 5a00f34..e1bcbd1 100644
--- a/conn/bind_std.go
+++ b/conn/bind_std.go
@@ -65,7 +65,7 @@ func NewStdNetBind() Bind {
msgs := make([]ipv6.Message, IdealBatchSize)
for i := range msgs {
msgs[i].Buffers = make(net.Buffers, 1)
- msgs[i].OOB = make([]byte, controlSize)
+ msgs[i].OOB = make([]byte, stickyControlSize+gsoControlSize)
}
return &msgs
},
diff --git a/conn/gso_default.go b/conn/gso_default.go
new file mode 100644
index 0000000..57780db
--- /dev/null
+++ b/conn/gso_default.go
@@ -0,0 +1,21 @@
+//go:build !linux
+
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
+ */
+
+package conn
+
+// getGSOSize parses control for UDP_GRO and if found returns its GSO size data.
+func getGSOSize(control []byte) (int, error) {
+ return 0, nil
+}
+
+// setGSOSize sets a UDP_SEGMENT in control based on gsoSize.
+func setGSOSize(control *[]byte, gsoSize uint16) {
+}
+
+// gsoControlSize returns the recommended buffer size for pooling sticky and UDP
+// offloading control data.
+const gsoControlSize = 0
diff --git a/conn/gso_linux.go b/conn/gso_linux.go
new file mode 100644
index 0000000..b8599ce
--- /dev/null
+++ b/conn/gso_linux.go
@@ -0,0 +1,65 @@
+//go:build linux
+
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
+ */
+
+package conn
+
+import (
+ "fmt"
+ "unsafe"
+
+ "golang.org/x/sys/unix"
+)
+
+const (
+ sizeOfGSOData = 2
+)
+
+// getGSOSize parses control for UDP_GRO and if found returns its GSO size data.
+func getGSOSize(control []byte) (int, error) {
+ var (
+ hdr unix.Cmsghdr
+ data []byte
+ rem = control
+ err error
+ )
+
+ for len(rem) > unix.SizeofCmsghdr {
+ hdr, data, rem, err = unix.ParseOneSocketControlMessage(rem)
+ if err != nil {
+ return 0, fmt.Errorf("error parsing socket control message: %w", err)
+ }
+ if hdr.Level == unix.SOL_UDP && hdr.Type == unix.UDP_GRO && len(data) >= sizeOfGSOData {
+ var gso uint16
+ copy(unsafe.Slice((*byte)(unsafe.Pointer(&gso)), sizeOfGSOData), data[:sizeOfGSOData])
+ return int(gso), nil
+ }
+ }
+ return 0, nil
+}
+
+// setGSOSize sets a UDP_SEGMENT in control based on gsoSize. It leaves existing
+// data in control untouched.
+func setGSOSize(control *[]byte, gsoSize uint16) {
+ existingLen := len(*control)
+ avail := cap(*control) - existingLen
+ space := unix.CmsgSpace(sizeOfGSOData)
+ if avail < space {
+ return
+ }
+ *control = (*control)[:cap(*control)]
+ gsoControl := (*control)[existingLen:]
+ hdr := (*unix.Cmsghdr)(unsafe.Pointer(&(gsoControl)[0]))
+ hdr.Level = unix.SOL_UDP
+ hdr.Type = unix.UDP_SEGMENT
+ hdr.SetLen(unix.CmsgLen(sizeOfGSOData))
+ copy((gsoControl)[unix.SizeofCmsghdr:], unsafe.Slice((*byte)(unsafe.Pointer(&gsoSize)), sizeOfGSOData))
+ *control = (*control)[:existingLen+space]
+}
+
+// gsoControlSize returns the recommended buffer size for pooling UDP
+// offloading control data.
+var gsoControlSize = unix.CmsgSpace(sizeOfGSOData)
diff --git a/conn/control_default.go b/conn/sticky_default.go
index 9459da5..0b21386 100644
--- a/conn/control_default.go
+++ b/conn/sticky_default.go
@@ -35,17 +35,8 @@ func getSrcFromControl(control []byte, ep *StdNetEndpoint) {
func setSrcControl(control *[]byte, ep *StdNetEndpoint) {
}
-// getGSOSize parses control for UDP_GRO and if found returns its GSO size data.
-func getGSOSize(control []byte) (int, error) {
- return 0, nil
-}
-
-// setGSOSize sets a UDP_SEGMENT in control based on gsoSize.
-func setGSOSize(control *[]byte, gsoSize uint16) {
-}
-
-// controlSize returns the recommended buffer size for pooling sticky and UDP
+// stickyControlSize returns the recommended buffer size for pooling sticky
// offloading control data.
-const controlSize = 0
+const stickyControlSize = 0
const StdNetSupportsStickySockets = false
diff --git a/conn/control_linux.go b/conn/sticky_linux.go
index 44a94e6..8e206e9 100644
--- a/conn/control_linux.go
+++ b/conn/sticky_linux.go
@@ -8,7 +8,6 @@
package conn
import (
- "fmt"
"net/netip"
"unsafe"
@@ -106,54 +105,8 @@ func setSrcControl(control *[]byte, ep *StdNetEndpoint) {
*control = append(*control, ep.src...)
}
-const (
- sizeOfGSOData = 2
-)
-
-// getGSOSize parses control for UDP_GRO and if found returns its GSO size data.
-func getGSOSize(control []byte) (int, error) {
- var (
- hdr unix.Cmsghdr
- data []byte
- rem = control
- err error
- )
-
- for len(rem) > unix.SizeofCmsghdr {
- hdr, data, rem, err = unix.ParseOneSocketControlMessage(rem)
- if err != nil {
- return 0, fmt.Errorf("error parsing socket control message: %w", err)
- }
- if hdr.Level == unix.SOL_UDP && hdr.Type == unix.UDP_GRO && len(data) >= sizeOfGSOData {
- var gso uint16
- copy(unsafe.Slice((*byte)(unsafe.Pointer(&gso)), sizeOfGSOData), data[:sizeOfGSOData])
- return int(gso), nil
- }
- }
- return 0, nil
-}
-
-// setGSOSize sets a UDP_SEGMENT in control based on gsoSize. It leaves existing
-// data in control untouched.
-func setGSOSize(control *[]byte, gsoSize uint16) {
- existingLen := len(*control)
- avail := cap(*control) - existingLen
- space := unix.CmsgSpace(sizeOfGSOData)
- if avail < space {
- return
- }
- *control = (*control)[:cap(*control)]
- gsoControl := (*control)[existingLen:]
- hdr := (*unix.Cmsghdr)(unsafe.Pointer(&(gsoControl)[0]))
- hdr.Level = unix.SOL_UDP
- hdr.Type = unix.UDP_SEGMENT
- hdr.SetLen(unix.CmsgLen(sizeOfGSOData))
- copy((gsoControl)[unix.SizeofCmsghdr:], unsafe.Slice((*byte)(unsafe.Pointer(&gsoSize)), sizeOfGSOData))
- *control = (*control)[:existingLen+space]
-}
-
-// controlSize returns the recommended buffer size for pooling sticky and UDP
+// stickyControlSize returns the recommended buffer size for pooling sticky
// offloading control data.
-var controlSize = unix.CmsgSpace(unix.SizeofInet6Pktinfo) + unix.CmsgSpace(sizeOfGSOData)
+var stickyControlSize = unix.CmsgSpace(unix.SizeofInet6Pktinfo)
const StdNetSupportsStickySockets = true
diff --git a/conn/control_linux_test.go b/conn/sticky_linux_test.go
index 96f9da2..d2bd584 100644
--- a/conn/control_linux_test.go
+++ b/conn/sticky_linux_test.go
@@ -60,7 +60,7 @@ func Test_setSrcControl(t *testing.T) {
}
setSrc(ep, netip.MustParseAddr("127.0.0.1"), 5)
- control := make([]byte, controlSize)
+ control := make([]byte, stickyControlSize)
setSrcControl(&control, ep)
@@ -89,7 +89,7 @@ func Test_setSrcControl(t *testing.T) {
}
setSrc(ep, netip.MustParseAddr("::1"), 5)
- control := make([]byte, controlSize)
+ control := make([]byte, stickyControlSize)
setSrcControl(&control, ep)
@@ -113,7 +113,7 @@ func Test_setSrcControl(t *testing.T) {
})
t.Run("ClearOnNoSrc", func(t *testing.T) {
- control := make([]byte, controlSize)
+ control := make([]byte, stickyControlSize)
hdr := (*unix.Cmsghdr)(unsafe.Pointer(&control[0]))
hdr.Level = 1
hdr.Type = 2
@@ -129,7 +129,7 @@ func Test_setSrcControl(t *testing.T) {
func Test_getSrcFromControl(t *testing.T) {
t.Run("IPv4", func(t *testing.T) {
- control := make([]byte, controlSize)
+ control := make([]byte, stickyControlSize)
hdr := (*unix.Cmsghdr)(unsafe.Pointer(&control[0]))
hdr.Level = unix.IPPROTO_IP
hdr.Type = unix.IP_PKTINFO
@@ -149,7 +149,7 @@ func Test_getSrcFromControl(t *testing.T) {
}
})
t.Run("IPv6", func(t *testing.T) {
- control := make([]byte, controlSize)
+ control := make([]byte, stickyControlSize)
hdr := (*unix.Cmsghdr)(unsafe.Pointer(&control[0]))
hdr.Level = unix.IPPROTO_IPV6
hdr.Type = unix.IPV6_PKTINFO