Implement loss recovery from the current WG draft

Fixes #498 and will hopefully go a long way towards fixing the many
flaky tests.
This commit is contained in:
Lucas Clemente 2017-03-24 18:28:59 +01:00
parent 959a8d0e4f
commit 1c5380c49b
9 changed files with 376 additions and 434 deletions

View file

@ -43,7 +43,7 @@ func (m *mockCongestion) OnRetransmissionTimeout(packetsRetransmitted bool) {
}
func (m *mockCongestion) RetransmissionDelay() time.Duration {
return protocol.DefaultRetransmissionTime
return defaultRTOTimeout
}
func (m *mockCongestion) SetNumEmulatedConnections(n int) { panic("not implemented") }
@ -90,7 +90,7 @@ var _ = Describe("SentPacketHandler", func() {
Expect(handler.lastSentPacketNumber).To(Equal(protocol.PacketNumber(2)))
Expect(handler.packetHistory.Front().Value.PacketNumber).To(Equal(protocol.PacketNumber(1)))
Expect(handler.packetHistory.Back().Value.PacketNumber).To(Equal(protocol.PacketNumber(2)))
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(3)))
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(3)))
Expect(handler.skippedPackets).To(BeEmpty())
})
@ -103,7 +103,7 @@ var _ = Describe("SentPacketHandler", func() {
Expect(err).To(MatchError(errPacketNumberNotIncreasing))
Expect(handler.lastSentPacketNumber).To(Equal(protocol.PacketNumber(1)))
Expect(handler.packetHistory.Front().Value.PacketNumber).To(Equal(protocol.PacketNumber(1)))
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(1)))
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(1)))
Expect(handler.skippedPackets).To(BeEmpty())
})
@ -116,7 +116,7 @@ var _ = Describe("SentPacketHandler", func() {
Expect(err).To(MatchError(errPacketNumberNotIncreasing))
Expect(handler.lastSentPacketNumber).To(Equal(protocol.PacketNumber(2)))
Expect(handler.packetHistory.Front().Value.PacketNumber).To(Equal(protocol.PacketNumber(2)))
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(1)))
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(1)))
})
It("stores the sent time", func() {
@ -126,13 +126,6 @@ var _ = Describe("SentPacketHandler", func() {
Expect(handler.packetHistory.Front().Value.SendTime.Unix()).To(BeNumerically("~", time.Now().Unix(), 1))
})
It("updates the last sent time", func() {
packet := Packet{PacketNumber: 1, Frames: []frames.Frame{&streamFrame}, Length: 1}
err := handler.SentPacket(&packet)
Expect(err).ToNot(HaveOccurred())
Expect(handler.lastSentPacketTime.Unix()).To(BeNumerically("~", time.Now().Unix(), 1))
})
Context("skipped packet numbers", func() {
It("works with non-consecutive packet numbers", func() {
packet1 := Packet{PacketNumber: 1, Frames: []frames.Frame{&streamFrame}, Length: 1}
@ -146,7 +139,7 @@ var _ = Describe("SentPacketHandler", func() {
Expect(el.Value.PacketNumber).To(Equal(protocol.PacketNumber(1)))
el = el.Next()
Expect(el.Value.PacketNumber).To(Equal(protocol.PacketNumber(3)))
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(3)))
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(3)))
Expect(handler.skippedPackets).To(HaveLen(1))
Expect(handler.skippedPackets[0]).To(Equal(protocol.PacketNumber(2)))
})
@ -244,9 +237,12 @@ var _ = Describe("SentPacketHandler", func() {
{PacketNumber: 12, Frames: []frames.Frame{&streamFrame}, Length: 1},
}
for _, packet := range packets {
handler.SentPacket(packet)
err := handler.SentPacket(packet)
Expect(err).NotTo(HaveOccurred())
}
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(len(packets))))
// Increase RTT, because the tests would be flaky otherwise
handler.rttStats.UpdateRTT(time.Hour, 0, time.Now())
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(len(packets))))
})
Context("ACK validation", func() {
@ -258,10 +254,10 @@ var _ = Describe("SentPacketHandler", func() {
}
err := handler.ReceivedAck(&ack, 1337, time.Now())
Expect(err).ToNot(HaveOccurred())
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(len(packets) - 3)))
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(len(packets) - 3)))
err = handler.ReceivedAck(&ack, 1337, time.Now())
Expect(err).To(MatchError(ErrDuplicateOrOutOfOrderAck))
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(len(packets) - 3)))
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(len(packets) - 3)))
})
It("rejects out of order ACKs", func() {
@ -270,11 +266,11 @@ var _ = Describe("SentPacketHandler", func() {
}
err := handler.ReceivedAck(&ack, 1337, time.Now())
Expect(err).ToNot(HaveOccurred())
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(len(packets) - 3)))
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(len(packets) - 3)))
err = handler.ReceivedAck(&ack, 1337-1, time.Now())
Expect(err).To(MatchError(ErrDuplicateOrOutOfOrderAck))
Expect(handler.LargestAcked).To(Equal(protocol.PacketNumber(3)))
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(len(packets) - 3)))
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(len(packets) - 3)))
})
It("rejects ACKs with a too high LargestAcked packet number", func() {
@ -283,7 +279,7 @@ var _ = Describe("SentPacketHandler", func() {
}
err := handler.ReceivedAck(&ack, 1, time.Now())
Expect(err).To(MatchError(errAckForUnsentPacket))
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(len(packets))))
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(len(packets))))
})
It("ignores repeated ACKs", func() {
@ -293,11 +289,11 @@ var _ = Describe("SentPacketHandler", func() {
}
err := handler.ReceivedAck(&ack, 1337, time.Now())
Expect(err).ToNot(HaveOccurred())
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(len(packets) - 3)))
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(len(packets) - 3)))
err = handler.ReceivedAck(&ack, 1337+1, time.Now())
Expect(err).ToNot(HaveOccurred())
Expect(handler.LargestAcked).To(Equal(protocol.PacketNumber(3)))
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(len(packets) - 3)))
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(len(packets) - 3)))
})
It("rejects ACKs for skipped packets", func() {
@ -307,7 +303,6 @@ var _ = Describe("SentPacketHandler", func() {
}
err := handler.ReceivedAck(&ack, 1337, time.Now())
Expect(err).To(MatchError(ErrAckForSkippedPacket))
Expect(handler.LargestAcked).To(BeZero())
})
It("accepts an ACK that correctly nacks a skipped packet", func() {
@ -337,7 +332,6 @@ var _ = Describe("SentPacketHandler", func() {
el := handler.packetHistory.Front()
for i := 6; i <= 10; i++ {
Expect(el.Value.PacketNumber).To(Equal(protocol.PacketNumber(i)))
Expect(el.Value.MissingReports).To(BeZero())
el = el.Next()
}
Expect(el.Value.PacketNumber).To(Equal(protocol.PacketNumber(12)))
@ -354,10 +348,8 @@ var _ = Describe("SentPacketHandler", func() {
Expect(el.Value.PacketNumber).To(Equal(protocol.PacketNumber(1)))
el = el.Next()
Expect(el.Value.PacketNumber).To(Equal(protocol.PacketNumber(9)))
Expect(el.Value.MissingReports).To(BeZero())
el = el.Next()
Expect(el.Value.PacketNumber).To(Equal(protocol.PacketNumber(10)))
Expect(el.Value.MissingReports).To(BeZero())
Expect(el.Next().Value.PacketNumber).To(Equal(protocol.PacketNumber(12)))
})
@ -376,17 +368,14 @@ var _ = Describe("SentPacketHandler", func() {
Expect(el.Value.PacketNumber).To(Equal(protocol.PacketNumber(1)))
el = el.Next()
Expect(el.Value.PacketNumber).To(Equal(protocol.PacketNumber(4)))
Expect(el.Value.MissingReports).To(Equal(uint8(1)))
el = el.Next()
Expect(el.Value.PacketNumber).To(Equal(protocol.PacketNumber(5)))
Expect(el.Value.MissingReports).To(Equal(uint8(1)))
el = el.Next()
Expect(el.Value.PacketNumber).To(Equal(protocol.PacketNumber(10)))
Expect(el.Value.MissingReports).To(BeZero())
Expect(el.Next().Value.PacketNumber).To(Equal(protocol.PacketNumber(12)))
})
It("NACKs packets below the LowestAcked", func() {
It("Does not ack packets below the LowestAcked", func() {
ack := frames.AckFrame{
LargestAcked: 8,
LowestAcked: 3,
@ -395,10 +384,8 @@ var _ = Describe("SentPacketHandler", func() {
Expect(err).ToNot(HaveOccurred())
el := handler.packetHistory.Front()
Expect(el.Value.PacketNumber).To(Equal(protocol.PacketNumber(1)))
Expect(el.Value.MissingReports).To(Equal(uint8(1)))
el = el.Next()
Expect(el.Value.PacketNumber).To(Equal(protocol.PacketNumber(2)))
Expect(el.Value.MissingReports).To(Equal(uint8(1)))
Expect(el.Next().Value.PacketNumber).To(Equal(protocol.PacketNumber(9)))
})
@ -417,19 +404,14 @@ var _ = Describe("SentPacketHandler", func() {
Expect(err).ToNot(HaveOccurred())
el := handler.packetHistory.Front()
Expect(el.Value.PacketNumber).To(Equal(protocol.PacketNumber(2)))
Expect(el.Value.MissingReports).To(Equal(uint8(1)))
el = el.Next()
Expect(el.Value.PacketNumber).To(Equal(protocol.PacketNumber(4)))
Expect(el.Value.MissingReports).To(Equal(uint8(1)))
el = el.Next()
Expect(el.Value.PacketNumber).To(Equal(protocol.PacketNumber(5)))
Expect(el.Value.MissingReports).To(Equal(uint8(1)))
el = el.Next()
Expect(el.Value.PacketNumber).To(Equal(protocol.PacketNumber(8)))
Expect(el.Value.MissingReports).To(Equal(uint8(1)))
el = el.Next()
Expect(el.Value.PacketNumber).To(Equal(protocol.PacketNumber(10)))
Expect(el.Value.MissingReports).To(BeZero())
})
It("processes an ACK frame that would be sent after a late arrival of a packet", func() {
@ -444,7 +426,7 @@ var _ = Describe("SentPacketHandler", func() {
}
err := handler.ReceivedAck(&ack1, 1, time.Now())
Expect(err).ToNot(HaveOccurred())
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(len(packets) - 5)))
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(len(packets) - 5)))
el := handler.packetHistory.Front()
Expect(el.Value.PacketNumber).To(Equal(protocol.PacketNumber(3)))
ack2 := frames.AckFrame{
@ -453,7 +435,7 @@ var _ = Describe("SentPacketHandler", func() {
}
err = handler.ReceivedAck(&ack2, 2, time.Now())
Expect(err).ToNot(HaveOccurred())
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(len(packets) - 6)))
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(len(packets) - 6)))
Expect(handler.packetHistory.Front().Value.PacketNumber).To(Equal(protocol.PacketNumber(7)))
})
@ -468,7 +450,7 @@ var _ = Describe("SentPacketHandler", func() {
}
err := handler.ReceivedAck(&ack1, 1, time.Now())
Expect(err).ToNot(HaveOccurred())
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(len(packets) - 5)))
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(len(packets) - 5)))
el := handler.packetHistory.Front()
Expect(el.Value.PacketNumber).To(Equal(protocol.PacketNumber(3)))
ack2 := frames.AckFrame{
@ -477,7 +459,7 @@ var _ = Describe("SentPacketHandler", func() {
}
err = handler.ReceivedAck(&ack2, 2, time.Now())
Expect(err).ToNot(HaveOccurred())
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(len(packets) - 7)))
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(len(packets) - 7)))
Expect(handler.packetHistory.Front().Value.PacketNumber).To(Equal(protocol.PacketNumber(8)))
})
@ -489,7 +471,7 @@ var _ = Describe("SentPacketHandler", func() {
err := handler.ReceivedAck(&ack1, 1, time.Now())
Expect(err).ToNot(HaveOccurred())
Expect(handler.packetHistory.Front().Value.PacketNumber).To(Equal(protocol.PacketNumber(7)))
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(len(packets) - 6)))
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(len(packets) - 6)))
ack2 := frames.AckFrame{
LargestAcked: 10,
LowestAcked: 1,
@ -501,14 +483,14 @@ var _ = Describe("SentPacketHandler", func() {
}
err = handler.ReceivedAck(&ack2, 2, time.Now())
Expect(err).ToNot(HaveOccurred())
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(len(packets) - 6 - 3)))
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(len(packets) - 6 - 3)))
Expect(handler.packetHistory.Front().Value.PacketNumber).To(Equal(protocol.PacketNumber(7)))
Expect(handler.packetHistory.Back().Value.PacketNumber).To(Equal(protocol.PacketNumber(12)))
})
})
Context("calculating RTT", func() {
It("calculates the RTT", func() {
It("computes the RTT", func() {
now := time.Now()
// First, fake the sent times of the first, second and last packet
getPacketElement(1).Value.SendTime = now.Add(-10 * time.Minute)
@ -536,7 +518,7 @@ var _ = Describe("SentPacketHandler", func() {
})
})
Context("Retransmission handler", func() {
Context("Retransmission handling", func() {
var packets []*Packet
BeforeEach(func() {
@ -552,67 +534,33 @@ var _ = Describe("SentPacketHandler", func() {
for _, packet := range packets {
handler.SentPacket(packet)
}
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(7)))
// Increase RTT, because the tests would be flaky otherwise
handler.rttStats.UpdateRTT(time.Minute, 0, time.Now())
// Ack a single packet so that we have non-RTO timings
handler.ReceivedAck(&frames.AckFrame{LargestAcked: 2, LowestAcked: 2}, 1, time.Now())
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(6)))
})
It("does not dequeue a packet if no packet has been nacked", func() {
for i := uint8(0); i < protocol.RetransmissionThreshold; i++ {
el := getPacketElement(2)
Expect(el).ToNot(BeNil())
handler.nackPacket(el)
}
Expect(getPacketElement(2)).ToNot(BeNil())
handler.MaybeQueueRTOs()
It("does not dequeue a packet if no ack has been received", func() {
Expect(handler.DequeuePacketForRetransmission()).To(BeNil())
})
It("queues a packet for retransmission", func() {
for i := uint8(0); i < protocol.RetransmissionThreshold+1; i++ {
el := getPacketElement(2)
Expect(el).ToNot(BeNil())
handler.nackPacket(el)
}
Expect(getPacketElement(2)).To(BeNil())
handler.MaybeQueueRTOs()
Expect(handler.retransmissionQueue).To(HaveLen(1))
Expect(handler.retransmissionQueue[0].PacketNumber).To(Equal(protocol.PacketNumber(2)))
})
It("dequeues a packet for retransmission", func() {
for i := uint8(0); i < protocol.RetransmissionThreshold+1; i++ {
el := getPacketElement(3)
Expect(el).ToNot(BeNil())
handler.nackPacket(el)
}
getPacketElement(1).Value.SendTime = time.Now().Add(-time.Hour)
handler.OnAlarm()
Expect(getPacketElement(1)).To(BeNil())
Expect(handler.retransmissionQueue).To(HaveLen(1))
Expect(handler.retransmissionQueue[0].PacketNumber).To(Equal(protocol.PacketNumber(1)))
packet := handler.DequeuePacketForRetransmission()
Expect(packet).ToNot(BeNil())
Expect(packet.PacketNumber).To(Equal(protocol.PacketNumber(3)))
Expect(packet.PacketNumber).To(Equal(protocol.PacketNumber(1)))
Expect(handler.DequeuePacketForRetransmission()).To(BeNil())
})
It("keeps the packets in the right order", func() {
for i := uint8(0); i < protocol.RetransmissionThreshold+1; i++ {
el := getPacketElement(4)
Expect(el).ToNot(BeNil())
handler.nackPacket(el)
}
for i := uint8(0); i < protocol.RetransmissionThreshold+1; i++ {
el := getPacketElement(2)
Expect(el).ToNot(BeNil())
handler.nackPacket(el)
}
packet := handler.DequeuePacketForRetransmission()
Expect(packet).ToNot(BeNil())
Expect(packet.PacketNumber).To(Equal(protocol.PacketNumber(2)))
packet = handler.DequeuePacketForRetransmission()
Expect(packet).ToNot(BeNil())
Expect(packet.PacketNumber).To(Equal(protocol.PacketNumber(4)))
})
Context("StopWaitings", func() {
It("gets a StopWaitingFrame", func() {
ack := frames.AckFrame{LargestAcked: 5, LowestAcked: 5}
err := handler.ReceivedAck(&ack, 1, time.Now())
err := handler.ReceivedAck(&ack, 2, time.Now())
Expect(err).ToNot(HaveOccurred())
Expect(handler.GetStopWaitingFrame(false)).To(Equal(&frames.StopWaitingFrame{LeastUnacked: 6}))
})
@ -624,55 +572,40 @@ var _ = Describe("SentPacketHandler", func() {
})
})
Context("calculating bytes in flight", func() {
It("works in a typical retransmission scenarios", func() {
packet1 := Packet{PacketNumber: 1, Frames: []frames.Frame{&streamFrame}, Length: 1}
packet2 := Packet{PacketNumber: 2, Frames: []frames.Frame{&streamFrame}, Length: 2}
packet3 := Packet{PacketNumber: 3, Frames: []frames.Frame{&streamFrame}, Length: 3}
err := handler.SentPacket(&packet1)
Expect(err).NotTo(HaveOccurred())
err = handler.SentPacket(&packet2)
Expect(err).NotTo(HaveOccurred())
err = handler.SentPacket(&packet3)
Expect(err).NotTo(HaveOccurred())
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(1 + 2 + 3)))
It("calculates bytes in flight", func() {
packet1 := Packet{PacketNumber: 1, Frames: []frames.Frame{&streamFrame}, Length: 1}
packet2 := Packet{PacketNumber: 2, Frames: []frames.Frame{&streamFrame}, Length: 2}
packet3 := Packet{PacketNumber: 3, Frames: []frames.Frame{&streamFrame}, Length: 3}
err := handler.SentPacket(&packet1)
Expect(err).NotTo(HaveOccurred())
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(1)))
err = handler.SentPacket(&packet2)
Expect(err).NotTo(HaveOccurred())
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(1 + 2)))
err = handler.SentPacket(&packet3)
Expect(err).NotTo(HaveOccurred())
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(1 + 2 + 3)))
// ACK 1 and 3, NACK 2
ack := frames.AckFrame{
LargestAcked: 3,
LowestAcked: 1,
AckRanges: []frames.AckRange{
{FirstPacketNumber: 3, LastPacketNumber: 3},
{FirstPacketNumber: 1, LastPacketNumber: 1},
},
}
err = handler.ReceivedAck(&ack, 1, time.Now())
Expect(err).NotTo(HaveOccurred())
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(2)))
// Increase RTT, because the tests would be flaky otherwise
handler.rttStats.UpdateRTT(time.Minute, 0, time.Now())
// Simulate protocol.RetransmissionThreshold more NACKs
for i := uint8(0); i < protocol.RetransmissionThreshold; i++ {
el := getPacketElement(2)
Expect(el).ToNot(BeNil())
handler.nackPacket(el)
}
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(0)))
// ACK 1 and 3, NACK 2
ack := frames.AckFrame{
LargestAcked: 3,
LowestAcked: 1,
AckRanges: []frames.AckRange{
{FirstPacketNumber: 3, LastPacketNumber: 3},
{FirstPacketNumber: 1, LastPacketNumber: 1},
},
}
err = handler.ReceivedAck(&ack, 1, time.Now())
Expect(err).NotTo(HaveOccurred())
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(2)))
// Retransmission
packet4 := Packet{PacketNumber: 4, Length: 2}
err = handler.SentPacket(&packet4)
Expect(err).NotTo(HaveOccurred())
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(2)))
handler.packetHistory.Front().Value.SendTime = time.Now().Add(-time.Hour)
handler.OnAlarm()
// ACK
ack = frames.AckFrame{
LargestAcked: 4,
LowestAcked: 1,
}
err = handler.ReceivedAck(&ack, 2, time.Now())
Expect(err).NotTo(HaveOccurred())
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(0)))
})
Expect(handler.bytesInFlight).To(Equal(protocol.ByteCount(0)))
})
Context("congestion", func() {
@ -688,7 +621,6 @@ var _ = Describe("SentPacketHandler", func() {
It("should call OnSent", func() {
p := &Packet{
PacketNumber: 1,
Frames: []frames.Frame{&frames.StreamFrame{StreamID: 5}},
Length: 42,
}
err := handler.SentPacket(p)
@ -700,46 +632,31 @@ var _ = Describe("SentPacketHandler", func() {
Expect(cong.argsOnPacketSent[4]).To(BeTrue())
})
It("should call OnCongestionEvent", func() {
It("should call OnCongestionEvent for ACKs", func() {
handler.SentPacket(&Packet{PacketNumber: 1, Frames: []frames.Frame{}, Length: 1})
handler.SentPacket(&Packet{PacketNumber: 2, Frames: []frames.Frame{}, Length: 2})
handler.SentPacket(&Packet{PacketNumber: 3, Frames: []frames.Frame{}, Length: 3})
ack := frames.AckFrame{
LargestAcked: 3,
LowestAcked: 1,
AckRanges: []frames.AckRange{
{FirstPacketNumber: 3, LastPacketNumber: 3},
{FirstPacketNumber: 1, LastPacketNumber: 1},
},
}
err := handler.ReceivedAck(&ack, 1, time.Now())
handler.SentPacket(&Packet{PacketNumber: 2, Frames: []frames.Frame{}, Length: 1})
Expect(cong.nCalls).To(Equal(2))
err := handler.ReceivedAck(&frames.AckFrame{LargestAcked: 1, LowestAcked: 1}, 1, time.Now())
Expect(err).NotTo(HaveOccurred())
Expect(cong.nCalls).To(Equal(4)) // 3 * SentPacket + 1 * ReceivedAck
// rttUpdated, bytesInFlight, ackedPackets, lostPackets
Expect(cong.nCalls).To(Equal(3))
Expect(cong.argsOnCongestionEvent[0]).To(BeTrue())
Expect(cong.argsOnCongestionEvent[1]).To(Equal(protocol.ByteCount(2)))
Expect(cong.argsOnCongestionEvent[2]).To(Equal(congestion.PacketVector{{Number: 1, Length: 1}, {Number: 3, Length: 3}}))
Expect(cong.argsOnCongestionEvent[1]).To(Equal(protocol.ByteCount(1)))
Expect(cong.argsOnCongestionEvent[2]).To(Equal(congestion.PacketVector{{Number: 1, Length: 1}}))
Expect(cong.argsOnCongestionEvent[3]).To(BeEmpty())
})
// Loose the packet
var packetNumber protocol.PacketNumber
for i := uint8(0); i < protocol.RetransmissionThreshold; i++ {
packetNumber = protocol.PacketNumber(4 + i)
handler.SentPacket(&Packet{PacketNumber: packetNumber, Frames: []frames.Frame{}, Length: protocol.ByteCount(packetNumber)})
ack := frames.AckFrame{
LargestAcked: packetNumber,
LowestAcked: 1,
AckRanges: []frames.AckRange{
{FirstPacketNumber: 3, LastPacketNumber: packetNumber},
{FirstPacketNumber: 1, LastPacketNumber: 1},
},
}
err = handler.ReceivedAck(&ack, protocol.PacketNumber(2+i), time.Now())
Expect(err).NotTo(HaveOccurred())
}
Expect(cong.argsOnCongestionEvent[2]).To(Equal(congestion.PacketVector{{Number: packetNumber, Length: protocol.ByteCount(packetNumber)}}))
Expect(cong.argsOnCongestionEvent[3]).To(Equal(congestion.PacketVector{{Number: 2, Length: 2}}))
It("should call OnCongestionEvent for losses", func() {
handler.SentPacket(&Packet{PacketNumber: 1, Frames: []frames.Frame{}, Length: 1})
handler.SentPacket(&Packet{PacketNumber: 2, Frames: []frames.Frame{}, Length: 1})
handler.SentPacket(&Packet{PacketNumber: 3, Frames: []frames.Frame{}, Length: 1})
Expect(cong.nCalls).To(Equal(3))
handler.OnAlarm() // RTO, meaning 2 lost packets
Expect(cong.nCalls).To(Equal(3 + 4 /* 2* (OnCongestionEvent+OnRTO)*/))
Expect(cong.onRetransmissionTimeout).To(BeTrue())
Expect(cong.argsOnCongestionEvent[0]).To(BeFalse())
Expect(cong.argsOnCongestionEvent[1]).To(Equal(protocol.ByteCount(1)))
Expect(cong.argsOnCongestionEvent[2]).To(BeEmpty())
Expect(cong.argsOnCongestionEvent[3]).To(Equal(congestion.PacketVector{{Number: 2, Length: 1}}))
})
It("allows or denies sending based on congestion", func() {
@ -754,111 +671,101 @@ var _ = Describe("SentPacketHandler", func() {
handler.retransmissionQueue = make([]*Packet, protocol.MaxTrackedSentPackets)
Expect(handler.SendingAllowed()).To(BeFalse())
})
It("should call OnRetransmissionTimeout", func() {
err := handler.SentPacket(&Packet{PacketNumber: 1, Frames: []frames.Frame{}, Length: 1})
Expect(err).NotTo(HaveOccurred())
handler.lastSentPacketTime = time.Now().Add(-time.Second)
handler.MaybeQueueRTOs()
Expect(cong.nCalls).To(Equal(3))
// rttUpdated, bytesInFlight, ackedPackets, lostPackets
Expect(cong.argsOnCongestionEvent[0]).To(BeFalse())
Expect(cong.argsOnCongestionEvent[1]).To(Equal(protocol.ByteCount(1)))
Expect(cong.argsOnCongestionEvent[2]).To(BeEmpty())
Expect(cong.argsOnCongestionEvent[3]).To(Equal(congestion.PacketVector{{Number: 1, Length: 1}}))
Expect(cong.onRetransmissionTimeout).To(BeTrue())
})
})
Context("calculating RTO", func() {
It("uses default RTO", func() {
Expect(handler.getRTO()).To(Equal(protocol.DefaultRetransmissionTime))
Expect(handler.computeRTOTimeout()).To(Equal(defaultRTOTimeout))
})
It("uses RTO from rttStats", func() {
rtt := time.Second
expected := rtt + rtt/2*4
handler.rttStats.UpdateRTT(rtt, 0, time.Now())
Expect(handler.getRTO()).To(Equal(expected))
Expect(handler.computeRTOTimeout()).To(Equal(expected))
})
It("limits RTO min", func() {
rtt := time.Millisecond
handler.rttStats.UpdateRTT(rtt, 0, time.Now())
Expect(handler.getRTO()).To(Equal(protocol.MinRetransmissionTime))
Expect(handler.computeRTOTimeout()).To(Equal(minRTOTimeout))
})
It("limits RTO max", func() {
rtt := time.Hour
handler.rttStats.UpdateRTT(rtt, 0, time.Now())
Expect(handler.getRTO()).To(Equal(protocol.MaxRetransmissionTime))
Expect(handler.computeRTOTimeout()).To(Equal(maxRTOTimeout))
})
It("implements exponential backoff", func() {
handler.consecutiveRTOCount = 0
Expect(handler.getRTO()).To(Equal(protocol.DefaultRetransmissionTime))
handler.consecutiveRTOCount = 1
Expect(handler.getRTO()).To(Equal(2 * protocol.DefaultRetransmissionTime))
handler.consecutiveRTOCount = 2
Expect(handler.getRTO()).To(Equal(4 * protocol.DefaultRetransmissionTime))
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))
})
})
Context("Delay-based loss detection", func() {
It("detects a packet as lost", func() {
err := handler.SentPacket(&Packet{PacketNumber: 1, Length: 1})
Expect(err).NotTo(HaveOccurred())
err = handler.SentPacket(&Packet{PacketNumber: 2, Length: 1})
Expect(err).NotTo(HaveOccurred())
Expect(handler.lossTime.IsZero()).To(BeTrue())
err = handler.ReceivedAck(&frames.AckFrame{LargestAcked: 2, LowestAcked: 2}, 1, time.Now().Add(time.Hour))
Expect(err).NotTo(HaveOccurred())
Expect(handler.lossTime.IsZero()).To(BeFalse())
// RTT is around 1h now.
// The formula is (1+1/8) * RTT, so this should be around that number
Expect(handler.lossTime.Sub(time.Now())).To(BeNumerically("~", time.Hour*9/8, time.Minute))
Expect(handler.GetAlarmTimeout().Sub(time.Now())).To(BeNumerically("~", time.Hour*9/8, time.Minute))
handler.packetHistory.Front().Value.SendTime = time.Now().Add(-2 * time.Hour)
handler.OnAlarm()
Expect(handler.DequeuePacketForRetransmission()).NotTo(BeNil())
})
It("does not detect packets as lost without ACKs", func() {
err := handler.SentPacket(&Packet{PacketNumber: 1, Length: 1})
Expect(err).NotTo(HaveOccurred())
err = handler.SentPacket(&Packet{PacketNumber: 2, Length: 1})
Expect(err).NotTo(HaveOccurred())
err = handler.SentPacket(&Packet{PacketNumber: 3, Length: 1})
Expect(err).NotTo(HaveOccurred())
Expect(handler.lossTime.IsZero()).To(BeTrue())
err = handler.ReceivedAck(&frames.AckFrame{LargestAcked: 1, LowestAcked: 1}, 1, time.Now().Add(time.Hour))
Expect(err).NotTo(HaveOccurred())
Expect(handler.lossTime.IsZero()).To(BeTrue())
Expect(handler.GetAlarmTimeout().Sub(time.Now())).To(BeNumerically("~", handler.computeRTOTimeout(), time.Minute))
// This means RTO, so both packets should be lost
handler.OnAlarm()
Expect(handler.DequeuePacketForRetransmission()).ToNot(BeNil())
Expect(handler.DequeuePacketForRetransmission()).ToNot(BeNil())
})
})
Context("RTO retransmission", func() {
Context("calculating the time to first RTO", func() {
It("defaults to zero", func() {
Expect(handler.TimeOfFirstRTO().IsZero()).To(BeTrue())
})
It("returns time to RTO", func() {
err := handler.SentPacket(&Packet{PacketNumber: 1, Frames: []frames.Frame{}, Length: 1})
Expect(err).NotTo(HaveOccurred())
Expect(handler.TimeOfFirstRTO().Sub(time.Now())).To(BeNumerically("~", protocol.DefaultRetransmissionTime, time.Millisecond))
})
})
Context("queuing packets due to RTO", func() {
It("does nothing if not required", func() {
err := handler.SentPacket(&Packet{PacketNumber: 1, Frames: []frames.Frame{}, Length: 1})
Expect(err).NotTo(HaveOccurred())
handler.MaybeQueueRTOs()
Expect(handler.retransmissionQueue).To(BeEmpty())
})
It("queues a packet if RTO expired", func() {
p := &Packet{PacketNumber: 1, Frames: []frames.Frame{}, Length: 1}
err := handler.SentPacket(p)
Expect(err).NotTo(HaveOccurred())
handler.lastSentPacketTime = time.Now().Add(-time.Second)
handler.MaybeQueueRTOs()
Expect(handler.retransmissionQueue).To(HaveLen(1))
Expect(handler.retransmissionQueue[0].PacketNumber).To(Equal(p.PacketNumber))
Expect(time.Now().Sub(handler.lastSentPacketTime)).To(BeNumerically("<", time.Second/2))
})
It("queues two packets if RTO expired", func() {
for i := 1; i < 4; i++ {
p := &Packet{PacketNumber: protocol.PacketNumber(i), Length: 1}
err := handler.SentPacket(p)
Expect(err).NotTo(HaveOccurred())
}
handler.lastSentPacketTime = time.Now().Add(-time.Second)
handler.MaybeQueueRTOs()
Expect(handler.retransmissionQueue).To(HaveLen(2))
Expect(handler.retransmissionQueue[0].PacketNumber).To(Equal(protocol.PacketNumber(1)))
Expect(handler.retransmissionQueue[1].PacketNumber).To(Equal(protocol.PacketNumber(2)))
Expect(time.Now().Sub(handler.lastSentPacketTime)).To(BeNumerically("<", time.Second/2))
Expect(handler.consecutiveRTOCount).To(Equal(uint32(1)))
})
})
It("works with DequeuePacketForRetransmission", func() {
p := &Packet{PacketNumber: 1, Frames: []frames.Frame{}, Length: 1}
err := handler.SentPacket(p)
It("queues two packets if RTO expires", func() {
err := handler.SentPacket(&Packet{PacketNumber: 1, Length: 1})
Expect(err).NotTo(HaveOccurred())
handler.lastSentPacketTime = time.Now().Add(-time.Second)
handler.MaybeQueueRTOs()
Expect(handler.DequeuePacketForRetransmission().PacketNumber).To(Equal(p.PacketNumber))
err = handler.SentPacket(&Packet{PacketNumber: 2, Length: 1})
Expect(err).NotTo(HaveOccurred())
handler.rttStats.UpdateRTT(time.Hour, 0, time.Now())
Expect(handler.lossTime.IsZero()).To(BeTrue())
Expect(handler.GetAlarmTimeout().Sub(time.Now())).To(BeNumerically("~", handler.computeRTOTimeout(), time.Minute))
handler.OnAlarm()
Expect(handler.DequeuePacketForRetransmission()).ToNot(BeNil())
Expect(handler.DequeuePacketForRetransmission()).ToNot(BeNil())
Expect(handler.rtoCount).To(BeEquivalentTo(1))
})
})
})