@@ -170,6 +170,17 @@ const (
170
170
// CUBIC congestion control is the default in Windows, Linux, and MacOS, and generally achieves
171
171
// better throughput on large, long networks.
172
172
congestionControlCubic = "cubic"
173
+ // maxRetries is the maximum number of retransmissions that the TCP stack should undertake for
174
+ // unacked TCP segments, that is, when we are trying to send TCP data and the other side is
175
+ // unresponsive. It does not affect TCP operation while both sides are idle. The retry timeout
176
+ // has a minimum of 200ms and maximum of 120s, and grows exponentially when the other side is
177
+ // unresponsive. The default maxRetries in gVisor is 15, which means in practice over ten
178
+ // minutes of unresponsiveness before we time out. Setting to 5 should time out in 15-30s,
179
+ // depending on the latency of the connection. In Coder's system we depend on Wireguard as the
180
+ // underlay, which retries handshakes on a 5s timer, so we don't want to shorten the timeout
181
+ // less than 15s or so, to give us several chances to re-establish a Wireguard session after
182
+ // idling.
183
+ maxRetries = 5
173
184
)
174
185
175
186
// Create creates and populates a new Impl.
@@ -227,6 +238,11 @@ func Create(logf logger.Logf, tundev *tstun.Wrapper, e wgengine.Engine, mc *magi
227
238
if tcpipErr != nil {
228
239
return nil , fmt .Errorf ("could not set congestion control: %v" , tcpipErr )
229
240
}
241
+ retries := tcpip .TCPMaxRetriesOption (maxRetries )
242
+ tcpipErr = ipstack .SetTransportProtocolOption (tcp .ProtocolNumber , & retries )
243
+ if tcpipErr != nil {
244
+ return nil , fmt .Errorf ("could not set max retries: %v" , tcpipErr )
245
+ }
230
246
231
247
linkEP := NewEndpoint (512 , tstun .DefaultMTU (), "" )
232
248
if tcpipProblem := ipstack .CreateNIC (nicID , linkEP ); tcpipProblem != nil {
0 commit comments