@@ -153,6 +153,27 @@ const nicID = 1
153
153
// one day making the MTU more dynamic.
154
154
const maxUDPPacketSize = 1500
155
155
156
+ const (
157
+ megabytes = 1024 * 1024
158
+ // recvBufSize is the size in bytes for TCP receive buffers. 6MiB is the usual maximum in
159
+ // Linux, but here we set it as the default, because unlike Linux, gVisor does not dynamically
160
+ // resize the buffer based on utilization. The channel that connects gVisor to Wireguard is 512
161
+ // packets and Wireguard encrypt and decrypt buffers are 1024 packets each, so we could queue
162
+ // 2.5k packets (over 2MiB), even before counting packets in flight on the network. The TCP
163
+ // window is set to half the recv buffer, or 3 MiB in this case. Since TCP will only send this
164
+ // much un-ACK'd data, this corresponds to max throughput of 3MiB per RTT (for example, 10 ms
165
+ // RTT is 300 MiB/s or 2.4 Gbit/s).
166
+ recvBufSize = 6 * megabytes
167
+ // sendBufSize is the size in bytes for the TCP send buffers. 4MiB is the usual maximum in
168
+ // Linux. The send buffer is used for both unsent and un-ACK'd data, so it is important that
169
+ // it is greater than half of the recvBufSize so that there is still room for unsent data from
170
+ // the application.
171
+ sendBufSize = 4 * megabytes
172
+ // CUBIC congestion control is the default in Windows, Linux, and MacOS, and generally achieves
173
+ // better throughput on large, long networks.
174
+ congestionControlCubic = "cubic"
175
+ )
176
+
156
177
// Create creates and populates a new Impl.
157
178
func Create (logf logger.Logf , tundev * tstun.Wrapper , e wgengine.Engine , mc * magicsock.Conn , dialer * tsdial.Dialer , dns * dns.Manager ) (* Impl , error ) {
158
179
if mc == nil {
@@ -174,13 +195,41 @@ func Create(logf logger.Logf, tundev *tstun.Wrapper, e wgengine.Engine, mc *magi
174
195
NetworkProtocols : []stack.NetworkProtocolFactory {ipv4 .NewProtocol , ipv6 .NewProtocol },
175
196
TransportProtocols : []stack.TransportProtocolFactory {tcp .NewProtocol , udp .NewProtocol , icmp .NewProtocol4 , icmp .NewProtocol6 },
176
197
})
177
- // Issue: https://github.com/coder/coder/issues/7388
178
- //
179
- /*sackEnabledOpt := tcpip.TCPSACKEnabled(true) // TCP SACK is disabled by default
198
+
199
+ sackEnabledOpt := tcpip .TCPSACKEnabled (true ) // TCP SACK is disabled by default
180
200
tcpipErr := ipstack .SetTransportProtocolOption (tcp .ProtocolNumber , & sackEnabledOpt )
181
201
if tcpipErr != nil {
182
202
return nil , fmt .Errorf ("could not enable TCP SACK: %v" , tcpipErr )
183
- }*/
203
+ }
204
+ soRecv := tcpip.TCPReceiveBufferSizeRangeOption {
205
+ Min : recvBufSize ,
206
+ Default : recvBufSize ,
207
+ Max : recvBufSize ,
208
+ }
209
+ tcpipErr = ipstack .SetTransportProtocolOption (tcp .ProtocolNumber , & soRecv )
210
+ if tcpipErr != nil {
211
+ return nil , fmt .Errorf ("could not set recv buf size: %v" , tcpipErr )
212
+ }
213
+ soSend := tcpip.TCPSendBufferSizeRangeOption {
214
+ Min : sendBufSize ,
215
+ Default : sendBufSize ,
216
+ Max : sendBufSize ,
217
+ }
218
+ tcpipErr = ipstack .SetTransportProtocolOption (tcp .ProtocolNumber , & soSend )
219
+ if tcpipErr != nil {
220
+ return nil , fmt .Errorf ("could not set send buf size: %v" , tcpipErr )
221
+ }
222
+ rack := tcpip .TCPRecovery (0 ) // Disable RACK
223
+ tcpipErr = ipstack .SetTransportProtocolOption (tcp .ProtocolNumber , & rack )
224
+ if tcpipErr != nil {
225
+ return nil , fmt .Errorf ("could not disable RACK: %v" , tcpipErr )
226
+ }
227
+ cc := tcpip .CongestionControlOption (congestionControlCubic )
228
+ tcpipErr = ipstack .SetTransportProtocolOption (tcp .ProtocolNumber , & cc )
229
+ if tcpipErr != nil {
230
+ return nil , fmt .Errorf ("could not set congestion control: %v" , tcpipErr )
231
+ }
232
+
184
233
linkEP := & protectedLinkEndpoint {Endpoint : channel .New (512 , tstun .DefaultMTU (), "" )}
185
234
if tcpipProblem := ipstack .CreateNIC (nicID , linkEP ); tcpipProblem != nil {
186
235
return nil , fmt .Errorf ("could not create netstack NIC: %v" , tcpipProblem )
@@ -256,10 +305,8 @@ func (ns *Impl) Start(lb *ipnlocal.LocalBackend) error {
256
305
ns .lb = lb
257
306
}
258
307
ns .e .AddNetworkMapCallback (ns .updateIPs )
259
- // size = 0 means use default buffer size
260
- const tcpReceiveBufferSize = 0
261
308
const maxInFlightConnectionAttempts = 1024
262
- tcpFwd := tcp .NewForwarder (ns .ipstack , tcpReceiveBufferSize , maxInFlightConnectionAttempts , ns .acceptTCP )
309
+ tcpFwd := tcp .NewForwarder (ns .ipstack , recvBufSize , maxInFlightConnectionAttempts , ns .acceptTCP )
263
310
udpFwd := udp .NewForwarder (ns .ipstack , ns .acceptUDP )
264
311
ns .ipstack .SetTransportProtocolHandler (tcp .ProtocolNumber , ns .wrapProtoHandler (tcpFwd .HandlePacket ))
265
312
ns .ipstack .SetTransportProtocolHandler (udp .ProtocolNumber , ns .wrapProtoHandler (udpFwd .HandlePacket ))
0 commit comments