github.com/metacubex/quic-go@v0.44.1-0.20240520163451-20b689a59136/internal/ackhandler/received_packet_tracker_test.go (about) 1 package ackhandler 2 3 import ( 4 "time" 5 6 "github.com/metacubex/quic-go/internal/protocol" 7 "github.com/metacubex/quic-go/internal/utils" 8 "github.com/metacubex/quic-go/internal/wire" 9 10 . "github.com/onsi/ginkgo/v2" 11 . "github.com/onsi/gomega" 12 ) 13 14 var _ = Describe("Received Packet Tracker", func() { 15 var tracker *receivedPacketTracker 16 17 BeforeEach(func() { 18 tracker = newReceivedPacketTracker() 19 }) 20 21 It("acknowledges packets", func() { 22 t := time.Now().Add(-10 * time.Second) 23 Expect(tracker.ReceivedPacket(protocol.PacketNumber(3), protocol.ECNNon, t, true)).To(Succeed()) 24 ack := tracker.GetAckFrame() 25 Expect(ack).ToNot(BeNil()) 26 Expect(ack.AckRanges).To(Equal([]wire.AckRange{{Smallest: 3, Largest: 3}})) 27 Expect(ack.DelayTime).To(BeZero()) 28 // now receive another packet 29 Expect(tracker.ReceivedPacket(protocol.PacketNumber(4), protocol.ECNNon, t.Add(time.Second), true)).To(Succeed()) 30 ack = tracker.GetAckFrame() 31 Expect(ack).ToNot(BeNil()) 32 Expect(ack.AckRanges).To(Equal([]wire.AckRange{{Smallest: 3, Largest: 4}})) 33 Expect(ack.DelayTime).To(BeZero()) 34 }) 35 36 It("also acknowledges delayed packets", func() { 37 t := time.Now().Add(-10 * time.Second) 38 Expect(tracker.ReceivedPacket(protocol.PacketNumber(3), protocol.ECNNon, t, true)).To(Succeed()) 39 ack := tracker.GetAckFrame() 40 Expect(ack).ToNot(BeNil()) 41 Expect(ack.LargestAcked()).To(Equal(protocol.PacketNumber(3))) 42 Expect(ack.LowestAcked()).To(Equal(protocol.PacketNumber(3))) 43 Expect(ack.DelayTime).To(BeZero()) 44 // now receive another packet 45 Expect(tracker.ReceivedPacket(protocol.PacketNumber(1), protocol.ECNNon, t.Add(time.Second), true)).To(Succeed()) 46 ack = tracker.GetAckFrame() 47 Expect(ack).ToNot(BeNil()) 48 Expect(ack.AckRanges).To(HaveLen(2)) 49 Expect(ack.AckRanges).To(ContainElement(wire.AckRange{Smallest: 1, Largest: 1})) 50 Expect(ack.AckRanges).To(ContainElement(wire.AckRange{Smallest: 3, Largest: 3})) 51 Expect(ack.DelayTime).To(BeZero()) 52 }) 53 54 It("doesn't trigger ACKs for non-ack-eliciting packets", func() { 55 t := time.Now().Add(-10 * time.Second) 56 Expect(tracker.ReceivedPacket(protocol.PacketNumber(3), protocol.ECNNon, t, false)).To(Succeed()) 57 Expect(tracker.GetAckFrame()).To(BeNil()) 58 Expect(tracker.ReceivedPacket(protocol.PacketNumber(4), protocol.ECNNon, t.Add(5*time.Second), false)).To(Succeed()) 59 Expect(tracker.GetAckFrame()).To(BeNil()) 60 Expect(tracker.ReceivedPacket(protocol.PacketNumber(5), protocol.ECNNon, t.Add(10*time.Second), true)).To(Succeed()) 61 ack := tracker.GetAckFrame() 62 Expect(ack).ToNot(BeNil()) 63 Expect(ack.AckRanges).To(Equal([]wire.AckRange{{Smallest: 3, Largest: 5}})) 64 }) 65 }) 66 67 var _ = Describe("Application Data Received Packet Tracker", func() { 68 var tracker *appDataReceivedPacketTracker 69 70 BeforeEach(func() { 71 tracker = newAppDataReceivedPacketTracker(utils.DefaultLogger) 72 }) 73 74 Context("accepting packets", func() { 75 It("saves the time when each packet arrived", func() { 76 t := time.Now() 77 Expect(tracker.ReceivedPacket(protocol.PacketNumber(3), protocol.ECNNon, t, true)).To(Succeed()) 78 Expect(tracker.largestObservedRcvdTime).To(Equal(t)) 79 }) 80 81 It("updates the largestObserved and the largestObservedRcvdTime", func() { 82 now := time.Now() 83 tracker.largestObserved = 3 84 tracker.largestObservedRcvdTime = now.Add(-1 * time.Second) 85 Expect(tracker.ReceivedPacket(5, protocol.ECNNon, now, true)).To(Succeed()) 86 Expect(tracker.largestObserved).To(Equal(protocol.PacketNumber(5))) 87 Expect(tracker.largestObservedRcvdTime).To(Equal(now)) 88 }) 89 90 It("doesn't update the largestObserved and the largestObservedRcvdTime for a belated packet", func() { 91 now := time.Now() 92 timestamp := now.Add(-1 * time.Second) 93 tracker.largestObserved = 5 94 tracker.largestObservedRcvdTime = timestamp 95 Expect(tracker.ReceivedPacket(4, protocol.ECNNon, now, true)).To(Succeed()) 96 Expect(tracker.largestObserved).To(Equal(protocol.PacketNumber(5))) 97 Expect(tracker.largestObservedRcvdTime).To(Equal(timestamp)) 98 }) 99 }) 100 101 Context("ACKs", func() { 102 Context("queueing ACKs", func() { 103 // receives and gets ACKs for packet numbers 1 to 10 (including) 104 receiveAndAck10Packets := func() { 105 for i := 1; i <= 10; i++ { 106 Expect(tracker.ReceivedPacket(protocol.PacketNumber(i), protocol.ECNNon, time.Time{}, true)).To(Succeed()) 107 } 108 Expect(tracker.GetAckFrame(true)).ToNot(BeNil()) 109 Expect(tracker.ackQueued).To(BeFalse()) 110 } 111 112 It("always queues an ACK for the first packet", func() { 113 Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) 114 Expect(tracker.ackQueued).To(BeTrue()) 115 Expect(tracker.GetAlarmTimeout()).To(BeZero()) 116 Expect(tracker.GetAckFrame(true).DelayTime).To(BeNumerically("~", 0, time.Second)) 117 }) 118 119 It("works with packet number 0", func() { 120 Expect(tracker.ReceivedPacket(0, protocol.ECNNon, time.Now(), true)).To(Succeed()) 121 Expect(tracker.ackQueued).To(BeTrue()) 122 Expect(tracker.GetAlarmTimeout()).To(BeZero()) 123 Expect(tracker.GetAckFrame(true).DelayTime).To(BeNumerically("~", 0, time.Second)) 124 }) 125 126 It("sets ECN flags", func() { 127 Expect(tracker.ReceivedPacket(0, protocol.ECT0, time.Now(), true)).To(Succeed()) 128 pn := protocol.PacketNumber(1) 129 for i := 0; i < 2; i++ { 130 Expect(tracker.ReceivedPacket(pn, protocol.ECT1, time.Now(), true)).To(Succeed()) 131 pn++ 132 } 133 for i := 0; i < 3; i++ { 134 Expect(tracker.ReceivedPacket(pn, protocol.ECNCE, time.Now(), true)).To(Succeed()) 135 pn++ 136 } 137 ack := tracker.GetAckFrame(false) 138 Expect(ack.ECT0).To(BeEquivalentTo(1)) 139 Expect(ack.ECT1).To(BeEquivalentTo(2)) 140 Expect(ack.ECNCE).To(BeEquivalentTo(3)) 141 }) 142 143 It("queues an ACK for every second ack-eliciting packet", func() { 144 receiveAndAck10Packets() 145 p := protocol.PacketNumber(11) 146 for i := 0; i <= 20; i++ { 147 Expect(tracker.ReceivedPacket(p, protocol.ECNNon, time.Time{}, true)).To(Succeed()) 148 Expect(tracker.ackQueued).To(BeFalse()) 149 p++ 150 Expect(tracker.ReceivedPacket(p, protocol.ECNNon, time.Time{}, true)).To(Succeed()) 151 Expect(tracker.ackQueued).To(BeTrue()) 152 p++ 153 // dequeue the ACK frame 154 Expect(tracker.GetAckFrame(true)).ToNot(BeNil()) 155 } 156 }) 157 158 It("resets the counter when a non-queued ACK frame is generated", func() { 159 receiveAndAck10Packets() 160 rcvTime := time.Now() 161 Expect(tracker.ReceivedPacket(11, protocol.ECNNon, rcvTime, true)).To(Succeed()) 162 Expect(tracker.GetAckFrame(false)).ToNot(BeNil()) 163 Expect(tracker.ReceivedPacket(12, protocol.ECNNon, rcvTime, true)).To(Succeed()) 164 Expect(tracker.GetAckFrame(true)).To(BeNil()) 165 Expect(tracker.ReceivedPacket(13, protocol.ECNNon, rcvTime, true)).To(Succeed()) 166 Expect(tracker.GetAckFrame(false)).ToNot(BeNil()) 167 }) 168 169 It("only sets the timer when receiving a ack-eliciting packets", func() { 170 receiveAndAck10Packets() 171 Expect(tracker.ReceivedPacket(11, protocol.ECNNon, time.Now(), false)).To(Succeed()) 172 Expect(tracker.ackQueued).To(BeFalse()) 173 Expect(tracker.GetAlarmTimeout()).To(BeZero()) 174 rcvTime := time.Now().Add(10 * time.Millisecond) 175 Expect(tracker.ReceivedPacket(12, protocol.ECNNon, rcvTime, true)).To(Succeed()) 176 Expect(tracker.ackQueued).To(BeFalse()) 177 Expect(tracker.GetAlarmTimeout()).To(Equal(rcvTime.Add(protocol.MaxAckDelay))) 178 }) 179 180 It("queues an ACK if the packet was ECN-CE marked", func() { 181 receiveAndAck10Packets() 182 Expect(tracker.ReceivedPacket(11, protocol.ECNCE, time.Now(), true)).To(Succeed()) 183 ack := tracker.GetAckFrame(true) 184 Expect(ack).ToNot(BeNil()) 185 Expect(ack.AckRanges).To(HaveLen(1)) 186 Expect(ack.AckRanges[0].Largest).To(Equal(protocol.PacketNumber(11))) 187 Expect(ack.ECNCE).To(BeEquivalentTo(1)) 188 }) 189 190 It("queues an ACK if it was reported missing before", func() { 191 receiveAndAck10Packets() 192 Expect(tracker.ReceivedPacket(11, protocol.ECNNon, time.Now(), true)).To(Succeed()) 193 Expect(tracker.ReceivedPacket(13, protocol.ECNNon, time.Now(), true)).To(Succeed()) 194 ack := tracker.GetAckFrame(true) // ACK: 1-11 and 13, missing: 12 195 Expect(ack).ToNot(BeNil()) 196 Expect(ack.HasMissingRanges()).To(BeTrue()) 197 Expect(tracker.ackQueued).To(BeFalse()) 198 Expect(tracker.ReceivedPacket(12, protocol.ECNNon, time.Now(), true)).To(Succeed()) 199 Expect(tracker.ackQueued).To(BeTrue()) 200 }) 201 202 It("doesn't recognize in-order packets as out-of-order after raising the threshold", func() { 203 receiveAndAck10Packets() 204 Expect(tracker.lastAck.LargestAcked()).To(Equal(protocol.PacketNumber(10))) 205 Expect(tracker.ackQueued).To(BeFalse()) 206 tracker.IgnoreBelow(11) 207 Expect(tracker.ReceivedPacket(11, protocol.ECNNon, time.Now(), true)).To(Succeed()) 208 Expect(tracker.GetAckFrame(true)).To(BeNil()) 209 }) 210 211 It("recognizes out-of-order packets after raising the threshold", func() { 212 receiveAndAck10Packets() 213 Expect(tracker.lastAck.LargestAcked()).To(Equal(protocol.PacketNumber(10))) 214 Expect(tracker.ackQueued).To(BeFalse()) 215 tracker.IgnoreBelow(11) 216 Expect(tracker.ReceivedPacket(12, protocol.ECNNon, time.Now(), true)).To(Succeed()) 217 ack := tracker.GetAckFrame(true) 218 Expect(ack).ToNot(BeNil()) 219 Expect(ack.AckRanges).To(Equal([]wire.AckRange{{Smallest: 12, Largest: 12}})) 220 }) 221 222 It("doesn't queue an ACK if for non-ack-eliciting packets arriving out-of-order", func() { 223 receiveAndAck10Packets() 224 Expect(tracker.ReceivedPacket(11, protocol.ECNNon, time.Now(), true)).To(Succeed()) 225 Expect(tracker.GetAckFrame(true)).To(BeNil()) 226 Expect(tracker.ReceivedPacket(13, protocol.ECNNon, time.Now(), false)).To(Succeed()) // receive a non-ack-eliciting packet out-of-order 227 Expect(tracker.GetAckFrame(true)).To(BeNil()) 228 }) 229 230 It("doesn't queue an ACK if packets arrive out-of-order, but haven't been acknowledged yet", func() { 231 receiveAndAck10Packets() 232 Expect(tracker.lastAck).ToNot(BeNil()) 233 Expect(tracker.ReceivedPacket(12, protocol.ECNNon, time.Now(), false)).To(Succeed()) 234 Expect(tracker.GetAckFrame(true)).To(BeNil()) 235 // 11 is received out-of-order, but this hasn't been reported in an ACK frame yet 236 Expect(tracker.ReceivedPacket(11, protocol.ECNNon, time.Now(), true)).To(Succeed()) 237 Expect(tracker.GetAckFrame(true)).To(BeNil()) 238 }) 239 }) 240 241 Context("ACK generation", func() { 242 It("generates an ACK for an ack-eliciting packet, if no ACK is queued yet", func() { 243 Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) 244 // The first packet is always acknowledged. 245 Expect(tracker.GetAckFrame(true)).ToNot(BeNil()) 246 }) 247 248 It("doesn't generate ACK for a non-ack-eliciting packet, if no ACK is queued yet", func() { 249 Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) 250 // The first packet is always acknowledged. 251 Expect(tracker.GetAckFrame(true)).ToNot(BeNil()) 252 253 Expect(tracker.ReceivedPacket(2, protocol.ECNNon, time.Now(), false)).To(Succeed()) 254 Expect(tracker.GetAckFrame(false)).To(BeNil()) 255 Expect(tracker.ReceivedPacket(3, protocol.ECNNon, time.Now(), true)).To(Succeed()) 256 ack := tracker.GetAckFrame(false) 257 Expect(ack).ToNot(BeNil()) 258 Expect(ack.LowestAcked()).To(Equal(protocol.PacketNumber(1))) 259 Expect(ack.LargestAcked()).To(Equal(protocol.PacketNumber(3))) 260 }) 261 262 Context("for queued ACKs", func() { 263 BeforeEach(func() { 264 tracker.ackQueued = true 265 }) 266 267 It("generates a simple ACK frame", func() { 268 Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) 269 Expect(tracker.ReceivedPacket(2, protocol.ECNNon, time.Now(), true)).To(Succeed()) 270 ack := tracker.GetAckFrame(true) 271 Expect(ack).ToNot(BeNil()) 272 Expect(ack.LargestAcked()).To(Equal(protocol.PacketNumber(2))) 273 Expect(ack.LowestAcked()).To(Equal(protocol.PacketNumber(1))) 274 Expect(ack.HasMissingRanges()).To(BeFalse()) 275 }) 276 277 It("generates an ACK for packet number 0", func() { 278 Expect(tracker.ReceivedPacket(0, protocol.ECNNon, time.Now(), true)).To(Succeed()) 279 ack := tracker.GetAckFrame(true) 280 Expect(ack).ToNot(BeNil()) 281 Expect(ack.LargestAcked()).To(Equal(protocol.PacketNumber(0))) 282 Expect(ack.LowestAcked()).To(Equal(protocol.PacketNumber(0))) 283 Expect(ack.HasMissingRanges()).To(BeFalse()) 284 }) 285 286 It("sets the delay time", func() { 287 Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) 288 Expect(tracker.ReceivedPacket(2, protocol.ECNNon, time.Now().Add(-1337*time.Millisecond), true)).To(Succeed()) 289 ack := tracker.GetAckFrame(true) 290 Expect(ack).ToNot(BeNil()) 291 Expect(ack.DelayTime).To(BeNumerically("~", 1337*time.Millisecond, 50*time.Millisecond)) 292 }) 293 294 It("uses a 0 delay time if the delay would be negative", func() { 295 Expect(tracker.ReceivedPacket(0, protocol.ECNNon, time.Now().Add(time.Hour), true)).To(Succeed()) 296 ack := tracker.GetAckFrame(true) 297 Expect(ack).ToNot(BeNil()) 298 Expect(ack.DelayTime).To(BeZero()) 299 }) 300 301 It("saves the last sent ACK", func() { 302 Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) 303 ack := tracker.GetAckFrame(true) 304 Expect(ack).ToNot(BeNil()) 305 Expect(tracker.lastAck).To(Equal(ack)) 306 Expect(tracker.ReceivedPacket(2, protocol.ECNNon, time.Now(), true)).To(Succeed()) 307 tracker.ackQueued = true 308 ack = tracker.GetAckFrame(true) 309 Expect(ack).ToNot(BeNil()) 310 Expect(tracker.lastAck).To(Equal(ack)) 311 }) 312 313 It("generates an ACK frame with missing packets", func() { 314 Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) 315 Expect(tracker.ReceivedPacket(4, protocol.ECNNon, time.Now(), true)).To(Succeed()) 316 ack := tracker.GetAckFrame(true) 317 Expect(ack).ToNot(BeNil()) 318 Expect(ack.LargestAcked()).To(Equal(protocol.PacketNumber(4))) 319 Expect(ack.LowestAcked()).To(Equal(protocol.PacketNumber(1))) 320 Expect(ack.AckRanges).To(Equal([]wire.AckRange{ 321 {Smallest: 4, Largest: 4}, 322 {Smallest: 1, Largest: 1}, 323 })) 324 }) 325 326 It("generates an ACK for packet number 0 and other packets", func() { 327 Expect(tracker.ReceivedPacket(0, protocol.ECNNon, time.Now(), true)).To(Succeed()) 328 Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) 329 Expect(tracker.ReceivedPacket(3, protocol.ECNNon, time.Now(), true)).To(Succeed()) 330 ack := tracker.GetAckFrame(true) 331 Expect(ack).ToNot(BeNil()) 332 Expect(ack.LargestAcked()).To(Equal(protocol.PacketNumber(3))) 333 Expect(ack.LowestAcked()).To(Equal(protocol.PacketNumber(0))) 334 Expect(ack.AckRanges).To(Equal([]wire.AckRange{ 335 {Smallest: 3, Largest: 3}, 336 {Smallest: 0, Largest: 1}, 337 })) 338 }) 339 340 It("errors when called with an old packet", func() { 341 tracker.IgnoreBelow(7) 342 Expect(tracker.IsPotentiallyDuplicate(4)).To(BeTrue()) 343 Expect(tracker.ReceivedPacket(4, protocol.ECNNon, time.Now(), true)).To(MatchError("recevedPacketTracker BUG: ReceivedPacket called for old / duplicate packet 4")) 344 }) 345 346 It("deletes packets from the packetHistory when a lower limit is set", func() { 347 for i := 1; i <= 12; i++ { 348 Expect(tracker.ReceivedPacket(protocol.PacketNumber(i), protocol.ECNNon, time.Now(), true)).To(Succeed()) 349 } 350 tracker.IgnoreBelow(7) 351 // check that the packets were deleted from the receivedPacketHistory by checking the values in an ACK frame 352 ack := tracker.GetAckFrame(true) 353 Expect(ack).ToNot(BeNil()) 354 Expect(ack.LargestAcked()).To(Equal(protocol.PacketNumber(12))) 355 Expect(ack.LowestAcked()).To(Equal(protocol.PacketNumber(7))) 356 Expect(ack.HasMissingRanges()).To(BeFalse()) 357 }) 358 359 It("resets all counters needed for the ACK queueing decision when sending an ACK", func() { 360 Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) 361 tracker.ackAlarm = time.Now().Add(-time.Minute) 362 Expect(tracker.GetAckFrame(true)).ToNot(BeNil()) 363 Expect(tracker.GetAlarmTimeout()).To(BeZero()) 364 Expect(tracker.ackElicitingPacketsReceivedSinceLastAck).To(BeZero()) 365 Expect(tracker.ackQueued).To(BeFalse()) 366 }) 367 368 It("doesn't generate an ACK when none is queued and the timer is not set", func() { 369 Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) 370 tracker.ackQueued = false 371 tracker.ackAlarm = time.Time{} 372 Expect(tracker.GetAckFrame(true)).To(BeNil()) 373 }) 374 375 It("doesn't generate an ACK when none is queued and the timer has not yet expired", func() { 376 Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) 377 tracker.ackQueued = false 378 tracker.ackAlarm = time.Now().Add(time.Minute) 379 Expect(tracker.GetAckFrame(true)).To(BeNil()) 380 }) 381 382 It("generates an ACK when the timer has expired", func() { 383 Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) 384 tracker.ackQueued = false 385 tracker.ackAlarm = time.Now().Add(-time.Minute) 386 Expect(tracker.GetAckFrame(true)).ToNot(BeNil()) 387 }) 388 }) 389 }) 390 }) 391 })