conn: separate gso and sticky control
Android wants GSO but not sticky. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
parent
24ea13351e
commit
5d37bd24e1
@ -65,7 +65,7 @@ func NewStdNetBind() Bind {
|
|||||||
msgs := make([]ipv6.Message, IdealBatchSize)
|
msgs := make([]ipv6.Message, IdealBatchSize)
|
||||||
for i := range msgs {
|
for i := range msgs {
|
||||||
msgs[i].Buffers = make(net.Buffers, 1)
|
msgs[i].Buffers = make(net.Buffers, 1)
|
||||||
msgs[i].OOB = make([]byte, controlSize)
|
msgs[i].OOB = make([]byte, stickyControlSize+gsoControlSize)
|
||||||
}
|
}
|
||||||
return &msgs
|
return &msgs
|
||||||
},
|
},
|
||||||
|
21
conn/gso_default.go
Normal file
21
conn/gso_default.go
Normal file
@ -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
|
65
conn/gso_linux.go
Normal file
65
conn/gso_linux.go
Normal file
@ -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)
|
@ -35,17 +35,8 @@ func getSrcFromControl(control []byte, ep *StdNetEndpoint) {
|
|||||||
func setSrcControl(control *[]byte, ep *StdNetEndpoint) {
|
func setSrcControl(control *[]byte, ep *StdNetEndpoint) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// getGSOSize parses control for UDP_GRO and if found returns its GSO size data.
|
// stickyControlSize returns the recommended buffer size for pooling sticky
|
||||||
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
|
|
||||||
// offloading control data.
|
// offloading control data.
|
||||||
const controlSize = 0
|
const stickyControlSize = 0
|
||||||
|
|
||||||
const StdNetSupportsStickySockets = false
|
const StdNetSupportsStickySockets = false
|
@ -8,7 +8,6 @@
|
|||||||
package conn
|
package conn
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
@ -106,54 +105,8 @@ func setSrcControl(control *[]byte, ep *StdNetEndpoint) {
|
|||||||
*control = append(*control, ep.src...)
|
*control = append(*control, ep.src...)
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
// stickyControlSize returns the recommended buffer size for pooling sticky
|
||||||
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
|
|
||||||
// offloading control data.
|
// offloading control data.
|
||||||
var controlSize = unix.CmsgSpace(unix.SizeofInet6Pktinfo) + unix.CmsgSpace(sizeOfGSOData)
|
var stickyControlSize = unix.CmsgSpace(unix.SizeofInet6Pktinfo)
|
||||||
|
|
||||||
const StdNetSupportsStickySockets = true
|
const StdNetSupportsStickySockets = true
|
@ -60,7 +60,7 @@ func Test_setSrcControl(t *testing.T) {
|
|||||||
}
|
}
|
||||||
setSrc(ep, netip.MustParseAddr("127.0.0.1"), 5)
|
setSrc(ep, netip.MustParseAddr("127.0.0.1"), 5)
|
||||||
|
|
||||||
control := make([]byte, controlSize)
|
control := make([]byte, stickyControlSize)
|
||||||
|
|
||||||
setSrcControl(&control, ep)
|
setSrcControl(&control, ep)
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ func Test_setSrcControl(t *testing.T) {
|
|||||||
}
|
}
|
||||||
setSrc(ep, netip.MustParseAddr("::1"), 5)
|
setSrc(ep, netip.MustParseAddr("::1"), 5)
|
||||||
|
|
||||||
control := make([]byte, controlSize)
|
control := make([]byte, stickyControlSize)
|
||||||
|
|
||||||
setSrcControl(&control, ep)
|
setSrcControl(&control, ep)
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ func Test_setSrcControl(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("ClearOnNoSrc", func(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 := (*unix.Cmsghdr)(unsafe.Pointer(&control[0]))
|
||||||
hdr.Level = 1
|
hdr.Level = 1
|
||||||
hdr.Type = 2
|
hdr.Type = 2
|
||||||
@ -129,7 +129,7 @@ func Test_setSrcControl(t *testing.T) {
|
|||||||
|
|
||||||
func Test_getSrcFromControl(t *testing.T) {
|
func Test_getSrcFromControl(t *testing.T) {
|
||||||
t.Run("IPv4", func(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 := (*unix.Cmsghdr)(unsafe.Pointer(&control[0]))
|
||||||
hdr.Level = unix.IPPROTO_IP
|
hdr.Level = unix.IPPROTO_IP
|
||||||
hdr.Type = unix.IP_PKTINFO
|
hdr.Type = unix.IP_PKTINFO
|
||||||
@ -149,7 +149,7 @@ func Test_getSrcFromControl(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("IPv6", func(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 := (*unix.Cmsghdr)(unsafe.Pointer(&control[0]))
|
||||||
hdr.Level = unix.IPPROTO_IPV6
|
hdr.Level = unix.IPPROTO_IPV6
|
||||||
hdr.Type = unix.IPV6_PKTINFO
|
hdr.Type = unix.IPV6_PKTINFO
|
Loading…
Reference in New Issue
Block a user