move congestion control from session to ackhandler

this simplifies things a bit, especially in prep for #56
This commit is contained in:
Lucas Clemente 2016-05-18 19:35:31 +02:00
parent 7a97f34fac
commit a0228a9049
6 changed files with 202 additions and 261 deletions

View file

@ -3,15 +3,51 @@ package ackhandler
import (
"time"
"github.com/lucas-clemente/quic-go/congestion"
"github.com/lucas-clemente/quic-go/frames"
"github.com/lucas-clemente/quic-go/protocol"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
type mockCongestion struct {
nCalls int
argsOnPacketSent []interface{}
argsOnCongestionEvent []interface{}
}
func (m *mockCongestion) TimeUntilSend(now time.Time, bytesInFlight protocol.ByteCount) time.Duration {
panic("not implemented")
}
func (m *mockCongestion) OnPacketSent(sentTime time.Time, bytesInFlight protocol.ByteCount, packetNumber protocol.PacketNumber, bytes protocol.ByteCount, isRetransmittable bool) bool {
m.nCalls++
m.argsOnPacketSent = []interface{}{sentTime, bytesInFlight, packetNumber, bytes, isRetransmittable}
return false
}
func (m *mockCongestion) GetCongestionWindow() protocol.ByteCount {
m.nCalls++
return protocol.DefaultTCPMSS
}
func (m *mockCongestion) OnCongestionEvent(rttUpdated bool, bytesInFlight protocol.ByteCount, ackedPackets congestion.PacketVector, lostPackets congestion.PacketVector) {
m.nCalls++
m.argsOnCongestionEvent = []interface{}{rttUpdated, bytesInFlight, ackedPackets, lostPackets}
}
func (m *mockCongestion) SetNumEmulatedConnections(n int) { panic("not implemented") }
func (m *mockCongestion) OnRetransmissionTimeout(packetsRetransmitted bool) { panic("not implemented") }
func (m *mockCongestion) OnConnectionMigration() { panic("not implemented") }
func (m *mockCongestion) RetransmissionDelay() time.Duration { panic("not implemented") }
func (m *mockCongestion) SetSlowStartLargeReduction(enabled bool) { panic("not implemented") }
var _ = Describe("SentPacketHandler", func() {
var handler *sentPacketHandler
var streamFrame frames.StreamFrame
var (
handler *sentPacketHandler
streamFrame frames.StreamFrame
)
BeforeEach(func() {
stopWaitingManager := NewStopWaitingManager()
handler = NewSentPacketHandler(stopWaitingManager).(*sentPacketHandler)
@ -88,7 +124,7 @@ var _ = Describe("SentPacketHandler", func() {
LargestObserved: 1,
Entropy: byte(entropy),
}
_, _, _, err = handler.ReceivedAck(&ack)
err = handler.ReceivedAck(&ack)
Expect(err).ToNot(HaveOccurred())
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(0)))
err = handler.SentPacket(&packet2)
@ -200,7 +236,7 @@ var _ = Describe("SentPacketHandler", func() {
LargestObserved: 4,
Entropy: 1,
}
_, _, _, err := handler.ReceivedAck(&ack)
err := handler.ReceivedAck(&ack)
Expect(err).To(MatchError(ErrEntropy))
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(6)))
})
@ -215,19 +251,13 @@ var _ = Describe("SentPacketHandler", func() {
LargestObserved: protocol.PacketNumber(largestObserved),
Entropy: byte(entropy),
}
_, acked, lost, err := handler.ReceivedAck(&ack)
err := handler.ReceivedAck(&ack)
Expect(err).ToNot(HaveOccurred())
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(2)))
Expect(handler.LargestObserved).To(Equal(protocol.PacketNumber(largestObserved)))
Expect(handler.highestInOrderAckedPacketNumber).To(Equal(protocol.PacketNumber(largestObserved)))
Expect(handler.packetHistory).ToNot(HaveKey(protocol.PacketNumber(largestObserved - 1)))
Expect(handler.packetHistory).To(HaveKey(protocol.PacketNumber(largestObserved + 1)))
Expect(acked).To(HaveLen(4))
Expect(acked[0].PacketNumber).To(Equal(protocol.PacketNumber(1)))
Expect(acked[1].PacketNumber).To(Equal(protocol.PacketNumber(2)))
Expect(acked[2].PacketNumber).To(Equal(protocol.PacketNumber(3)))
Expect(acked[3].PacketNumber).To(Equal(protocol.PacketNumber(4)))
Expect(lost).To(BeEmpty())
})
It("completely processes an ACK with a NACK range", func() {
@ -247,7 +277,7 @@ var _ = Describe("SentPacketHandler", func() {
{FirstPacketNumber: 3, LastPacketNumber: 3},
},
}
_, acked, lost, err := handler.ReceivedAck(&ack)
err := handler.ReceivedAck(&ack)
Expect(err).ToNot(HaveOccurred())
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(2)))
Expect(handler.LargestObserved).To(Equal(protocol.PacketNumber(largestObserved)))
@ -257,12 +287,6 @@ var _ = Describe("SentPacketHandler", func() {
Expect(handler.packetHistory).ToNot(HaveKey(protocol.PacketNumber(4)))
Expect(handler.packetHistory).To(HaveKey(protocol.PacketNumber(5)))
Expect(handler.packetHistory).ToNot(HaveKey(protocol.PacketNumber(6)))
Expect(acked).To(HaveLen(4))
Expect(acked[0].PacketNumber).To(Equal(protocol.PacketNumber(1)))
Expect(acked[1].PacketNumber).To(Equal(protocol.PacketNumber(2)))
Expect(acked[2].PacketNumber).To(Equal(protocol.PacketNumber(6)))
Expect(acked[3].PacketNumber).To(Equal(protocol.PacketNumber(4)))
Expect(lost).To(BeEmpty())
})
})
@ -290,10 +314,10 @@ var _ = Describe("SentPacketHandler", func() {
ack := frames.AckFrame{
LargestObserved: protocol.PacketNumber(largestObserved),
}
_, _, _, err := handler.ReceivedAck(&ack)
err := handler.ReceivedAck(&ack)
Expect(err).ToNot(HaveOccurred())
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(3)))
_, _, _, err = handler.ReceivedAck(&ack)
err = handler.ReceivedAck(&ack)
Expect(err).To(MatchError(ErrDuplicateOrOutOfOrderAck))
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(3)))
})
@ -303,11 +327,11 @@ var _ = Describe("SentPacketHandler", func() {
ack := frames.AckFrame{
LargestObserved: protocol.PacketNumber(largestObserved),
}
_, _, _, err := handler.ReceivedAck(&ack)
err := handler.ReceivedAck(&ack)
Expect(err).ToNot(HaveOccurred())
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(3)))
ack.LargestObserved--
_, _, _, err = handler.ReceivedAck(&ack)
err = handler.ReceivedAck(&ack)
Expect(err).To(MatchError(ErrDuplicateOrOutOfOrderAck))
Expect(handler.LargestObserved).To(Equal(protocol.PacketNumber(largestObserved)))
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(3)))
@ -317,29 +341,39 @@ var _ = Describe("SentPacketHandler", func() {
ack := frames.AckFrame{
LargestObserved: packets[len(packets)-1].PacketNumber + 1337,
}
_, _, _, err := handler.ReceivedAck(&ack)
err := handler.ReceivedAck(&ack)
Expect(err).To(MatchError(errAckForUnsentPacket))
Expect(handler.highestInOrderAckedPacketNumber).To(Equal(protocol.PacketNumber(0)))
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(6)))
})
})
It("calculates the time delta", func() {
now := time.Now()
// First, fake the sent times of the first, second and last packet
handler.packetHistory[1].sendTime = now.Add(-10 * time.Minute)
handler.packetHistory[2].sendTime = now.Add(-5 * time.Minute)
handler.packetHistory[6].sendTime = now.Add(-1 * time.Minute)
// Now, check that the proper times are used when calculating the deltas
d, _, _, err := handler.ReceivedAck(&frames.AckFrame{LargestObserved: 1})
Expect(err).NotTo(HaveOccurred())
Expect(d).To(BeNumerically("~", 10*time.Minute, 1*time.Second))
d, _, _, err = handler.ReceivedAck(&frames.AckFrame{LargestObserved: 2})
Expect(err).NotTo(HaveOccurred())
Expect(d).To(BeNumerically("~", 5*time.Minute, 1*time.Second))
d, _, _, err = handler.ReceivedAck(&frames.AckFrame{LargestObserved: 6})
Expect(err).NotTo(HaveOccurred())
Expect(d).To(BeNumerically("~", 1*time.Minute, 1*time.Second))
Context("calculating RTT", func() {
It("calculates the RTT", func() {
now := time.Now()
// First, fake the sent times of the first, second and last packet
handler.packetHistory[1].sendTime = now.Add(-10 * time.Minute)
handler.packetHistory[2].sendTime = now.Add(-5 * time.Minute)
handler.packetHistory[6].sendTime = now.Add(-1 * time.Minute)
// Now, check that the proper times are used when calculating the deltas
err := handler.ReceivedAck(&frames.AckFrame{LargestObserved: 1})
Expect(err).NotTo(HaveOccurred())
Expect(handler.rttStats.LatestRTT()).To(BeNumerically("~", 10*time.Minute, 1*time.Second))
err = handler.ReceivedAck(&frames.AckFrame{LargestObserved: 2})
Expect(err).NotTo(HaveOccurred())
Expect(handler.rttStats.LatestRTT()).To(BeNumerically("~", 5*time.Minute, 1*time.Second))
err = handler.ReceivedAck(&frames.AckFrame{LargestObserved: 6})
Expect(err).NotTo(HaveOccurred())
Expect(handler.rttStats.LatestRTT()).To(BeNumerically("~", 1*time.Minute, 1*time.Second))
})
It("uses the DelayTime in the ack frame", func() {
now := time.Now()
handler.packetHistory[1].sendTime = now.Add(-10 * time.Minute)
err := handler.ReceivedAck(&frames.AckFrame{LargestObserved: 1, DelayTime: 5 * time.Minute})
Expect(err).NotTo(HaveOccurred())
Expect(handler.rttStats.LatestRTT()).To(BeNumerically("~", 5*time.Minute, 1*time.Second))
})
})
})
@ -411,7 +445,7 @@ var _ = Describe("SentPacketHandler", func() {
LargestObserved: 4,
NackRanges: []frames.NackRange{{FirstPacketNumber: 3, LastPacketNumber: 3}},
}
_, _, _, err := handler.ReceivedAck(&ack)
err := handler.ReceivedAck(&ack)
Expect(err).ToNot(HaveOccurred())
Expect(handler.highestInOrderAckedPacketNumber).To(Equal(protocol.PacketNumber(2)))
handler.nackPacket(3) // this is the second NACK for this packet
@ -434,7 +468,7 @@ var _ = Describe("SentPacketHandler", func() {
LargestObserved: 2,
NackRanges: []frames.NackRange{{FirstPacketNumber: 1, LastPacketNumber: 1}},
}
_, _, _, err = handler.ReceivedAck(&ack)
err = handler.ReceivedAck(&ack)
Expect(err).NotTo(HaveOccurred())
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(1)))
@ -453,32 +487,70 @@ var _ = Describe("SentPacketHandler", func() {
ack = frames.AckFrame{
LargestObserved: 3,
}
_, _, _, err = handler.ReceivedAck(&ack)
err = handler.ReceivedAck(&ack)
Expect(err).NotTo(HaveOccurred())
Expect(handler.BytesInFlight()).To(Equal(protocol.ByteCount(0)))
})
})
It("returns lost packets in ReceivedAck()", func() {
packet1 := Packet{PacketNumber: 1, Frames: []frames.Frame{&streamFrame}, EntropyBit: false, Length: 1}
packet2 := Packet{PacketNumber: 2, Frames: []frames.Frame{&streamFrame}, EntropyBit: false, Length: 2}
err := handler.SentPacket(&packet1)
Expect(err).NotTo(HaveOccurred())
err = handler.SentPacket(&packet2)
Expect(err).NotTo(HaveOccurred())
Context("congestion", func() {
var (
cong *mockCongestion
)
// First, simulate a NACK for packet number 1
handler.nackPacket(1)
// Now, simulate an ack frame
ack := &frames.AckFrame{
LargestObserved: 2,
NackRanges: []frames.NackRange{{FirstPacketNumber: 1, LastPacketNumber: 1}},
}
_, acked, lost, err := handler.ReceivedAck(ack)
Expect(err).NotTo(HaveOccurred())
Expect(acked).To(HaveLen(1))
Expect(acked[0].PacketNumber).To(Equal(protocol.PacketNumber(2)))
Expect(lost).To(HaveLen(1))
Expect(lost[0].PacketNumber).To(Equal(protocol.PacketNumber(1)))
BeforeEach(func() {
cong = &mockCongestion{}
handler.congestion = cong
})
It("should call OnSent", func() {
p := &Packet{
PacketNumber: 1,
Frames: []frames.Frame{&frames.StreamFrame{StreamID: 5}},
Length: 42,
}
err := handler.SentPacket(p)
Expect(err).NotTo(HaveOccurred())
Expect(cong.nCalls).To(Equal(1))
Expect(cong.argsOnPacketSent[1]).To(Equal(protocol.ByteCount(42)))
Expect(cong.argsOnPacketSent[2]).To(Equal(protocol.PacketNumber(1)))
Expect(cong.argsOnPacketSent[3]).To(Equal(protocol.ByteCount(42)))
Expect(cong.argsOnPacketSent[4]).To(BeTrue())
})
It("should call OnCongestionEvent", 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})
err := handler.ReceivedAck(&frames.AckFrame{
LargestObserved: 3,
NackRanges: []frames.NackRange{{2, 2}},
})
Expect(err).NotTo(HaveOccurred())
Expect(cong.nCalls).To(Equal(4)) // 3 * SentPacket + 1 * ReceivedAck
// rttUpdated, bytesInFlight, ackedPackets, lostPackets
Expect(cong.argsOnCongestionEvent[0]).To(BeTrue())
Expect(cong.argsOnCongestionEvent[1]).To(Equal(protocol.ByteCount(2)))
Expect(cong.argsOnCongestionEvent[2]).To(Equal(congestion.PacketVector{{1, 1}, {3, 3}}))
Expect(cong.argsOnCongestionEvent[3]).To(BeEmpty())
// Loose the packet
handler.SentPacket(&Packet{PacketNumber: 4, Frames: []frames.Frame{}, Length: 4})
err = handler.ReceivedAck(&frames.AckFrame{
LargestObserved: 4,
NackRanges: []frames.NackRange{{2, 2}},
})
Expect(err).NotTo(HaveOccurred())
Expect(cong.argsOnCongestionEvent[2]).To(Equal(congestion.PacketVector{{4, 4}}))
Expect(cong.argsOnCongestionEvent[3]).To(Equal(congestion.PacketVector{{2, 2}}))
})
It("allows or denies sending", func() {
Expect(handler.AllowsSending()).To(BeTrue())
err := handler.SentPacket(&Packet{PacketNumber: 1, Frames: []frames.Frame{}, Length: protocol.DefaultTCPMSS + 1})
Expect(err).NotTo(HaveOccurred())
Expect(handler.AllowsSending()).To(BeFalse())
})
})
})