diff --git a/src/node/handlers/rx_loop.rs b/src/node/handlers/rx_loop.rs index 3399b77..e45684e 100644 --- a/src/node/handlers/rx_loop.rs +++ b/src/node/handlers/rx_loop.rs @@ -82,14 +82,42 @@ impl Node { loop { tokio::select! { + biased; packet = packet_rx.recv() => { match packet { Some(p) => self.process_packet(p).await, None => break, // channel closed } + // Drain remaining ready inbound packets in a tight loop + // before yielding back to select! — every yield is a + // futex hop on tokio's multi-thread scheduler, and at + // line rate the kernel UDP queue typically has several + // datagrams available per wake. Caps at a batch + // boundary so other branches (tick, control) eventually + // get a turn even under sustained load. + let mut drained = 0; + while drained < 256 { + match packet_rx.try_recv() { + Ok(p) => { + self.process_packet(p).await; + drained += 1; + } + Err(_) => break, + } + } } Some(ipv6_packet) = tun_outbound_rx.recv() => { self.handle_tun_outbound(ipv6_packet).await; + let mut drained = 0; + while drained < 256 { + match tun_outbound_rx.try_recv() { + Ok(p) => { + self.handle_tun_outbound(p).await; + drained += 1; + } + Err(_) => break, + } + } } Some(identity) = dns_identity_rx.recv() => { debug!(