forked from quic-go/quic-go
disable GSO and ECN on kernels older than version 5 (#4456)
This commit is contained in:
12
quic_suite_linux_test.go
Normal file
12
quic_suite_linux_test.go
Normal file
@@ -0,0 +1,12 @@
|
||||
//go:build linux
|
||||
|
||||
package quic
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func init() {
|
||||
major, minor := kernelVersion()
|
||||
fmt.Printf("Kernel Version: %d.%d\n\n", major, minor)
|
||||
}
|
||||
@@ -33,4 +33,6 @@ func parseIPv4PktInfo(body []byte) (ip netip.Addr, ifIndex uint32, ok bool) {
|
||||
return netip.AddrFrom4(*(*[4]byte)(body[8:12])), binary.LittleEndian.Uint32(body), true
|
||||
}
|
||||
|
||||
func isGSOSupported(syscall.RawConn) bool { return false }
|
||||
func isGSOEnabled(syscall.RawConn) bool { return false }
|
||||
|
||||
func isECNEnabled() bool { return !isECNDisabledUsingEnv() }
|
||||
|
||||
@@ -28,4 +28,6 @@ func parseIPv4PktInfo(body []byte) (ip netip.Addr, _ uint32, ok bool) {
|
||||
return netip.AddrFrom4(*(*[4]byte)(body)), 0, true
|
||||
}
|
||||
|
||||
func isGSOSupported(syscall.RawConn) bool { return false }
|
||||
func isGSOEnabled(syscall.RawConn) bool { return false }
|
||||
|
||||
func isECNEnabled() bool { return !isECNDisabledUsingEnv() }
|
||||
|
||||
@@ -23,6 +23,12 @@ const ecnIPv4DataLen = 1
|
||||
|
||||
const batchSize = 8 // needs to smaller than MaxUint8 (otherwise the type of oobConn.readPos has to be changed)
|
||||
|
||||
var kernelVersionMajor int
|
||||
|
||||
func init() {
|
||||
kernelVersionMajor, _ = kernelVersion()
|
||||
}
|
||||
|
||||
func forceSetReceiveBuffer(c syscall.RawConn, bytes int) error {
|
||||
var serr error
|
||||
if err := c.Control(func(fd uintptr) {
|
||||
@@ -55,9 +61,12 @@ func parseIPv4PktInfo(body []byte) (ip netip.Addr, ifIndex uint32, ok bool) {
|
||||
return netip.AddrFrom4(*(*[4]byte)(body[8:12])), binary.LittleEndian.Uint32(body), true
|
||||
}
|
||||
|
||||
// isGSOSupported tests if the kernel supports GSO.
|
||||
// isGSOEnabled tests if the kernel supports GSO.
|
||||
// Sending with GSO might still fail later on, if the interface doesn't support it (see isGSOError).
|
||||
func isGSOSupported(conn syscall.RawConn) bool {
|
||||
func isGSOEnabled(conn syscall.RawConn) bool {
|
||||
if kernelVersionMajor < 5 {
|
||||
return false
|
||||
}
|
||||
disabled, err := strconv.ParseBool(os.Getenv("QUIC_GO_DISABLE_GSO"))
|
||||
if err == nil && disabled {
|
||||
return false
|
||||
@@ -108,3 +117,40 @@ func isPermissionError(err error) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isECNEnabled() bool {
|
||||
return kernelVersionMajor >= 5 && !isECNDisabledUsingEnv()
|
||||
}
|
||||
|
||||
// kernelVersion returns major and minor kernel version numbers, parsed from
|
||||
// the syscall.Uname's Release field, or 0, 0 if the version can't be obtained
|
||||
// or parsed.
|
||||
//
|
||||
// copied from the standard library's internal/syscall/unix/kernel_version_linux.go
|
||||
func kernelVersion() (major, minor int) {
|
||||
var uname syscall.Utsname
|
||||
if err := syscall.Uname(&uname); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
values [2]int
|
||||
value, vi int
|
||||
)
|
||||
for _, c := range uname.Release {
|
||||
if '0' <= c && c <= '9' {
|
||||
value = (value * 10) + int(c-'0')
|
||||
} else {
|
||||
// Note that we're assuming N.N.N here.
|
||||
// If we see anything else, we are likely to mis-parse it.
|
||||
values[vi] = value
|
||||
vi++
|
||||
if vi >= len(values) {
|
||||
break
|
||||
}
|
||||
value = 0
|
||||
}
|
||||
}
|
||||
|
||||
return values[0], values[1]
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ func inspectWriteBuffer(c syscall.RawConn) (int, error) {
|
||||
return size, serr
|
||||
}
|
||||
|
||||
func isECNDisabled() bool {
|
||||
func isECNDisabledUsingEnv() bool {
|
||||
disabled, err := strconv.ParseBool(os.Getenv("QUIC_GO_DISABLE_ECN"))
|
||||
return err == nil && disabled
|
||||
}
|
||||
@@ -147,8 +147,8 @@ func newConn(c OOBCapablePacketConn, supportsDF bool) (*oobConn, error) {
|
||||
readPos: batchSize,
|
||||
cap: connCapabilities{
|
||||
DF: supportsDF,
|
||||
GSO: isGSOSupported(rawConn),
|
||||
ECN: !isECNDisabled(),
|
||||
GSO: isGSOEnabled(rawConn),
|
||||
ECN: isECNEnabled(),
|
||||
},
|
||||
}
|
||||
for i := 0; i < batchSize; i++ {
|
||||
@@ -247,7 +247,7 @@ func (c *oobConn) WritePacket(b []byte, addr net.Addr, packetInfoOOB []byte, gso
|
||||
}
|
||||
if ecn != protocol.ECNUnsupported {
|
||||
if !c.capabilities().ECN {
|
||||
panic("tried to send a ECN-marked packet although ECN is disabled")
|
||||
panic("tried to send an ECN-marked packet although ECN is disabled")
|
||||
}
|
||||
if remoteUDPAddr, ok := addr.(*net.UDPAddr); ok {
|
||||
if remoteUDPAddr.IP.To4() != nil {
|
||||
|
||||
Reference in New Issue
Block a user