Skip to content

Increase physical UDP receive and send buffers - #2611

Open
alatteri wants to merge 2 commits into
zerotier:devfrom
instinctual:agent/increase-udp-receive-buffer
Open

Increase physical UDP receive and send buffers#2611
alatteri wants to merge 2 commits into
zerotier:devfrom
instinctual:agent/increase-udp-receive-buffer

Conversation

@alatteri

@alatteri alatteri commented Aug 17, 2026

Copy link
Copy Markdown

Summary

  • split the physical UDP socket receive and send buffer configuration
  • increase the requested receive buffer from 1 MiB to 4 MiB
  • increase the requested send buffer from 1 MiB to 2 MiB
  • preserve the existing Phy::udpBind() API for callers that want one shared size
  • exercise the asymmetric bind path in the existing PHY self-test

Problem

ZeroTier currently applies the same 1 MiB request to both SO_RCVBUF and
SO_SNDBUF. On a high-throughput Linux relay carrying sustained real-time UDP
traffic, the physical ZeroTier sockets accumulated 3,205 UdpRcvbufErrors.
The socket drop counters reported by ss accounted for all 3,205 errors.

At the same time:

  • UdpSndbufErrors remained zero
  • physical-interface receive and transmit drops remained zero
  • the ZeroTier interface did not report receive drops
  • the Linux socket receive capacity was 2 MiB, reflecting Linux's doubled
    accounting for the 1 MiB request

This isolates the loss point to burst exhaustion of the physical UDP receive
socket rather than the NIC, route, virtual interface, or UDP send socket.

Separate high-throughput sending workloads can run at roughly twice this
relay's data rate and produce larger short spikes. Doubling the send request
provides moderate transient headroom for those bursts without matching the
larger receive allocation.

Change

Phy::udpBind() now accepts independent receive and send sizes. A compatibility
overload retains the original three-argument behavior by applying a shared size
to both directions, so existing callers do not change behavior.

The production Binder requests:

  • 4 MiB for SO_RCVBUF
  • 2 MiB for SO_SNDBUF

The existing fallback behavior is retained: if the operating system rejects a
requested size, ZeroTier retries progressively smaller values.

Send buffer sizing

The deployed relay did not exhibit send-buffer exhaustion, so the send increase
is not presented as a fix for its receive drops. The 2 MiB value is intended as
a balanced default for higher-rate, bursty senders: it doubles upstream's
transient headroom while remaining smaller than the receive request.

Additional send capacity only adds delay when the outbound path is backlogged.
Persistent Send-Q growth or UdpSndbufErrors still indicates an underlying
capacity or scheduling problem rather than a need for unbounded buffering.

Impact

The change does not alter ZeroTier's wire protocol, encryption, routing, or
packet ordering. It adds burst headroom to physical UDP bindings.
Systems may cap or account for socket buffers differently; the existing
best-effort fallback remains in effect.

On Linux, the 4 MiB/2 MiB requests report as 8 MiB receive and 4 MiB send due
to kernel socket-buffer accounting. The deployed host's net.core.rmem_max
was already large enough to permit the request.

Validation

  • make -j2 selftest
  • ./zerotier-selftest (including 10,000 UDP packets)
  • make -j2
  • isolated runtime socket inspection confirmed 8 MiB receive / 4 MiB send on Linux
  • a deployed 4 MiB/1 MiB build confirmed the receive behavior under sustained traffic

Deployed monitoring

The receive-buffer change was deployed with the original 1 MiB send request and
monitored continuously for 30 minutes 2 seconds under live relay traffic. This
run validates the receive-side change and provides a stable baseline; the 2 MiB
send request was validated separately by build, self-test, and isolated runtime
socket inspection. During the deployed window, the host processed:

  • 56,848,408 additional inbound UDP datagrams (about 31,500/second average)
  • 55,446,839 additional outbound UDP datagrams

The following counters remained zero for the entire run:

  • UdpInErrors
  • UdpRcvbufErrors
  • UdpSndbufErrors
  • physical-interface receive and transmit drops
  • ZeroTier-interface receive and transmit drops

The ZeroTier service remained active throughout. One downstream receiver was
rebooted during the window, changing outbound traffic volume without causing
any socket-buffer or interface drops on the relay.

@alatteri
alatteri marked this pull request as ready for review August 17, 2026 21:43
@alatteri
alatteri marked this pull request as draft August 17, 2026 21:49
@alatteri alatteri changed the title Increase physical UDP receive buffer Increase physical UDP receive and send buffers Aug 17, 2026
@alatteri
alatteri marked this pull request as ready for review September 4, 2026 16:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant