ackhandler: account for skipped packets in packet threshold calculation (#5316)

This commit is contained in:
Marten Seemann
2025-08-29 11:39:41 +08:00
committed by GitHub
parent 9cd98f48bf
commit 0bef51ec76
3 changed files with 48 additions and 1 deletions

View File

@@ -710,7 +710,7 @@ func (h *sentPacketHandler) detectLostPackets(now time.Time, encLevel protocol.E
h.tracer.LostPacket(p.EncryptionLevel, pn, logging.PacketLossTimeThreshold)
}
}
} else if pnSpace.largestAcked >= pn+packetThreshold {
} else if pnSpace.history.Difference(pnSpace.largestAcked, pn) >= packetThreshold {
packetLost = true
if !p.isPathProbePacket {
if h.logger.Debug() {

View File

@@ -254,3 +254,24 @@ func (h *sentPacketHistory) DeclareLost(pn protocol.PacketNumber) {
h.cleanupStart()
}
}
// Difference returns the difference between two packet numbers a and b (a - b),
// taking into account any skipped packet numbers between them.
//
// Note that old skipped packets are garbage collected at some point,
// so this function is not guaranteed to return the correct result after a while.
func (h *sentPacketHistory) Difference(a, b protocol.PacketNumber) protocol.PacketNumber {
diff := a - b
if len(h.skippedPackets) == 0 {
return diff
}
if a < h.skippedPackets[0] || b > h.skippedPackets[len(h.skippedPackets)-1] {
return diff
}
for _, p := range h.skippedPackets {
if p > b && p < a {
diff--
}
}
return diff
}

View File

@@ -296,3 +296,29 @@ func TestSentPacketHistoryPathProbes(t *testing.T) {
require.Equal(t, protocol.InvalidPacketNumber, pn)
require.Nil(t, p)
}
func TestSentPacketHistoryDifference(t *testing.T) {
hist := newSentPacketHistory(true)
hist.SentNonAckElicitingPacket(0)
hist.SentAckElicitingPacket(1, &packet{})
hist.SentAckElicitingPacket(2, &packet{})
hist.SentAckElicitingPacket(3, &packet{})
hist.SkippedPacket(4)
hist.SkippedPacket(5)
hist.SentAckElicitingPacket(6, &packet{})
hist.SentNonAckElicitingPacket(7)
hist.SkippedPacket(8)
hist.SentAckElicitingPacket(9, &packet{})
require.Zero(t, hist.Difference(1, 1))
require.Zero(t, hist.Difference(2, 2))
require.Zero(t, hist.Difference(7, 7))
require.Equal(t, protocol.PacketNumber(1), hist.Difference(2, 1))
require.Equal(t, protocol.PacketNumber(2), hist.Difference(3, 1))
require.Equal(t, protocol.PacketNumber(3), hist.Difference(4, 1))
require.Equal(t, protocol.PacketNumber(3), hist.Difference(6, 1)) // 4 and 5 were skipped
require.Equal(t, protocol.PacketNumber(4), hist.Difference(7, 1)) // 4 and 5 were skipped
require.Equal(t, protocol.PacketNumber(3), hist.Difference(7, 2)) // 4 and 5 were skipped
require.Equal(t, protocol.PacketNumber(5), hist.Difference(9, 1)) // 4, 5 and 8 were skipped
}