From 6288fe9f25cc4a315c669fb52bcf77c4e242044d Mon Sep 17 00:00:00 2001 From: Siavash Sameni Date: Tue, 31 Mar 2026 19:13:46 +0400 Subject: [PATCH] Fix IPv6 UDP TX: reset consecutive_errors after yield, pace every 16 pkts ENOBUFS hits every send on macOS IPv6 because the interface output queue is full. The adaptive backoff never recovered because consecutive_errors never reset. Now reset after sleeping, and yield more frequently (every 16 packets instead of 64). Co-Authored-By: Claude Opus 4.6 (1M context) --- src/server.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/server.rs b/src/server.rs index 746cc80..714d2d6 100644 --- a/src/server.rs +++ b/src/server.rs @@ -798,11 +798,14 @@ async fn udp_tx_loop( } } None => { - // Unlimited: yield every 64 packets. On ENOBUFS-prone systems - // (IPv6, macOS), sleep briefly to let the kernel drain buffers. - if seq % 64 == 0 { + // "Unlimited" mode: still need minimal pacing to prevent + // macOS interface queue overflow (ENOBUFS). + // Yield every 16 packets; if errors seen, add real delay. + if seq % 16 == 0 { if consecutive_errors > 0 { - tokio::time::sleep(Duration::from_micros(500)).await; + // Back off enough for the NIC to drain + tokio::time::sleep(Duration::from_micros(50)).await; + consecutive_errors = 0; // reset after yielding } else { tokio::task::yield_now().await; }