Fix IPv6 UDP TX: adaptive backoff on ENOBUFS
All checks were successful
CI / test (push) Successful in 1m28s
Build & Release / release (push) Successful in 3m10s

IPv6 UDP sends hit ENOBUFS much faster than IPv4 (smaller kernel
buffers, NDP overhead). Fixed:
- Adaptive backoff: 200us→10ms as errors accumulate, resets on success
- Higher error threshold: 50k instead of 1k before stopping
- Yield with sleep when errors have been seen recently

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Siavash Sameni
2026-03-31 18:45:04 +04:00
parent ba0a8f1b7c
commit 7be6a0d541

View File

@@ -736,13 +736,17 @@ async fn udp_tx_loop(
Err(e) => { Err(e) => {
consecutive_errors += 1; consecutive_errors += 1;
if consecutive_errors == 1 { if consecutive_errors == 1 {
tracing::warn!("UDP TX send error: {} (target={})", e, target); tracing::debug!("UDP TX send error: {} (target={})", e, target);
} }
if consecutive_errors > 1000 { if consecutive_errors > 50000 {
tracing::warn!("UDP TX: too many consecutive send errors, stopping"); tracing::warn!("UDP TX: too many consecutive send errors, stopping");
break; break;
} }
tokio::time::sleep(Duration::from_micros(200)).await; // Adaptive backoff: sleep longer as errors accumulate
let backoff = Duration::from_micros(
(200 + consecutive_errors.min(5000) as u64 * 10).min(10000)
);
tokio::time::sleep(backoff).await;
continue; continue;
} }
} }
@@ -766,14 +770,19 @@ async fn udp_tx_loop(
} }
} }
None => { None => {
// Unlimited: yield every 64 packets to keep system responsive // Unlimited: yield every 64 packets. On ENOBUFS-prone systems
// (IPv6, macOS), sleep briefly to let the kernel drain buffers.
if seq % 64 == 0 { if seq % 64 == 0 {
if consecutive_errors > 0 {
tokio::time::sleep(Duration::from_micros(500)).await;
} else {
tokio::task::yield_now().await; tokio::task::yield_now().await;
} }
} }
} }
} }
} }
}
async fn udp_rx_loop(socket: &UdpSocket, state: Arc<BandwidthState>) { async fn udp_rx_loop(socket: &UdpSocket, state: Arc<BandwidthState>) {
let mut buf = vec![0u8; 65536]; let mut buf = vec![0u8; 65536];