perf(amneziawgnet): autotune the embedded TCP receive buffer up to 8 MB

gVisor ships with receive-buffer moderation off and a fixed 1 MB window
capped at 4 MB, so every client upload relayed through the embedded datapath
was window-bound on any real-world RTT. Moderation is now on and may grow a
connection to 8 MB; connections still start at gVisor's 1 MB default and
only grow while the relay drains them faster per RTT, so idle peers cost no
more memory.

Single-stream client upload through the panel's own embedded inbound
(netns client, 50 ms RTT via netem, 16 vCPU WSL2 host, iperf3 -t 15):

  before (fixed buffer)        308 / 309 Mbit/s
  moderation, 4 MB cap         312 / 311 Mbit/s
  moderation, 8 MB cap         490 / 509 Mbit/s
  0 ms RTT, before / after     1789-1928 / 1795 Mbit/s

No test can observe a gVisor tuning option without restating it; the numbers
come from a real panel + Xray run in network namespaces with a kernel
AmneziaWG client.
This commit is contained in:
MHSanaei
2026-10-25 11:31:38 +01:00
parent 64a7697f56
commit 96069e9393
+13
View File
@@ -27,6 +27,10 @@ import (
// 1024 starved simultaneous TCP slow-starts; channel.Endpoint drops silently when full.
const tunQueueDepth = 8192
// maxReceiveBuffer caps per-connection receive autotuning; gVisor's own 4 MB
// cap held a single client upload near 310 Mbit/s at 50 ms RTT.
const maxReceiveBuffer = 8 << 20
// stackTun implements amneziawg-go tun.Device over a gVisor channel endpoint,
// exposing *stack.Stack for forwarder attachment.
type stackTun struct {
@@ -63,6 +67,15 @@ func createNetTUNWithStack(localAddresses []netip.Addr, mtu int) (awgtun.Device,
if err := dev.stack.SetTransportProtocolOption(tcp.ProtocolNumber, &sackEnabledOpt); err != nil {
return nil, nil, fmt.Errorf("amneziawgnet: enable TCP SACK: %s", err)
}
// Connections start at gVisor's 1 MB default and only grow while the
// relay drains them faster per RTT, so idle peers cost no more memory.
rcvBufOpt := tcpip.TCPReceiveBufferSizeRangeOption{Min: tcp.MinBufferSize, Default: tcp.DefaultReceiveBufferSize, Max: maxReceiveBuffer}
moderateOpt := tcpip.TCPModerateReceiveBufferOption(true)
for _, opt := range []tcpip.SettableTransportProtocolOption{&rcvBufOpt, &moderateOpt} {
if err := dev.stack.SetTransportProtocolOption(tcp.ProtocolNumber, opt); err != nil {
return nil, nil, fmt.Errorf("amneziawgnet: tune TCP receive buffer: %s", err)
}
}
dev.notifyHandle = dev.ep.AddNotify(dev)
if err := dev.stack.CreateNIC(1, dev.ep); err != nil {
return nil, nil, fmt.Errorf("amneziawgnet: CreateNIC: %s", err)