]> git.ipfire.org Git - thirdparty/wireguard-go.git/commitdiff
conn: don't enable GRO on Linux < 5.12
authorJason A. Donenfeld <Jason@zx2c4.com>
Wed, 21 May 2025 23:33:55 +0000 (01:33 +0200)
committerJason A. Donenfeld <Jason@zx2c4.com>
Wed, 21 May 2025 23:43:39 +0000 (01:43 +0200)
Kernels below 5.12 are missing this:

    commit 98184612aca0a9ee42b8eb0262a49900ee9eef0d
    Author: Norman Maurer <norman_maurer@apple.com>
    Date:   Thu Apr 1 08:59:17 2021

        net: udp: Add support for getsockopt(..., ..., UDP_GRO, ..., ...);

        Support for UDP_GRO was added in the past but the implementation for
        getsockopt was missed which did lead to an error when we tried to
        retrieve the setting for UDP_GRO. This patch adds the missing switch
        case for UDP_GRO

Fixes: e20cf8d3f1f7 ("udp: implement GRO for plain UDP sockets.")
Signed-off-by: Norman Maurer <norman_maurer@apple.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
That means we can't set the option and then read it back later. Given
how buggy UDP_GRO is in general on odd kernels, just disable it on older
kernels all together.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
conn/controlfns_linux.go

index 3447349f738a94172b6a83234713ad75d025d139..f0deefaaf7e3cf26762c06b9cbcd75a293f83696 100644 (file)
@@ -13,6 +13,35 @@ import (
        "golang.org/x/sys/unix"
 )
 
+// Taken from go/src/internal/syscall/unix/kernel_version_linux.go
+func kernelVersion() (major, minor int) {
+       var uname unix.Utsname
+       if err := unix.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]
+}
+
 func init() {
        controlFns = append(controlFns,
 
@@ -60,6 +89,17 @@ func init() {
 
                // Attempt to enable UDP_GRO
                func(network, address string, c syscall.RawConn) error {
+                       // Kernels below 5.12 are missing 98184612aca0 ("net:
+                       // udp: Add support for getsockopt(..., ..., UDP_GRO,
+                       // ..., ...);"), which means we can't read this back
+                       // later. We could pipe the return value through to
+                       // the rest of the code, but UDP_GRO is kind of buggy
+                       // anyway, so just gate this here.
+                       major, minor := kernelVersion()
+                       if major < 5 || (major == 5 && minor < 12) {
+                               return nil
+                       }
+
                        c.Control(func(fd uintptr) {
                                _ = unix.SetsockoptInt(int(fd), unix.IPPROTO_UDP, unix.UDP_GRO, 1)
                        })