wgengine/magicsock: drop DERP queue from head rather than tail

If the DERP queue is full, drop the oldest item first, rather than the
youngest, on the assumption that older data is more likely to be
unanswerable.

Updates tailscale/corp#31762

Signed-off-by: James Tucker <james@tailscale.com>
This commit is contained in:
James Tucker
2025-08-28 21:29:11 -07:00
committed by James Tucker
parent 89fe2e1f12
commit 3b68d607be
2 changed files with 23 additions and 13 deletions
+21 -11
View File
@@ -1642,18 +1642,27 @@ func (c *Conn) sendAddr(addr netip.AddrPort, pubKey key.NodePublic, b []byte, is
// internal locks.
pkt := bytes.Clone(b)
select {
case <-c.donec:
metricSendDERPErrorClosed.Add(1)
return false, errConnClosed
case ch <- derpWriteRequest{addr, pubKey, pkt, isDisco}:
metricSendDERPQueued.Add(1)
return true, nil
default:
metricSendDERPErrorQueue.Add(1)
// Too many writes queued. Drop packet.
return false, errDropDerpPacket
wr := derpWriteRequest{addr, pubKey, pkt, isDisco}
for range 3 {
select {
case <-c.donec:
metricSendDERPErrorClosed.Add(1)
return false, errConnClosed
case ch <- wr:
metricSendDERPQueued.Add(1)
return true, nil
default:
select {
case <-ch:
metricSendDERPDropped.Add(1)
default:
}
}
}
// gave up after 3 write attempts
metricSendDERPErrorQueue.Add(1)
// Too many writes queued. Drop packet.
return false, errDropDerpPacket
}
type receiveBatch struct {
@@ -3937,6 +3946,7 @@ var (
metricSendDERPErrorChan = clientmetric.NewCounter("magicsock_send_derp_error_chan")
metricSendDERPErrorClosed = clientmetric.NewCounter("magicsock_send_derp_error_closed")
metricSendDERPErrorQueue = clientmetric.NewCounter("magicsock_send_derp_error_queue")
metricSendDERPDropped = clientmetric.NewCounter("magicsock_send_derp_dropped")
metricSendUDP = clientmetric.NewAggregateCounter("magicsock_send_udp")
metricSendUDPError = clientmetric.NewCounter("magicsock_send_udp_error")
metricSendPeerRelay = clientmetric.NewAggregateCounter("magicsock_send_peer_relay")