Source file
src/net/mptcpsock_linux_test.go
1
2
3
4
5 package net
6
7 import (
8 "bytes"
9 "context"
10 "errors"
11 "syscall"
12 "testing"
13 )
14
15 func newLocalListenerMPTCP(t *testing.T, envVar bool) Listener {
16 lc := &ListenConfig{}
17
18 if envVar {
19 if !lc.MultipathTCP() {
20 t.Fatal("MultipathTCP Listen is not on despite GODEBUG=multipathtcp=1")
21 }
22 } else {
23 if lc.MultipathTCP() {
24 t.Error("MultipathTCP should be off by default")
25 }
26
27 lc.SetMultipathTCP(true)
28 if !lc.MultipathTCP() {
29 t.Fatal("MultipathTCP is not on after having been forced to on")
30 }
31 }
32
33 ln, err := lc.Listen(context.Background(), "tcp", "127.0.0.1:0")
34 if err != nil {
35 t.Fatal(err)
36 }
37 return ln
38 }
39
40 func postAcceptMPTCP(ls *localServer, ch chan<- error) {
41 defer close(ch)
42
43 if len(ls.cl) == 0 {
44 ch <- errors.New("no accepted stream")
45 return
46 }
47
48 c := ls.cl[0]
49
50 tcp, ok := c.(*TCPConn)
51 if !ok {
52 ch <- errors.New("struct is not a TCPConn")
53 return
54 }
55
56 mptcp, err := tcp.MultipathTCP()
57 if err != nil {
58 ch <- err
59 return
60 }
61
62 if !mptcp {
63 ch <- errors.New("incoming connection is not with MPTCP")
64 return
65 }
66
67
68 if hasSOLMPTCP && !isUsingMPTCPProto(tcp.fd) {
69 ch <- errors.New("incoming connection is not an MPTCP proto")
70 return
71 }
72 }
73
74 func dialerMPTCP(t *testing.T, addr string, envVar bool) {
75 d := &Dialer{}
76
77 if envVar {
78 if !d.MultipathTCP() {
79 t.Fatal("MultipathTCP Dialer is not on despite GODEBUG=multipathtcp=1")
80 }
81 } else {
82 if d.MultipathTCP() {
83 t.Error("MultipathTCP should be off by default")
84 }
85
86 d.SetMultipathTCP(true)
87 if !d.MultipathTCP() {
88 t.Fatal("MultipathTCP is not on after having been forced to on")
89 }
90 }
91
92 c, err := d.Dial("tcp", addr)
93 if err != nil {
94 t.Fatal(err)
95 }
96 defer c.Close()
97
98 tcp, ok := c.(*TCPConn)
99 if !ok {
100 t.Fatal("struct is not a TCPConn")
101 }
102
103
104 snt := []byte("MPTCP TEST")
105 if _, err := c.Write(snt); err != nil {
106 t.Fatal(err)
107 }
108 b := make([]byte, len(snt))
109 if _, err := c.Read(b); err != nil {
110 t.Fatal(err)
111 }
112 if !bytes.Equal(snt, b) {
113 t.Errorf("sent bytes (%s) are different from received ones (%s)", snt, b)
114 }
115
116 mptcp, err := tcp.MultipathTCP()
117 if err != nil {
118 t.Fatal(err)
119 }
120
121 t.Logf("outgoing connection from %s with mptcp: %t", addr, mptcp)
122
123 if !mptcp {
124 t.Error("outgoing connection is not with MPTCP")
125 }
126
127
128 if hasSOLMPTCP && !isUsingMPTCPProto(tcp.fd) {
129 t.Error("outgoing connection is not an MPTCP proto")
130 }
131 }
132
133 func canCreateMPTCPSocket() bool {
134
135
136 fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, _IPPROTO_MPTCP)
137 if err != nil {
138 return false
139 }
140
141 syscall.Close(fd)
142 return true
143 }
144
145 func testMultiPathTCP(t *testing.T, envVar bool) {
146 if envVar {
147 t.Log("Test with GODEBUG=multipathtcp=1")
148 t.Setenv("GODEBUG", "multipathtcp=1")
149 } else {
150 t.Log("Test with GODEBUG=multipathtcp=0")
151 t.Setenv("GODEBUG", "multipathtcp=0")
152 }
153
154 ln := newLocalListenerMPTCP(t, envVar)
155
156
157 ls := (&streamListener{Listener: ln}).newLocalServer()
158 defer ls.teardown()
159
160 if g, w := ls.Listener.Addr().Network(), "tcp"; g != w {
161 t.Fatalf("Network type mismatch: got %q, want %q", g, w)
162 }
163
164 genericCh := make(chan error)
165 mptcpCh := make(chan error)
166 handler := func(ls *localServer, ln Listener) {
167 ls.transponder(ln, genericCh)
168 postAcceptMPTCP(ls, mptcpCh)
169 }
170 if err := ls.buildup(handler); err != nil {
171 t.Fatal(err)
172 }
173
174 dialerMPTCP(t, ln.Addr().String(), envVar)
175
176 if err := <-genericCh; err != nil {
177 t.Error(err)
178 }
179 if err := <-mptcpCh; err != nil {
180 t.Error(err)
181 }
182 }
183
184 func TestMultiPathTCP(t *testing.T) {
185 if !canCreateMPTCPSocket() {
186 t.Skip("Cannot create MPTCP sockets")
187 }
188
189 for _, envVar := range []bool{false, true} {
190 testMultiPathTCP(t, envVar)
191 }
192 }
193
View as plain text