Create creates and populates a new Impl.
(logf logger.Logf, tundev *tstun.Wrapper, e wgengine.Engine, mc *magicsock.Conn, dialer *tsdial.Dialer, dns *dns.Manager, pm *proxymap.Mapper)
| 331 | |
| 332 | // Create creates and populates a new Impl. |
| 333 | func Create(logf logger.Logf, tundev *tstun.Wrapper, e wgengine.Engine, mc *magicsock.Conn, dialer *tsdial.Dialer, dns *dns.Manager, pm *proxymap.Mapper) (*Impl, error) { |
| 334 | if mc == nil { |
| 335 | return nil, errors.New("nil magicsock.Conn") |
| 336 | } |
| 337 | if tundev == nil { |
| 338 | return nil, errors.New("nil tundev") |
| 339 | } |
| 340 | if logf == nil { |
| 341 | return nil, errors.New("nil logger") |
| 342 | } |
| 343 | if e == nil { |
| 344 | return nil, errors.New("nil Engine") |
| 345 | } |
| 346 | if pm == nil { |
| 347 | return nil, errors.New("nil proxymap.Mapper") |
| 348 | } |
| 349 | if dialer == nil { |
| 350 | return nil, errors.New("nil Dialer") |
| 351 | } |
| 352 | ipstack := stack.New(stack.Options{ |
| 353 | NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol}, |
| 354 | TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol, udp.NewProtocol, icmp.NewProtocol4, icmp.NewProtocol6}, |
| 355 | }) |
| 356 | sackEnabledOpt := tcpip.TCPSACKEnabled(true) // TCP SACK is disabled by default |
| 357 | tcpipErr := ipstack.SetTransportProtocolOption(tcp.ProtocolNumber, &sackEnabledOpt) |
| 358 | if tcpipErr != nil { |
| 359 | return nil, fmt.Errorf("could not enable TCP SACK: %v", tcpipErr) |
| 360 | } |
| 361 | // See https://github.com/tailscale/tailscale/issues/9707 |
| 362 | // gVisor's RACK performs poorly. ACKs do not appear to be handled in a |
| 363 | // timely manner, leading to spurious retransmissions and a reduced |
| 364 | // congestion window. |
| 365 | tcpRecoveryOpt := tcpip.TCPRecovery(0) |
| 366 | tcpipErr = ipstack.SetTransportProtocolOption(tcp.ProtocolNumber, &tcpRecoveryOpt) |
| 367 | if tcpipErr != nil { |
| 368 | return nil, fmt.Errorf("could not disable TCP RACK: %v", tcpipErr) |
| 369 | } |
| 370 | // gVisor defaults to reno at the time of writing. We explicitly set reno |
| 371 | // congestion control in order to prevent unexpected changes. Netstack |
| 372 | // has an int overflow in sender congestion window arithmetic that is more |
| 373 | // prone to trigger with cubic congestion control. |
| 374 | // See https://github.com/google/gvisor/issues/11632 |
| 375 | renoOpt := tcpip.CongestionControlOption("reno") |
| 376 | tcpipErr = ipstack.SetTransportProtocolOption(tcp.ProtocolNumber, &renoOpt) |
| 377 | if tcpipErr != nil { |
| 378 | return nil, fmt.Errorf("could not set reno congestion control: %v", tcpipErr) |
| 379 | } |
| 380 | err := setTCPBufSizes(ipstack) |
| 381 | if err != nil { |
| 382 | return nil, err |
| 383 | } |
| 384 | supportedGSOKind := stack.GSONotSupported |
| 385 | supportedGROKind := groNotSupported |
| 386 | if runtime.GOOS == "linux" && buildfeatures.HasGRO { |
| 387 | // TODO(jwhited): add Windows support https://github.com/tailscale/corp/issues/21874 |
| 388 | supportedGROKind = tcpGROSupported |
| 389 | supportedGSOKind = stack.HostGSOSupported |
| 390 | } |
searching dependent graphs…