forked from quic-go/quic-go
Merge pull request #1692 from lucas-clemente/unify-tlp-and-rto
unify TLP and RTO
This commit is contained in:
@@ -12,10 +12,8 @@ const (
|
||||
SendAck
|
||||
// SendRetransmission means that retransmissions should be sent
|
||||
SendRetransmission
|
||||
// SendRTO means that an RTO probe packet should be sent
|
||||
SendRTO
|
||||
// SendTLP means that a TLP probe packet should be sent
|
||||
SendTLP
|
||||
// SendPTO means that a probe packet should be sent
|
||||
SendPTO
|
||||
// SendAny means that any packet should be sent
|
||||
SendAny
|
||||
)
|
||||
@@ -28,10 +26,8 @@ func (s SendMode) String() string {
|
||||
return "ack"
|
||||
case SendRetransmission:
|
||||
return "retransmission"
|
||||
case SendRTO:
|
||||
return "rto"
|
||||
case SendTLP:
|
||||
return "tlp"
|
||||
case SendPTO:
|
||||
return "pto"
|
||||
case SendAny:
|
||||
return "any"
|
||||
default:
|
||||
|
||||
@@ -10,8 +10,7 @@ var _ = Describe("Send Mode", func() {
|
||||
Expect(SendNone.String()).To(Equal("none"))
|
||||
Expect(SendAny.String()).To(Equal("any"))
|
||||
Expect(SendAck.String()).To(Equal("ack"))
|
||||
Expect(SendRTO.String()).To(Equal("rto"))
|
||||
Expect(SendTLP.String()).To(Equal("tlp"))
|
||||
Expect(SendPTO.String()).To(Equal("pto"))
|
||||
Expect(SendRetransmission.String()).To(Equal("retransmission"))
|
||||
Expect(SendMode(123).String()).To(Equal("invalid send mode: 123"))
|
||||
})
|
||||
|
||||
@@ -17,16 +17,8 @@ const (
|
||||
// Maximum reordering in time space before time based loss detection considers a packet lost.
|
||||
// In fraction of an RTT.
|
||||
timeReorderingFraction = 1.0 / 8
|
||||
// defaultRTOTimeout is the RTO time on new connections
|
||||
defaultRTOTimeout = 500 * time.Millisecond
|
||||
// Minimum time in the future a tail loss probe alarm may be set for.
|
||||
minTPLTimeout = 10 * time.Millisecond
|
||||
// Maximum number of tail loss probes before an RTO fires.
|
||||
maxTLPs = 2
|
||||
// Minimum time in the future an RTO alarm may be set for.
|
||||
minRTOTimeout = 200 * time.Millisecond
|
||||
// maxRTOTimeout is the maximum RTO time
|
||||
maxRTOTimeout = 60 * time.Second
|
||||
// Timer granularity. The timer will not be set to a value smaller than granularity.
|
||||
granularity = time.Millisecond
|
||||
)
|
||||
|
||||
type sentPacketHandler struct {
|
||||
@@ -44,7 +36,6 @@ type sentPacketHandler struct {
|
||||
// example: we send an ACK for packets 90-100 with packet number 20
|
||||
// once we receive an ACK from the peer for packet 20, the lowestPacketNotConfirmedAcked is 101
|
||||
lowestPacketNotConfirmedAcked protocol.PacketNumber
|
||||
largestSentBeforeRTO protocol.PacketNumber
|
||||
|
||||
packetHistory *sentPacketHistory
|
||||
|
||||
@@ -56,17 +47,13 @@ type sentPacketHandler struct {
|
||||
rttStats *congestion.RTTStats
|
||||
|
||||
handshakeComplete bool
|
||||
|
||||
// The number of times the crypto packets have been retransmitted without receiving an ack.
|
||||
cryptoCount uint32
|
||||
|
||||
// The number of times a TLP has been sent without receiving an ack.
|
||||
tlpCount uint32
|
||||
allowTLP bool
|
||||
|
||||
// The number of times an RTO has been sent without receiving an ack.
|
||||
rtoCount uint32
|
||||
// The number of RTO probe packets that should be sent.
|
||||
numRTOs int
|
||||
// The number of times a PTO has been sent without receiving an ack.
|
||||
ptoCount uint32
|
||||
// The number of PTO probe packets that should be sent.
|
||||
numProbesToSend int
|
||||
|
||||
// The time at which the next packet will be considered lost based on early transmit or exceeding the reordering window in time.
|
||||
lossTime time.Time
|
||||
@@ -173,10 +160,9 @@ func (h *sentPacketHandler) sentPacketImpl(packet *Packet) bool /* isRetransmitt
|
||||
packet.includedInBytesInFlight = true
|
||||
h.bytesInFlight += packet.Length
|
||||
packet.canBeRetransmitted = true
|
||||
if h.numRTOs > 0 {
|
||||
h.numRTOs--
|
||||
if h.numProbesToSend > 0 {
|
||||
h.numProbesToSend--
|
||||
}
|
||||
h.allowTLP = false
|
||||
}
|
||||
h.congestion.OnPacketSent(packet.SendTime, h.bytesInFlight, packet.PacketNumber, packet.Length, isRetransmittable)
|
||||
|
||||
@@ -210,6 +196,9 @@ func (h *sentPacketHandler) ReceivedAck(ackFrame *wire.AckFrame, withPacketNumbe
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(ackedPackets) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
priorInFlight := h.bytesInFlight
|
||||
for _, p := range ackedPackets {
|
||||
@@ -235,6 +224,10 @@ func (h *sentPacketHandler) ReceivedAck(ackFrame *wire.AckFrame, withPacketNumbe
|
||||
if err := h.detectLostPackets(rcvTime, priorInFlight); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
h.ptoCount = 0
|
||||
h.cryptoCount = 0
|
||||
|
||||
h.updateLossDetectionAlarm()
|
||||
return nil
|
||||
}
|
||||
@@ -310,15 +303,8 @@ func (h *sentPacketHandler) updateLossDetectionAlarm() {
|
||||
} else if !h.lossTime.IsZero() {
|
||||
// Early retransmit timer or time loss detection.
|
||||
h.alarm = h.lossTime
|
||||
} else {
|
||||
// RTO or TLP alarm
|
||||
alarmDuration := h.computeRTOTimeout()
|
||||
if h.tlpCount < maxTLPs {
|
||||
tlpAlarm := h.computeTLPTimeout()
|
||||
// if the RTO duration is shorter than the TLP duration, use the RTO duration
|
||||
alarmDuration = utils.MinDuration(alarmDuration, tlpAlarm)
|
||||
}
|
||||
h.alarm = h.lastSentRetransmittablePacketTime.Add(alarmDuration)
|
||||
} else { // PTO alarm
|
||||
h.alarm = h.lastSentRetransmittablePacketTime.Add(h.computePTOTimeout())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,6 +332,7 @@ func (h *sentPacketHandler) detectLostPackets(now time.Time, priorInFlight proto
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
||||
if h.logger.Debug() && len(lostPackets) > 0 {
|
||||
pns := make([]protocol.PacketNumber, len(lostPackets))
|
||||
for i, p := range lostPackets {
|
||||
@@ -399,21 +386,12 @@ func (h *sentPacketHandler) onVerifiedAlarm() error {
|
||||
}
|
||||
// Early retransmit or time loss detection
|
||||
err = h.detectLostPackets(time.Now(), h.bytesInFlight)
|
||||
} else if h.tlpCount < maxTLPs { // TLP
|
||||
} else { // PTO
|
||||
if h.logger.Debug() {
|
||||
h.logger.Debugf("Loss detection alarm fired in TLP mode. TLP count: %d", h.tlpCount)
|
||||
h.logger.Debugf("Loss detection alarm fired in PTO mode. PTO count: %d", h.ptoCount)
|
||||
}
|
||||
h.allowTLP = true
|
||||
h.tlpCount++
|
||||
} else { // RTO
|
||||
if h.logger.Debug() {
|
||||
h.logger.Debugf("Loss detection alarm fired in RTO mode. RTO count: %d", h.rtoCount)
|
||||
}
|
||||
if h.rtoCount == 0 {
|
||||
h.largestSentBeforeRTO = h.lastSentPacketNumber
|
||||
}
|
||||
h.rtoCount++
|
||||
h.numRTOs += 2
|
||||
h.ptoCount++
|
||||
h.numProbesToSend += 2
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -454,15 +432,9 @@ func (h *sentPacketHandler) onPacketAcked(p *Packet, rcvTime time.Time) error {
|
||||
if p.includedInBytesInFlight {
|
||||
h.bytesInFlight -= p.Length
|
||||
}
|
||||
if h.rtoCount > 0 {
|
||||
h.verifyRTO(p.PacketNumber)
|
||||
}
|
||||
if err := h.stopRetransmissionsFor(p); err != nil {
|
||||
return err
|
||||
}
|
||||
h.rtoCount = 0
|
||||
h.tlpCount = 0
|
||||
h.cryptoCount = 0
|
||||
return h.packetHistory.Remove(p.PacketNumber)
|
||||
}
|
||||
|
||||
@@ -480,18 +452,6 @@ func (h *sentPacketHandler) stopRetransmissionsFor(p *Packet) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) verifyRTO(pn protocol.PacketNumber) {
|
||||
if pn <= h.largestSentBeforeRTO {
|
||||
h.logger.Debugf("Spurious RTO detected. Received an ACK for %#x (largest sent before RTO: %#x)", pn, h.largestSentBeforeRTO)
|
||||
// Replace SRTT with latest_rtt and increase the variance to prevent
|
||||
// a spurious RTO from happening again.
|
||||
h.rttStats.ExpireSmoothedMetrics()
|
||||
return
|
||||
}
|
||||
h.logger.Debugf("RTO verified. Received an ACK for %#x (largest sent before RTO: %#x", pn, h.largestSentBeforeRTO)
|
||||
h.congestion.OnRetransmissionTimeout(true)
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) DequeuePacketForRetransmission() *Packet {
|
||||
if len(h.retransmissionQueue) == 0 {
|
||||
return nil
|
||||
@@ -539,11 +499,8 @@ func (h *sentPacketHandler) SendMode() SendMode {
|
||||
}
|
||||
return SendNone
|
||||
}
|
||||
if h.allowTLP {
|
||||
return SendTLP
|
||||
}
|
||||
if h.numRTOs > 0 {
|
||||
return SendRTO
|
||||
if h.numProbesToSend > 0 {
|
||||
return SendPTO
|
||||
}
|
||||
// Only send ACKs if we're congestion limited.
|
||||
if cwnd := h.congestion.GetCongestionWindow(); h.bytesInFlight > cwnd {
|
||||
@@ -570,9 +527,9 @@ func (h *sentPacketHandler) TimeUntilSend() time.Time {
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) ShouldSendNumPackets() int {
|
||||
if h.numRTOs > 0 {
|
||||
if h.numProbesToSend > 0 {
|
||||
// RTO probes should not be paced, but must be sent immediately.
|
||||
return h.numRTOs
|
||||
return h.numProbesToSend
|
||||
}
|
||||
delay := h.congestion.TimeUntilSend(h.bytesInFlight)
|
||||
if delay == 0 || delay > protocol.MinPacingDelay {
|
||||
@@ -610,27 +567,14 @@ func (h *sentPacketHandler) queuePacketForRetransmission(p *Packet) error {
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) computeCryptoTimeout() time.Duration {
|
||||
duration := utils.MaxDuration(2*h.rttStats.SmoothedOrInitialRTT(), minTPLTimeout)
|
||||
duration := utils.MaxDuration(2*h.rttStats.SmoothedOrInitialRTT(), granularity)
|
||||
// exponential backoff
|
||||
// There's an implicit limit to this set by the crypto timeout.
|
||||
return duration << h.cryptoCount
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) computeTLPTimeout() time.Duration {
|
||||
func (h *sentPacketHandler) computePTOTimeout() time.Duration {
|
||||
// TODO(#1236): include the max_ack_delay
|
||||
return utils.MaxDuration(h.rttStats.SmoothedOrInitialRTT()*3/2, minTPLTimeout)
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) computeRTOTimeout() time.Duration {
|
||||
var rto time.Duration
|
||||
rtt := h.rttStats.SmoothedRTT()
|
||||
if rtt == 0 {
|
||||
rto = defaultRTOTimeout
|
||||
} else {
|
||||
rto = rtt + 4*h.rttStats.MeanDeviation()
|
||||
}
|
||||
rto = utils.MaxDuration(rto, minRTOTimeout)
|
||||
// Exponential backoff
|
||||
rto <<= h.rtoCount
|
||||
return utils.MinDuration(rto, maxRTOTimeout)
|
||||
duration := utils.MaxDuration(h.rttStats.SmoothedOrInitialRTT()+4*h.rttStats.MeanDeviation(), granularity)
|
||||
return duration << h.ptoCount
|
||||
}
|
||||
|
||||
@@ -468,67 +468,6 @@ var _ = Describe("SentPacketHandler", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("doesn't call OnPacketLost and OnRetransmissionTimeout when queuing RTOs", func() {
|
||||
for i := protocol.PacketNumber(1); i < 3; i++ {
|
||||
cong.EXPECT().OnPacketSent(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
|
||||
cong.EXPECT().TimeUntilSend(gomock.Any())
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: i}))
|
||||
}
|
||||
handler.OnAlarm() // TLP
|
||||
handler.OnAlarm() // TLP
|
||||
handler.OnAlarm() // RTO
|
||||
})
|
||||
|
||||
It("declares all lower packets lost and call OnRetransmissionTimeout when verifying an RTO", func() {
|
||||
cong.EXPECT().OnPacketSent(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(5)
|
||||
cong.EXPECT().TimeUntilSend(gomock.Any()).Times(5)
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 1, SendTime: time.Now().Add(-time.Hour)}))
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 2, SendTime: time.Now().Add(-time.Hour)}))
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 3, SendTime: time.Now().Add(-time.Hour)}))
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 4, SendTime: time.Now().Add(-time.Hour)}))
|
||||
handler.OnAlarm() // TLP
|
||||
handler.OnAlarm() // TLP
|
||||
handler.OnAlarm() // RTO
|
||||
// send one probe packet and receive an ACK for it
|
||||
rcvTime := time.Now()
|
||||
gomock.InOrder(
|
||||
cong.EXPECT().MaybeExitSlowStart(),
|
||||
cong.EXPECT().OnRetransmissionTimeout(true),
|
||||
cong.EXPECT().OnPacketAcked(protocol.PacketNumber(5), protocol.ByteCount(1), protocol.ByteCount(5), rcvTime),
|
||||
cong.EXPECT().OnPacketLost(protocol.PacketNumber(1), protocol.ByteCount(1), protocol.ByteCount(5)),
|
||||
cong.EXPECT().OnPacketLost(protocol.PacketNumber(2), protocol.ByteCount(1), protocol.ByteCount(5)),
|
||||
cong.EXPECT().OnPacketLost(protocol.PacketNumber(3), protocol.ByteCount(1), protocol.ByteCount(5)),
|
||||
cong.EXPECT().OnPacketLost(protocol.PacketNumber(4), protocol.ByteCount(1), protocol.ByteCount(5)),
|
||||
)
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 5}))
|
||||
ack := &wire.AckFrame{AckRanges: []wire.AckRange{{Smallest: 5, Largest: 5}}}
|
||||
err := handler.ReceivedAck(ack, 1, protocol.Encryption1RTT, rcvTime)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
It("doesn't call OnRetransmissionTimeout when a spurious RTO occurs", func() {
|
||||
cong.EXPECT().OnPacketSent(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(3)
|
||||
cong.EXPECT().TimeUntilSend(gomock.Any()).Times(3)
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 1, SendTime: time.Now().Add(-time.Hour)}))
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 2, SendTime: time.Now()}))
|
||||
handler.OnAlarm() // TLP
|
||||
handler.OnAlarm() // TLP
|
||||
handler.OnAlarm() // RTO
|
||||
|
||||
// send one probe packet
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 3}))
|
||||
// receive an ACK for a packet send *before* the probe packet
|
||||
// don't EXPECT any call to OnRetransmissionTimeout
|
||||
gomock.InOrder(
|
||||
cong.EXPECT().MaybeExitSlowStart(),
|
||||
cong.EXPECT().OnPacketAcked(protocol.PacketNumber(2), protocol.ByteCount(1), protocol.ByteCount(3), gomock.Any()),
|
||||
cong.EXPECT().OnPacketLost(protocol.PacketNumber(1), protocol.ByteCount(1), protocol.ByteCount(3)),
|
||||
)
|
||||
ack := &wire.AckFrame{AckRanges: []wire.AckRange{{Smallest: 2, Largest: 2}}}
|
||||
err := handler.ReceivedAck(ack, 1, protocol.Encryption1RTT, time.Now())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
It("doesn't call OnPacketAcked when a retransmitted packet is acked", func() {
|
||||
cong.EXPECT().OnPacketSent(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(2)
|
||||
cong.EXPECT().TimeUntilSend(gomock.Any()).Times(2)
|
||||
@@ -621,9 +560,9 @@ var _ = Describe("SentPacketHandler", func() {
|
||||
It("allows RTOs, even when congestion limited", func() {
|
||||
// note that we don't EXPECT a call to GetCongestionWindow
|
||||
// that means retransmissions are sent without considering the congestion window
|
||||
handler.numRTOs = 1
|
||||
handler.numProbesToSend = 1
|
||||
handler.retransmissionQueue = []*Packet{{PacketNumber: 3}}
|
||||
Expect(handler.SendMode()).To(Equal(SendRTO))
|
||||
Expect(handler.SendMode()).To(Equal(SendPTO))
|
||||
})
|
||||
|
||||
It("gets the pacing delay", func() {
|
||||
@@ -636,7 +575,7 @@ var _ = Describe("SentPacketHandler", func() {
|
||||
})
|
||||
|
||||
It("allows sending of all RTO probe packets", func() {
|
||||
handler.numRTOs = 5
|
||||
handler.numProbesToSend = 5
|
||||
Expect(handler.ShouldSendNumPackets()).To(Equal(5))
|
||||
})
|
||||
|
||||
@@ -672,81 +611,55 @@ var _ = Describe("SentPacketHandler", func() {
|
||||
Expect(handler.SendMode()).To(Equal(SendAny))
|
||||
})
|
||||
|
||||
Context("TLPs", func() {
|
||||
Context("probe packets", func() {
|
||||
It("uses the RTT from RTT stats", func() {
|
||||
rtt := 2 * time.Second
|
||||
updateRTT(rtt)
|
||||
Expect(handler.computeTLPTimeout()).To(Equal(rtt * 3 / 2))
|
||||
Expect(handler.rttStats.SmoothedOrInitialRTT()).To(Equal(2 * time.Second))
|
||||
Expect(handler.rttStats.MeanDeviation()).To(Equal(time.Second))
|
||||
Expect(handler.computePTOTimeout()).To(Equal(time.Duration(2+4) * time.Second))
|
||||
})
|
||||
|
||||
It("uses the minTLPTimeout for short RTTs", func() {
|
||||
rtt := 2 * time.Microsecond
|
||||
It("uses the granularity for short RTTs", func() {
|
||||
rtt := time.Microsecond
|
||||
updateRTT(rtt)
|
||||
Expect(handler.computeTLPTimeout()).To(Equal(minTPLTimeout))
|
||||
})
|
||||
|
||||
It("sets the TLP send mode until one retransmittable packet is sent", func() {
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 1, SendTime: time.Now().Add(-time.Hour)}))
|
||||
handler.OnAlarm()
|
||||
Expect(handler.SendMode()).To(Equal(SendTLP))
|
||||
// Send a non-retransmittable packet.
|
||||
// It doesn't count as a probe packet.
|
||||
handler.SentPacket(nonRetransmittablePacket(&Packet{PacketNumber: 2}))
|
||||
Expect(handler.SendMode()).To(Equal(SendTLP))
|
||||
// Send a retransmittable packet.
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 3}))
|
||||
Expect(handler.SendMode()).ToNot(Equal(SendTLP))
|
||||
})
|
||||
|
||||
It("sends two TLPs, then RTOs", func() {
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 1, SendTime: time.Now().Add(-time.Hour)}))
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 2, SendTime: time.Now().Add(-time.Hour)}))
|
||||
// first TLP
|
||||
handler.OnAlarm()
|
||||
Expect(handler.SendMode()).To(Equal(SendTLP))
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 3}))
|
||||
// second TLP
|
||||
handler.OnAlarm()
|
||||
Expect(handler.SendMode()).To(Equal(SendTLP))
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 4}))
|
||||
// fire alarm a third time
|
||||
handler.OnAlarm()
|
||||
Expect(handler.SendMode()).To(Equal(SendRTO))
|
||||
})
|
||||
})
|
||||
|
||||
Context("RTOs", func() {
|
||||
It("uses default RTO", func() {
|
||||
Expect(handler.computeRTOTimeout()).To(Equal(defaultRTOTimeout))
|
||||
})
|
||||
|
||||
It("uses RTO from rttStats", func() {
|
||||
rtt := time.Second
|
||||
handler.rttStats.UpdateRTT(rtt, 0, time.Now())
|
||||
Expect(handler.rttStats.SmoothedRTT()).To(Equal(rtt))
|
||||
Expect(handler.rttStats.MeanDeviation()).To(Equal(rtt / 2))
|
||||
expected := rtt + rtt/2*4
|
||||
Expect(handler.computeRTOTimeout()).To(Equal(expected))
|
||||
})
|
||||
|
||||
It("limits RTO min", func() {
|
||||
rtt := 3 * time.Millisecond
|
||||
updateRTT(rtt)
|
||||
Expect(handler.computeRTOTimeout()).To(Equal(minRTOTimeout))
|
||||
})
|
||||
|
||||
It("limits RTO max", func() {
|
||||
updateRTT(time.Hour)
|
||||
Expect(handler.computeRTOTimeout()).To(Equal(maxRTOTimeout))
|
||||
Expect(handler.computePTOTimeout()).To(Equal(granularity))
|
||||
})
|
||||
|
||||
It("implements exponential backoff", func() {
|
||||
handler.rtoCount = 0
|
||||
Expect(handler.computeRTOTimeout()).To(Equal(defaultRTOTimeout))
|
||||
handler.rtoCount = 1
|
||||
Expect(handler.computeRTOTimeout()).To(Equal(2 * defaultRTOTimeout))
|
||||
handler.rtoCount = 2
|
||||
Expect(handler.computeRTOTimeout()).To(Equal(4 * defaultRTOTimeout))
|
||||
handler.ptoCount = 0
|
||||
timeout := handler.computePTOTimeout()
|
||||
Expect(timeout).ToNot(BeZero())
|
||||
handler.ptoCount = 1
|
||||
Expect(handler.computePTOTimeout()).To(Equal(2 * timeout))
|
||||
handler.ptoCount = 2
|
||||
Expect(handler.computePTOTimeout()).To(Equal(4 * timeout))
|
||||
})
|
||||
|
||||
It("sets the TPO send mode until two packets is sent", func() {
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 1, SendTime: time.Now().Add(-time.Hour)}))
|
||||
handler.OnAlarm()
|
||||
Expect(handler.SendMode()).To(Equal(SendPTO))
|
||||
Expect(handler.ShouldSendNumPackets()).To(Equal(2))
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 2}))
|
||||
Expect(handler.SendMode()).To(Equal(SendPTO))
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 3}))
|
||||
Expect(handler.SendMode()).ToNot(Equal(SendPTO))
|
||||
})
|
||||
|
||||
It("only counts retransmittable packets as probe packets", func() {
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 1, SendTime: time.Now().Add(-time.Hour)}))
|
||||
handler.OnAlarm()
|
||||
Expect(handler.SendMode()).To(Equal(SendPTO))
|
||||
Expect(handler.ShouldSendNumPackets()).To(Equal(2))
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 2}))
|
||||
Expect(handler.SendMode()).To(Equal(SendPTO))
|
||||
for p := protocol.PacketNumber(3); p < 30; p++ {
|
||||
handler.SentPacket(nonRetransmittablePacket(&Packet{PacketNumber: p}))
|
||||
Expect(handler.SendMode()).To(Equal(SendPTO))
|
||||
}
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 30}))
|
||||
Expect(handler.SendMode()).ToNot(Equal(SendPTO))
|
||||
})
|
||||
|
||||
It("gets two probe packets if RTO expires", func() {
|
||||
@@ -755,7 +668,6 @@ var _ = Describe("SentPacketHandler", func() {
|
||||
|
||||
updateRTT(time.Hour)
|
||||
Expect(handler.lossTime.IsZero()).To(BeTrue())
|
||||
Expect(time.Until(handler.GetAlarmTimeout())).To(BeNumerically("~", handler.computeRTOTimeout(), time.Minute))
|
||||
|
||||
handler.OnAlarm() // TLP
|
||||
handler.OnAlarm() // TLP
|
||||
@@ -770,7 +682,7 @@ var _ = Describe("SentPacketHandler", func() {
|
||||
Expect(p.PacketNumber).To(Equal(protocol.PacketNumber(2)))
|
||||
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(2)))
|
||||
|
||||
Expect(handler.rtoCount).To(BeEquivalentTo(1))
|
||||
Expect(handler.ptoCount).To(BeEquivalentTo(3))
|
||||
})
|
||||
|
||||
It("doesn't delete packets transmitted as RTO from the history", func() {
|
||||
@@ -797,20 +709,6 @@ var _ = Describe("SentPacketHandler", func() {
|
||||
Expect(handler.retransmissionQueue).To(BeEmpty()) // 1 and 2 were already sent as probe packets
|
||||
})
|
||||
|
||||
It("allows sending of two probe packets", func() {
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 1, SendTime: time.Now().Add(-time.Hour)}))
|
||||
handler.OnAlarm() // TLP
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 2})) // send the first TLP
|
||||
handler.OnAlarm() // TLP
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 3})) // send the second TLP
|
||||
handler.OnAlarm() // RTO
|
||||
Expect(handler.SendMode()).To(Equal(SendRTO))
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 4}))
|
||||
Expect(handler.SendMode()).To(Equal(SendRTO))
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 5}))
|
||||
Expect(handler.SendMode()).ToNot(Equal(SendRTO))
|
||||
})
|
||||
|
||||
It("gets packets sent before the probe packet for retransmission", func() {
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 1, SendTime: time.Now().Add(-time.Hour)}))
|
||||
handler.SentPacket(retransmittablePacket(&Packet{PacketNumber: 2, SendTime: time.Now().Add(-time.Hour)}))
|
||||
|
||||
@@ -830,7 +830,7 @@ sendLoop:
|
||||
// There will only be a new ACK after receiving new packets.
|
||||
// SendAck is only returned when we're congestion limited, so we don't need to set the pacingt timer.
|
||||
return s.maybeSendAckOnlyPacket()
|
||||
case ackhandler.SendTLP, ackhandler.SendRTO:
|
||||
case ackhandler.SendPTO:
|
||||
if err := s.sendProbePacket(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -706,7 +706,7 @@ var _ = Describe("Session", func() {
|
||||
retransmittedPacket := getPacket(123)
|
||||
sph := mockackhandler.NewMockSentPacketHandler(mockCtrl)
|
||||
sph.EXPECT().TimeUntilSend()
|
||||
sph.EXPECT().SendMode().Return(ackhandler.SendTLP)
|
||||
sph.EXPECT().SendMode().Return(ackhandler.SendPTO)
|
||||
sph.EXPECT().ShouldSendNumPackets().Return(1)
|
||||
sph.EXPECT().DequeueProbePacket().Return(packetToRetransmit, nil)
|
||||
packer.EXPECT().PackRetransmission(packetToRetransmit).Return([]*packedPacket{retransmittedPacket}, nil)
|
||||
|
||||
Reference in New Issue
Block a user