ackhandler: track lost packets and detect spurious losses (#5355)

* ackhandler: implement a lost packet tracker

* logging: add ConnectionTracer.DetectedSpuriousLoss event

* ackhandler: detect spurious losses

* qlog: add support for logging spurious packet loss

* ackhandler: delete lost packets after detecting spurios loss

* guard against slice index underflow
This commit is contained in:
Marten Seemann
2025-10-03 15:59:50 +08:00
committed by GitHub
parent 0f5d99db94
commit 7c1ce0efe2
12 changed files with 379 additions and 0 deletions

View File

@@ -68,6 +68,9 @@ func NewMockConnectionTracer(ctrl *gomock.Controller) (*logging.ConnectionTracer
LostPacket: func(encLevel logging.EncryptionLevel, pn logging.PacketNumber, reason logging.PacketLossReason) {
t.LostPacket(encLevel, pn, reason)
},
DetectedSpuriousLoss: func(encLevel logging.EncryptionLevel, pn logging.PacketNumber, reordering uint64, dur time.Duration) {
t.DetectedSpuriousLoss(encLevel, pn, reordering, dur)
},
UpdatedMTU: func(mtu logging.ByteCount, done bool) {
t.UpdatedMTU(mtu, done)
},

View File

@@ -258,6 +258,42 @@ func (c *MockConnectionTracerDebugCall) DoAndReturn(f func(string, string)) *Moc
return c
}
// DetectedSpuriousLoss mocks base method.
func (m *MockConnectionTracer) DetectedSpuriousLoss(arg0 logging.EncryptionLevel, arg1 logging.PacketNumber, arg2 uint64, arg3 time.Duration) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "DetectedSpuriousLoss", arg0, arg1, arg2, arg3)
}
// DetectedSpuriousLoss indicates an expected call of DetectedSpuriousLoss.
func (mr *MockConnectionTracerMockRecorder) DetectedSpuriousLoss(arg0, arg1, arg2, arg3 any) *MockConnectionTracerDetectedSpuriousLossCall {
mr.mock.ctrl.T.Helper()
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DetectedSpuriousLoss", reflect.TypeOf((*MockConnectionTracer)(nil).DetectedSpuriousLoss), arg0, arg1, arg2, arg3)
return &MockConnectionTracerDetectedSpuriousLossCall{Call: call}
}
// MockConnectionTracerDetectedSpuriousLossCall wrap *gomock.Call
type MockConnectionTracerDetectedSpuriousLossCall struct {
*gomock.Call
}
// Return rewrite *gomock.Call.Return
func (c *MockConnectionTracerDetectedSpuriousLossCall) Return() *MockConnectionTracerDetectedSpuriousLossCall {
c.Call = c.Call.Return()
return c
}
// Do rewrite *gomock.Call.Do
func (c *MockConnectionTracerDetectedSpuriousLossCall) Do(f func(logging.EncryptionLevel, logging.PacketNumber, uint64, time.Duration)) *MockConnectionTracerDetectedSpuriousLossCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
func (c *MockConnectionTracerDetectedSpuriousLossCall) DoAndReturn(f func(logging.EncryptionLevel, logging.PacketNumber, uint64, time.Duration)) *MockConnectionTracerDetectedSpuriousLossCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
// DroppedEncryptionLevel mocks base method.
func (m *MockConnectionTracer) DroppedEncryptionLevel(arg0 logging.EncryptionLevel) {
m.ctrl.T.Helper()

View File

@@ -38,6 +38,7 @@ type ConnectionTracer interface {
UpdatedMetrics(rttStats *logging.RTTStats, cwnd, bytesInFlight logging.ByteCount, packetsInFlight int)
AcknowledgedPacket(logging.EncryptionLevel, logging.PacketNumber)
LostPacket(logging.EncryptionLevel, logging.PacketNumber, logging.PacketLossReason)
DetectedSpuriousLoss(logging.EncryptionLevel, logging.PacketNumber, uint64, time.Duration)
UpdatedCongestionState(logging.CongestionState)
UpdatedPTOCount(value uint32)
UpdatedKeyFromTLS(logging.EncryptionLevel, logging.Perspective)