...
Source file
src/net/mptcpsock_linux.go
Documentation: net
1
2
3
4
5 package net
6
7 import (
8 "context"
9 "errors"
10 "internal/poll"
11 "internal/syscall/unix"
12 "sync"
13 "syscall"
14 )
15
16 var (
17 mptcpOnce sync.Once
18 mptcpAvailable bool
19 hasSOLMPTCP bool
20 )
21
22
23 const (
24 _IPPROTO_MPTCP = 0x106
25 _SOL_MPTCP = 0x11c
26 _MPTCP_INFO = 0x1
27 )
28
29 func supportsMultipathTCP() bool {
30 mptcpOnce.Do(initMPTCPavailable)
31 return mptcpAvailable
32 }
33
34
35
36 func initMPTCPavailable() {
37 family := syscall.AF_INET
38 if !supportsIPv4() {
39 family = syscall.AF_INET6
40 }
41 s, err := sysSocket(family, syscall.SOCK_STREAM, _IPPROTO_MPTCP)
42
43 switch {
44 case errors.Is(err, syscall.EPROTONOSUPPORT):
45 return
46 case errors.Is(err, syscall.EINVAL):
47 return
48 case err == nil:
49 poll.CloseFunc(s)
50 fallthrough
51 default:
52
53 mptcpAvailable = true
54 }
55
56 major, minor := unix.KernelVersion()
57
58 hasSOLMPTCP = major > 5 || (major == 5 && minor >= 16)
59 }
60
61 func (sd *sysDialer) dialMPTCP(ctx context.Context, laddr, raddr *TCPAddr) (*TCPConn, error) {
62 if supportsMultipathTCP() {
63 if conn, err := sd.doDialTCPProto(ctx, laddr, raddr, _IPPROTO_MPTCP); err == nil {
64 return conn, nil
65 }
66 }
67
68
69
70
71
72
73
74 return sd.dialTCP(ctx, laddr, raddr)
75 }
76
77 func (sl *sysListener) listenMPTCP(ctx context.Context, laddr *TCPAddr) (*TCPListener, error) {
78 if supportsMultipathTCP() {
79 if dial, err := sl.listenTCPProto(ctx, laddr, _IPPROTO_MPTCP); err == nil {
80 return dial, nil
81 }
82 }
83
84
85
86
87
88
89
90 return sl.listenTCP(ctx, laddr)
91 }
92
93
94
95
96
97
98
99
100
101
102
103
104 func hasFallenBack(fd *netFD) bool {
105 _, err := fd.pfd.GetsockoptInt(_SOL_MPTCP, _MPTCP_INFO)
106
107
108
109
110 return err == syscall.EOPNOTSUPP || err == syscall.ENOPROTOOPT
111 }
112
113
114
115
116
117
118 func isUsingMPTCPProto(fd *netFD) bool {
119 proto, _ := fd.pfd.GetsockoptInt(syscall.SOL_SOCKET, syscall.SO_PROTOCOL)
120
121 return proto == _IPPROTO_MPTCP
122 }
123
124
125
126
127
128 func isUsingMultipathTCP(fd *netFD) bool {
129 if !supportsMultipathTCP() {
130 return false
131 }
132
133 if hasSOLMPTCP {
134 return !hasFallenBack(fd)
135 }
136
137 return isUsingMPTCPProto(fd)
138 }
139
View as plain text