From 0a9dd47dd817904ec2b4a80b551e6050218ee8a6 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 22 Sep 2020 09:30:31 +0700 Subject: net: reflect TCP backlog size update of uint16->uint32 on Linux The sk_max_ack_backlog was increased from uint16 to uint32 in kernel version 4.1 and above, so adopt that change to maxListenerBacklog. See https://github.com/torvalds/linux/commit/becb74f0acca19b5abfcb24dc602530f3deea66a Fixes #41470 Change-Id: I63a142eb28f3ac3acaca57f0903c085c6cb15a6e Reviewed-on: https://go-review.googlesource.com/c/go/+/255898 Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Trust: Cuong Manh Le Trust: Emmanuel Odeke Reviewed-by: Ian Lance Taylor Reviewed-by: Emmanuel Odeke --- src/net/sock_linux.go | 62 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 4 deletions(-) (limited to 'src/net/sock_linux.go') diff --git a/src/net/sock_linux.go b/src/net/sock_linux.go index 7bca37605e..4d91001937 100644 --- a/src/net/sock_linux.go +++ b/src/net/sock_linux.go @@ -6,6 +6,62 @@ package net import "syscall" +func kernelVersion() (major int, minor int) { + var uname syscall.Utsname + if err := syscall.Uname(&uname); err != nil { + return + } + + rl := uname.Release + var values [2]int + vi := 0 + value := 0 + for _, c := range rl { + if c >= '0' && 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 + } + } + } + switch vi { + case 0: + return 0, 0 + case 1: + return values[0], 0 + case 2: + return values[0], values[1] + } + return +} + +// Linux stores the backlog as: +// +// - uint16 in kernel version < 4.1, +// - uint32 in kernel version >= 4.1 +// +// Truncate number to avoid wrapping. +// +// See issue 5030 and 41470. +func maxAckBacklog(n int) int { + major, minor := kernelVersion() + size := 16 + if major > 4 || (major == 4 && minor >= 1) { + size = 32 + } + + var max uint = 1< max { + n = int(max) + } + return n +} + func maxListenerBacklog() int { fd, err := open("/proc/sys/net/core/somaxconn") if err != nil { @@ -21,11 +77,9 @@ func maxListenerBacklog() int { if n == 0 || !ok { return syscall.SOMAXCONN } - // Linux stores the backlog in a uint16. - // Truncate number to avoid wrapping. - // See issue 5030. + if n > 1<<16-1 { - n = 1<<16 - 1 + return maxAckBacklog(n) } return n } -- cgit v1.3 From 66c02645062561ac29d00297e8d8c49698b2e4da Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 19 Nov 2020 19:15:57 -0800 Subject: net, internal/poll: reset value before adding in minor kernel version Fixes #42733 Change-Id: I5446aeb5de13cd70212755fb12c9bc484f343c74 Reviewed-on: https://go-review.googlesource.com/c/go/+/271846 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Dmitri Shuralyov Reviewed-by: Cuong Manh Le TryBot-Result: Go Bot --- src/internal/poll/copy_file_range_linux.go | 1 + src/net/sock_linux.go | 1 + 2 files changed, 2 insertions(+) (limited to 'src/net/sock_linux.go') diff --git a/src/internal/poll/copy_file_range_linux.go b/src/internal/poll/copy_file_range_linux.go index 1635bb1bfc..fc34aef4cb 100644 --- a/src/internal/poll/copy_file_range_linux.go +++ b/src/internal/poll/copy_file_range_linux.go @@ -35,6 +35,7 @@ func kernelVersion() (major int, minor int) { if vi >= len(values) { break } + value = 0 } } switch vi { diff --git a/src/net/sock_linux.go b/src/net/sock_linux.go index 4d91001937..9f62ed3dee 100644 --- a/src/net/sock_linux.go +++ b/src/net/sock_linux.go @@ -27,6 +27,7 @@ func kernelVersion() (major int, minor int) { if vi >= len(values) { break } + value = 0 } } switch vi { -- cgit v1.3