From 537737935c6f1c8ff8a9165b54053b9b3d1a9319 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Wed, 8 May 2019 14:34:56 +0900 Subject: [PATCH] limit the ACK delay by max_ack_delay --- internal/ackhandler/interfaces.go | 1 + internal/ackhandler/sent_packet_handler.go | 7 ++++++- .../ackhandler/sent_packet_handler_test.go | 21 +++++++++++++++---- .../mocks/ackhandler/sent_packet_handler.go | 12 +++++++++++ session.go | 1 + 5 files changed, 37 insertions(+), 5 deletions(-) diff --git a/internal/ackhandler/interfaces.go b/internal/ackhandler/interfaces.go index 362b9fbe..d3550feb 100644 --- a/internal/ackhandler/interfaces.go +++ b/internal/ackhandler/interfaces.go @@ -13,6 +13,7 @@ type SentPacketHandler interface { SentPacket(packet *Packet) SentPacketsAsRetransmission(packets []*Packet, retransmissionOf protocol.PacketNumber) ReceivedAck(ackFrame *wire.AckFrame, withPacketNumber protocol.PacketNumber, encLevel protocol.EncryptionLevel, recvTime time.Time) error + SetMaxAckDelay(time.Duration) SetHandshakeComplete() ResetForRetry() error diff --git a/internal/ackhandler/sent_packet_handler.go b/internal/ackhandler/sent_packet_handler.go index 9a05ef76..d3d27b9b 100644 --- a/internal/ackhandler/sent_packet_handler.go +++ b/internal/ackhandler/sent_packet_handler.go @@ -58,6 +58,7 @@ type sentPacketHandler struct { rttStats *congestion.RTTStats handshakeComplete bool + maxAckDelay time.Duration // The number of times the crypto packets have been retransmitted without receiving an ack. cryptoCount uint32 @@ -122,6 +123,10 @@ func (h *sentPacketHandler) SetHandshakeComplete() { h.handshakeComplete = true } +func (h *sentPacketHandler) SetMaxAckDelay(mad time.Duration) { + h.maxAckDelay = mad +} + func (h *sentPacketHandler) SentPacket(packet *Packet) { if isAckEliciting := h.sentPacketImpl(packet); isAckEliciting { h.getPacketNumberSpace(packet.EncryptionLevel).history.SentPacket(packet) @@ -208,7 +213,7 @@ func (h *sentPacketHandler) ReceivedAck(ackFrame *wire.AckFrame, withPacketNumbe // don't use the ack delay for Initial and Handshake packets var ackDelay time.Duration if encLevel == protocol.Encryption1RTT { - ackDelay = ackFrame.DelayTime + ackDelay = utils.MinDuration(ackFrame.DelayTime, h.maxAckDelay) } h.rttStats.UpdateRTT(rcvTime.Sub(p.SendTime), ackDelay, rcvTime) if h.logger.Debug() { diff --git a/internal/ackhandler/sent_packet_handler_test.go b/internal/ackhandler/sent_packet_handler_test.go index 18685622..3a923356 100644 --- a/internal/ackhandler/sent_packet_handler_test.go +++ b/internal/ackhandler/sent_packet_handler_test.go @@ -294,10 +294,10 @@ var _ = Describe("SentPacketHandler", func() { It("ignores the DelayTime for Initial and Handshake packets", func() { handler.SentPacket(cryptoPacket(&Packet{PacketNumber: 1})) - now := time.Now() + handler.SetMaxAckDelay(time.Hour) // make sure the rttStats have a min RTT, so that the delay is used handler.rttStats.UpdateRTT(5*time.Minute, 0, time.Now()) - getPacket(1, protocol.EncryptionInitial).SendTime = now.Add(-10 * time.Minute) + getPacket(1, protocol.EncryptionInitial).SendTime = time.Now().Add(-10 * time.Minute) ack := &wire.AckFrame{ AckRanges: []wire.AckRange{{Smallest: 1, Largest: 1}}, DelayTime: 5 * time.Minute, @@ -307,10 +307,10 @@ var _ = Describe("SentPacketHandler", func() { }) It("uses the DelayTime in the ACK frame", func() { - now := time.Now() + handler.SetMaxAckDelay(time.Hour) // make sure the rttStats have a min RTT, so that the delay is used handler.rttStats.UpdateRTT(5*time.Minute, 0, time.Now()) - getPacket(1, protocol.Encryption1RTT).SendTime = now.Add(-10 * time.Minute) + getPacket(1, protocol.Encryption1RTT).SendTime = time.Now().Add(-10 * time.Minute) ack := &wire.AckFrame{ AckRanges: []wire.AckRange{{Smallest: 1, Largest: 1}}, DelayTime: 5 * time.Minute, @@ -318,6 +318,19 @@ var _ = Describe("SentPacketHandler", func() { Expect(handler.ReceivedAck(ack, 1, protocol.Encryption1RTT, time.Now())).To(Succeed()) Expect(handler.rttStats.LatestRTT()).To(BeNumerically("~", 5*time.Minute, 1*time.Second)) }) + + It("limits the DelayTime in the ACK frame to max_ack_delay", func() { + handler.SetMaxAckDelay(time.Minute) + // make sure the rttStats have a min RTT, so that the delay is used + handler.rttStats.UpdateRTT(5*time.Minute, 0, time.Now()) + getPacket(1, protocol.Encryption1RTT).SendTime = time.Now().Add(-10 * time.Minute) + ack := &wire.AckFrame{ + AckRanges: []wire.AckRange{{Smallest: 1, Largest: 1}}, + DelayTime: 5 * time.Minute, + } + Expect(handler.ReceivedAck(ack, 1, protocol.Encryption1RTT, time.Now())).To(Succeed()) + Expect(handler.rttStats.LatestRTT()).To(BeNumerically("~", 9*time.Minute, 1*time.Second)) + }) }) Context("determining which ACKs we have received an ACK for", func() { diff --git a/internal/mocks/ackhandler/sent_packet_handler.go b/internal/mocks/ackhandler/sent_packet_handler.go index fc289f5e..a712c816 100644 --- a/internal/mocks/ackhandler/sent_packet_handler.go +++ b/internal/mocks/ackhandler/sent_packet_handler.go @@ -215,6 +215,18 @@ func (mr *MockSentPacketHandlerMockRecorder) SetHandshakeComplete() *gomock.Call return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetHandshakeComplete", reflect.TypeOf((*MockSentPacketHandler)(nil).SetHandshakeComplete)) } +// SetMaxAckDelay mocks base method +func (m *MockSentPacketHandler) SetMaxAckDelay(arg0 time.Duration) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetMaxAckDelay", arg0) +} + +// SetMaxAckDelay indicates an expected call of SetMaxAckDelay +func (mr *MockSentPacketHandlerMockRecorder) SetMaxAckDelay(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetMaxAckDelay", reflect.TypeOf((*MockSentPacketHandler)(nil).SetMaxAckDelay), arg0) +} + // ShouldSendNumPackets mocks base method func (m *MockSentPacketHandler) ShouldSendNumPackets() int { m.ctrl.T.Helper() diff --git a/session.go b/session.go index 0c1ec73d..68894243 100644 --- a/session.go +++ b/session.go @@ -939,6 +939,7 @@ func (s *session) processTransportParameters(data []byte) { s.packer.HandleTransportParameters(params) s.frameParser.SetAckDelayExponent(params.AckDelayExponent) s.connFlowController.UpdateSendWindow(params.InitialMaxData) + s.sentPacketHandler.SetMaxAckDelay(params.MaxAckDelay) if params.StatelessResetToken != nil { s.sessionRunner.AddResetToken(*params.StatelessResetToken, s) }