github.com/cristalhq/netx@v0.0.0-20221116164110-442313ef3309/listener_linux.go (about) 1 //go:build linux 2 3 package netx 4 5 import ( 6 "fmt" 7 "io/ioutil" 8 "os" 9 "strconv" 10 "strings" 11 "syscall" 12 ) 13 14 const ( 15 soReusePort = 0x0F 16 tcpFastOpen = 0x17 17 ) 18 19 func disableNoDelay(fd int) error { 20 return newError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, 1)) 21 } 22 23 func enableReusePort(fd int) error { 24 return newError("setsockopt", syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, soReusePort, 1)) 25 } 26 27 func enableDeferAccept(fd int) error { 28 return newError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_DEFER_ACCEPT, 1)) 29 } 30 31 const fastOpenQueueLen = 16 * 1024 32 33 func enableFastOpen(fd int, queueLen int) error { 34 return newError("setsockopt", syscall.SetsockoptInt(fd, syscall.SOL_TCP, tcpFastOpen, queueLen)) 35 } 36 37 func soMaxConn() (int, error) { 38 data, err := ioutil.ReadFile(soMaxConnFilePath) 39 if err != nil { 40 // This error may trigger on travis build. Just use SOMAXCONN 41 if os.IsNotExist(err) { 42 return syscall.SOMAXCONN, nil 43 } 44 return -1, err 45 } 46 s := strings.TrimSpace(string(data)) 47 n, err := strconv.Atoi(s) 48 if err != nil || n <= 0 { 49 return -1, fmt.Errorf("cannot parse somaxconn %q read from %s: %s", s, soMaxConnFilePath, err) 50 } 51 52 // Linux stores the backlog in a uint16. 53 // Truncate number to avoid wrapping. 54 // See https://github.com/golang/go/issues/5030 . 55 if n > 1<<16-1 { 56 n = 1<<16 - 1 57 } 58 return n, nil 59 } 60 61 const soMaxConnFilePath = "/proc/sys/net/core/somaxconn" 62 63 func setDefaultSockopts(s, family, sotype int, ipv6only bool) error { 64 if family == syscall.AF_INET6 && sotype != syscall.SOCK_RAW { 65 // Allow both IP versions even if the OS default 66 // is otherwise. Note that some operating systems 67 // never admit this option. 68 err := newError("setsockopt", syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, boolint(ipv6only))) 69 if err != nil { 70 return err 71 } 72 } 73 74 // Allow broadcast. 75 return newError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)) 76 } 77 78 func boolint(b bool) int { 79 if b { 80 return 1 81 } 82 return 0 83 }