| // Copyright 2019 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/third_party/quiche/src/quic/core/uber_received_packet_manager.h" |
| |
| #include "net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h" |
| #include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h" |
| #include "net/third_party/quiche/src/quic/core/quic_connection_stats.h" |
| #include "net/third_party/quiche/src/quic/core/quic_utils.h" |
| #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" |
| #include "net/third_party/quiche/src/quic/platform/api/quic_test.h" |
| #include "net/third_party/quiche/src/quic/test_tools/mock_clock.h" |
| |
| namespace quic { |
| namespace test { |
| |
| class UberReceivedPacketManagerPeer { |
| public: |
| static void SetAckMode(UberReceivedPacketManager* manager, AckMode ack_mode) { |
| for (auto& received_packet_manager : manager->received_packet_managers_) { |
| received_packet_manager.ack_mode_ = ack_mode; |
| } |
| } |
| |
| static void SetFastAckAfterQuiescence(UberReceivedPacketManager* manager, |
| bool fast_ack_after_quiescence) { |
| for (auto& received_packet_manager : manager->received_packet_managers_) { |
| received_packet_manager.fast_ack_after_quiescence_ = |
| fast_ack_after_quiescence; |
| } |
| } |
| |
| static void SetAckDecimationDelay(UberReceivedPacketManager* manager, |
| float ack_decimation_delay) { |
| for (auto& received_packet_manager : manager->received_packet_managers_) { |
| received_packet_manager.ack_decimation_delay_ = ack_decimation_delay; |
| } |
| } |
| }; |
| |
| namespace { |
| |
| const bool kInstigateAck = true; |
| const QuicTime::Delta kMinRttMs = QuicTime::Delta::FromMilliseconds(40); |
| const QuicTime::Delta kDelayedAckTime = |
| QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); |
| |
| class UberReceivedPacketManagerTest : public QuicTest { |
| protected: |
| UberReceivedPacketManagerTest() { |
| manager_ = QuicMakeUnique<UberReceivedPacketManager>(&stats_); |
| clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); |
| rtt_stats_.UpdateRtt(kMinRttMs, QuicTime::Delta::Zero(), QuicTime::Zero()); |
| manager_->set_save_timestamps(true); |
| } |
| |
| void RecordPacketReceipt(uint64_t packet_number) { |
| RecordPacketReceipt(ENCRYPTION_FORWARD_SECURE, packet_number); |
| } |
| |
| void RecordPacketReceipt(uint64_t packet_number, QuicTime receipt_time) { |
| RecordPacketReceipt(ENCRYPTION_FORWARD_SECURE, packet_number, receipt_time); |
| } |
| |
| void RecordPacketReceipt(EncryptionLevel decrypted_packet_level, |
| uint64_t packet_number) { |
| RecordPacketReceipt(decrypted_packet_level, packet_number, |
| QuicTime::Zero()); |
| } |
| |
| void RecordPacketReceipt(EncryptionLevel decrypted_packet_level, |
| uint64_t packet_number, |
| QuicTime receipt_time) { |
| QuicPacketHeader header; |
| header.packet_number = QuicPacketNumber(packet_number); |
| manager_->RecordPacketReceived(decrypted_packet_level, header, |
| receipt_time); |
| } |
| |
| bool HasPendingAck() { |
| if (!manager_->supports_multiple_packet_number_spaces()) { |
| return manager_->GetAckTimeout(APPLICATION_DATA).IsInitialized(); |
| } |
| return manager_->GetEarliestAckTimeout().IsInitialized(); |
| } |
| |
| void MaybeUpdateAckTimeout(bool should_last_packet_instigate_acks, |
| uint64_t last_received_packet_number) { |
| MaybeUpdateAckTimeout(should_last_packet_instigate_acks, |
| ENCRYPTION_FORWARD_SECURE, |
| last_received_packet_number); |
| } |
| |
| void MaybeUpdateAckTimeout(bool should_last_packet_instigate_acks, |
| EncryptionLevel decrypted_packet_level, |
| uint64_t last_received_packet_number) { |
| manager_->MaybeUpdateAckTimeout( |
| should_last_packet_instigate_acks, decrypted_packet_level, |
| QuicPacketNumber(last_received_packet_number), clock_.ApproximateNow(), |
| clock_.ApproximateNow(), &rtt_stats_, kDelayedAckTime); |
| } |
| |
| void CheckAckTimeout(QuicTime time) { |
| DCHECK(HasPendingAck()); |
| if (!manager_->supports_multiple_packet_number_spaces()) { |
| DCHECK(manager_->GetAckTimeout(APPLICATION_DATA) == time); |
| if (time <= clock_.ApproximateNow()) { |
| // ACK timeout expires, send an ACK. |
| manager_->ResetAckStates(ENCRYPTION_FORWARD_SECURE); |
| DCHECK(!HasPendingAck()); |
| } |
| return; |
| } |
| DCHECK(manager_->GetEarliestAckTimeout() == time); |
| // Send all expired ACKs. |
| for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) { |
| const QuicTime ack_timeout = |
| manager_->GetAckTimeout(static_cast<PacketNumberSpace>(i)); |
| if (!ack_timeout.IsInitialized() || |
| ack_timeout > clock_.ApproximateNow()) { |
| continue; |
| } |
| manager_->ResetAckStates( |
| QuicUtils::GetEncryptionLevel(static_cast<PacketNumberSpace>(i))); |
| } |
| } |
| |
| MockClock clock_; |
| RttStats rtt_stats_; |
| QuicConnectionStats stats_; |
| std::unique_ptr<UberReceivedPacketManager> manager_; |
| }; |
| |
| TEST_F(UberReceivedPacketManagerTest, DontWaitForPacketsBefore) { |
| RecordPacketReceipt(2); |
| RecordPacketReceipt(7); |
| EXPECT_TRUE(manager_->IsAwaitingPacket(ENCRYPTION_FORWARD_SECURE, |
| QuicPacketNumber(3u))); |
| EXPECT_TRUE(manager_->IsAwaitingPacket(ENCRYPTION_FORWARD_SECURE, |
| QuicPacketNumber(6u))); |
| manager_->DontWaitForPacketsBefore(ENCRYPTION_FORWARD_SECURE, |
| QuicPacketNumber(4)); |
| EXPECT_FALSE(manager_->IsAwaitingPacket(ENCRYPTION_FORWARD_SECURE, |
| QuicPacketNumber(3u))); |
| EXPECT_TRUE(manager_->IsAwaitingPacket(ENCRYPTION_FORWARD_SECURE, |
| QuicPacketNumber(6u))); |
| } |
| |
| TEST_F(UberReceivedPacketManagerTest, GetUpdatedAckFrame) { |
| QuicTime two_ms = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(2); |
| EXPECT_FALSE(manager_->IsAckFrameUpdated()); |
| RecordPacketReceipt(2, two_ms); |
| EXPECT_TRUE(manager_->IsAckFrameUpdated()); |
| |
| QuicFrame ack = |
| manager_->GetUpdatedAckFrame(APPLICATION_DATA, QuicTime::Zero()); |
| manager_->ResetAckStates(ENCRYPTION_FORWARD_SECURE); |
| EXPECT_FALSE(manager_->IsAckFrameUpdated()); |
| // When UpdateReceivedPacketInfo with a time earlier than the time of the |
| // largest observed packet, make sure that the delta is 0, not negative. |
| EXPECT_EQ(QuicTime::Delta::Zero(), ack.ack_frame->ack_delay_time); |
| EXPECT_EQ(1u, ack.ack_frame->received_packet_times.size()); |
| |
| QuicTime four_ms = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(4); |
| ack = manager_->GetUpdatedAckFrame(APPLICATION_DATA, four_ms); |
| manager_->ResetAckStates(ENCRYPTION_FORWARD_SECURE); |
| EXPECT_FALSE(manager_->IsAckFrameUpdated()); |
| // When UpdateReceivedPacketInfo after not having received a new packet, |
| // the delta should still be accurate. |
| EXPECT_EQ(QuicTime::Delta::FromMilliseconds(2), |
| ack.ack_frame->ack_delay_time); |
| // And received packet times won't have change. |
| EXPECT_EQ(1u, ack.ack_frame->received_packet_times.size()); |
| |
| RecordPacketReceipt(999, two_ms); |
| RecordPacketReceipt(4, two_ms); |
| RecordPacketReceipt(1000, two_ms); |
| EXPECT_TRUE(manager_->IsAckFrameUpdated()); |
| ack = manager_->GetUpdatedAckFrame(APPLICATION_DATA, two_ms); |
| manager_->ResetAckStates(ENCRYPTION_FORWARD_SECURE); |
| EXPECT_FALSE(manager_->IsAckFrameUpdated()); |
| // UpdateReceivedPacketInfo should discard any times which can't be |
| // expressed on the wire. |
| EXPECT_EQ(2u, ack.ack_frame->received_packet_times.size()); |
| } |
| |
| TEST_F(UberReceivedPacketManagerTest, UpdateReceivedConnectionStats) { |
| EXPECT_FALSE(manager_->IsAckFrameUpdated()); |
| RecordPacketReceipt(1); |
| EXPECT_TRUE(manager_->IsAckFrameUpdated()); |
| RecordPacketReceipt(6); |
| RecordPacketReceipt(2, |
| QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(1)); |
| |
| EXPECT_EQ(4u, stats_.max_sequence_reordering); |
| EXPECT_EQ(1000, stats_.max_time_reordering_us); |
| EXPECT_EQ(1u, stats_.packets_reordered); |
| } |
| |
| TEST_F(UberReceivedPacketManagerTest, LimitAckRanges) { |
| manager_->set_max_ack_ranges(10); |
| EXPECT_FALSE(manager_->IsAckFrameUpdated()); |
| for (int i = 0; i < 100; ++i) { |
| RecordPacketReceipt(1 + 2 * i); |
| EXPECT_TRUE(manager_->IsAckFrameUpdated()); |
| manager_->GetUpdatedAckFrame(APPLICATION_DATA, QuicTime::Zero()); |
| EXPECT_GE(10u, manager_->ack_frame().packets.NumIntervals()); |
| EXPECT_EQ(QuicPacketNumber(1u + 2 * i), |
| manager_->ack_frame().packets.Max()); |
| for (int j = 0; j < std::min(10, i + 1); ++j) { |
| ASSERT_GE(i, j); |
| EXPECT_TRUE(manager_->ack_frame().packets.Contains( |
| QuicPacketNumber(1 + (i - j) * 2))); |
| if (i > j) { |
| EXPECT_FALSE(manager_->ack_frame().packets.Contains( |
| QuicPacketNumber((i - j) * 2))); |
| } |
| } |
| } |
| } |
| |
| TEST_F(UberReceivedPacketManagerTest, IgnoreOutOfOrderTimestamps) { |
| EXPECT_FALSE(manager_->IsAckFrameUpdated()); |
| RecordPacketReceipt(1, QuicTime::Zero()); |
| EXPECT_TRUE(manager_->IsAckFrameUpdated()); |
| EXPECT_EQ(1u, manager_->ack_frame().received_packet_times.size()); |
| RecordPacketReceipt(2, |
| QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(1)); |
| EXPECT_EQ(2u, manager_->ack_frame().received_packet_times.size()); |
| RecordPacketReceipt(3, QuicTime::Zero()); |
| EXPECT_EQ(2u, manager_->ack_frame().received_packet_times.size()); |
| } |
| |
| TEST_F(UberReceivedPacketManagerTest, OutOfOrderReceiptCausesAckSent) { |
| EXPECT_FALSE(HasPendingAck()); |
| |
| RecordPacketReceipt(3, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, 3); |
| // Delayed ack is scheduled. |
| CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime); |
| |
| RecordPacketReceipt(2, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, 2); |
| CheckAckTimeout(clock_.ApproximateNow()); |
| |
| RecordPacketReceipt(1, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, 1); |
| // Should ack immediately, since this fills the last hole. |
| CheckAckTimeout(clock_.ApproximateNow()); |
| |
| RecordPacketReceipt(4, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, 4); |
| // Delayed ack is scheduled. |
| CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime); |
| } |
| |
| TEST_F(UberReceivedPacketManagerTest, OutOfOrderAckReceiptCausesNoAck) { |
| EXPECT_FALSE(HasPendingAck()); |
| |
| RecordPacketReceipt(2, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(!kInstigateAck, 2); |
| EXPECT_FALSE(HasPendingAck()); |
| |
| RecordPacketReceipt(1, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(!kInstigateAck, 1); |
| EXPECT_FALSE(HasPendingAck()); |
| } |
| |
| TEST_F(UberReceivedPacketManagerTest, AckReceiptCausesAckSend) { |
| EXPECT_FALSE(HasPendingAck()); |
| |
| RecordPacketReceipt(1, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(!kInstigateAck, 1); |
| EXPECT_FALSE(HasPendingAck()); |
| |
| RecordPacketReceipt(2, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(!kInstigateAck, 2); |
| EXPECT_FALSE(HasPendingAck()); |
| |
| RecordPacketReceipt(3, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, 3); |
| // Delayed ack is scheduled. |
| CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime); |
| clock_.AdvanceTime(kDelayedAckTime); |
| CheckAckTimeout(clock_.ApproximateNow()); |
| |
| RecordPacketReceipt(4, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(!kInstigateAck, 4); |
| EXPECT_FALSE(HasPendingAck()); |
| |
| RecordPacketReceipt(5, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(!kInstigateAck, 5); |
| EXPECT_FALSE(HasPendingAck()); |
| } |
| |
| TEST_F(UberReceivedPacketManagerTest, AckSentEveryNthPacket) { |
| EXPECT_FALSE(HasPendingAck()); |
| manager_->set_ack_frequency_before_ack_decimation(3); |
| |
| // Receives packets 1 - 39. |
| for (size_t i = 1; i <= 39; ++i) { |
| RecordPacketReceipt(i, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, i); |
| if (i % 3 == 0) { |
| CheckAckTimeout(clock_.ApproximateNow()); |
| } else { |
| CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime); |
| } |
| } |
| } |
| |
| TEST_F(UberReceivedPacketManagerTest, AckDecimationReducesAcks) { |
| EXPECT_FALSE(HasPendingAck()); |
| UberReceivedPacketManagerPeer::SetAckMode(manager_.get(), |
| ACK_DECIMATION_WITH_REORDERING); |
| |
| // Start ack decimation from 10th packet. |
| manager_->set_min_received_before_ack_decimation(10); |
| |
| // Receives packets 1 - 29. |
| for (size_t i = 1; i <= 29; ++i) { |
| RecordPacketReceipt(i, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, i); |
| if (i <= 10) { |
| // For packets 1-10, ack every 2 packets. |
| if (i % 2 == 0) { |
| CheckAckTimeout(clock_.ApproximateNow()); |
| } else { |
| CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime); |
| } |
| continue; |
| } |
| // ack at 20. |
| if (i == 20) { |
| CheckAckTimeout(clock_.ApproximateNow()); |
| } else { |
| CheckAckTimeout(clock_.ApproximateNow() + kMinRttMs * 0.25); |
| } |
| } |
| |
| // We now receive the 30th packet, and so we send an ack. |
| RecordPacketReceipt(30, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, 30); |
| CheckAckTimeout(clock_.ApproximateNow()); |
| } |
| |
| TEST_F(UberReceivedPacketManagerTest, SendDelayedAfterQuiescence) { |
| EXPECT_FALSE(HasPendingAck()); |
| UberReceivedPacketManagerPeer::SetFastAckAfterQuiescence(manager_.get(), |
| true); |
| // The beginning of the connection counts as quiescence. |
| QuicTime ack_time = |
| clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(1); |
| |
| RecordPacketReceipt(1, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, 1); |
| CheckAckTimeout(ack_time); |
| // Simulate delayed ack alarm firing. |
| clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); |
| CheckAckTimeout(clock_.ApproximateNow()); |
| |
| // Process another packet immediately after sending the ack and expect the |
| // ack timeout to be set delayed ack time in the future. |
| ack_time = clock_.ApproximateNow() + kDelayedAckTime; |
| RecordPacketReceipt(2, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, 2); |
| CheckAckTimeout(ack_time); |
| // Simulate delayed ack alarm firing. |
| clock_.AdvanceTime(kDelayedAckTime); |
| CheckAckTimeout(clock_.ApproximateNow()); |
| |
| // Wait 1 second and enesure the ack timeout is set to 1ms in the future. |
| clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); |
| ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(1); |
| RecordPacketReceipt(3, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, 3); |
| CheckAckTimeout(ack_time); |
| } |
| |
| TEST_F(UberReceivedPacketManagerTest, SendDelayedAckDecimation) { |
| EXPECT_FALSE(HasPendingAck()); |
| UberReceivedPacketManagerPeer::SetAckMode(manager_.get(), ACK_DECIMATION); |
| // The ack time should be based on min_rtt * 1/4, since it's less than the |
| // default delayed ack time. |
| QuicTime ack_time = clock_.ApproximateNow() + kMinRttMs * 0.25; |
| |
| // Process all the packets in order so there aren't missing packets. |
| uint64_t kFirstDecimatedPacket = 101; |
| for (uint64_t i = 1; i < kFirstDecimatedPacket; ++i) { |
| RecordPacketReceipt(i, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, i); |
| if (i % 2 == 0) { |
| // Ack every 2 packets by default. |
| CheckAckTimeout(clock_.ApproximateNow()); |
| } else { |
| CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime); |
| } |
| } |
| |
| RecordPacketReceipt(kFirstDecimatedPacket, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket); |
| CheckAckTimeout(ack_time); |
| |
| // The 10th received packet causes an ack to be sent. |
| for (uint64_t i = 1; i < 10; ++i) { |
| RecordPacketReceipt(kFirstDecimatedPacket + i, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + i); |
| } |
| CheckAckTimeout(clock_.ApproximateNow()); |
| } |
| |
| TEST_F(UberReceivedPacketManagerTest, |
| SendDelayedAckAckDecimationAfterQuiescence) { |
| EXPECT_FALSE(HasPendingAck()); |
| UberReceivedPacketManagerPeer::SetAckMode(manager_.get(), ACK_DECIMATION); |
| UberReceivedPacketManagerPeer::SetFastAckAfterQuiescence(manager_.get(), |
| true); |
| // The beginning of the connection counts as quiescence. |
| QuicTime ack_time = |
| clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(1); |
| RecordPacketReceipt(1, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, 1); |
| CheckAckTimeout(ack_time); |
| // Simulate delayed ack alarm firing. |
| clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); |
| CheckAckTimeout(clock_.ApproximateNow()); |
| |
| // Process another packet immedately after sending the ack and expect the |
| // ack timeout to be set delayed ack time in the future. |
| ack_time = clock_.ApproximateNow() + kDelayedAckTime; |
| RecordPacketReceipt(2, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, 2); |
| CheckAckTimeout(ack_time); |
| // Simulate delayed ack alarm firing. |
| clock_.AdvanceTime(kDelayedAckTime); |
| CheckAckTimeout(clock_.ApproximateNow()); |
| |
| // Wait 1 second and enesure the ack timeout is set to 1ms in the future. |
| clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); |
| ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(1); |
| RecordPacketReceipt(3, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, 3); |
| CheckAckTimeout(ack_time); |
| // Process enough packets to get into ack decimation behavior. |
| // The ack time should be based on min_rtt/4, since it's less than the |
| // default delayed ack time. |
| ack_time = clock_.ApproximateNow() + kMinRttMs * 0.25; |
| uint64_t kFirstDecimatedPacket = 101; |
| for (uint64_t i = 4; i < kFirstDecimatedPacket; ++i) { |
| RecordPacketReceipt(i, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, i); |
| if (i % 2 == 0) { |
| // Ack every 2 packets by default. |
| CheckAckTimeout(clock_.ApproximateNow()); |
| } else { |
| CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime); |
| } |
| } |
| EXPECT_FALSE(HasPendingAck()); |
| RecordPacketReceipt(kFirstDecimatedPacket, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket); |
| CheckAckTimeout(ack_time); |
| |
| // The 10th received packet causes an ack to be sent. |
| for (uint64_t i = 1; i < 10; ++i) { |
| RecordPacketReceipt(kFirstDecimatedPacket + i, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + i); |
| } |
| CheckAckTimeout(clock_.ApproximateNow()); |
| |
| // Wait 1 second and enesure the ack timeout is set to 1ms in the future. |
| clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); |
| ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(1); |
| RecordPacketReceipt(kFirstDecimatedPacket + 10, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + 10); |
| CheckAckTimeout(ack_time); |
| } |
| |
| TEST_F(UberReceivedPacketManagerTest, |
| SendDelayedAckDecimationUnlimitedAggregation) { |
| EXPECT_FALSE(HasPendingAck()); |
| QuicConfig config; |
| QuicTagVector connection_options; |
| connection_options.push_back(kACKD); |
| // No limit on the number of packets received before sending an ack. |
| connection_options.push_back(kAKDU); |
| config.SetConnectionOptionsToSend(connection_options); |
| manager_->SetFromConfig(config, Perspective::IS_CLIENT); |
| |
| // The ack time should be based on min_rtt/4, since it's less than the |
| // default delayed ack time. |
| QuicTime ack_time = clock_.ApproximateNow() + kMinRttMs * 0.25; |
| |
| // Process all the initial packets in order so there aren't missing packets. |
| uint64_t kFirstDecimatedPacket = 101; |
| for (uint64_t i = 1; i < kFirstDecimatedPacket; ++i) { |
| RecordPacketReceipt(i, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, i); |
| if (i % 2 == 0) { |
| // Ack every 2 packets by default. |
| CheckAckTimeout(clock_.ApproximateNow()); |
| } else { |
| CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime); |
| } |
| } |
| |
| RecordPacketReceipt(kFirstDecimatedPacket, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket); |
| CheckAckTimeout(ack_time); |
| |
| // 18 packets will not cause an ack to be sent. 19 will because when |
| // stop waiting frames are in use, we ack every 20 packets no matter what. |
| for (int i = 1; i <= 18; ++i) { |
| RecordPacketReceipt(kFirstDecimatedPacket + i, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + i); |
| } |
| CheckAckTimeout(ack_time); |
| } |
| |
| TEST_F(UberReceivedPacketManagerTest, SendDelayedAckDecimationEighthRtt) { |
| EXPECT_FALSE(HasPendingAck()); |
| UberReceivedPacketManagerPeer::SetAckMode(manager_.get(), ACK_DECIMATION); |
| UberReceivedPacketManagerPeer::SetAckDecimationDelay(manager_.get(), 0.125); |
| |
| // The ack time should be based on min_rtt/8, since it's less than the |
| // default delayed ack time. |
| QuicTime ack_time = clock_.ApproximateNow() + kMinRttMs * 0.125; |
| |
| // Process all the packets in order so there aren't missing packets. |
| uint64_t kFirstDecimatedPacket = 101; |
| for (uint64_t i = 1; i < kFirstDecimatedPacket; ++i) { |
| RecordPacketReceipt(i, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, i); |
| if (i % 2 == 0) { |
| // Ack every 2 packets by default. |
| CheckAckTimeout(clock_.ApproximateNow()); |
| } else { |
| CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime); |
| } |
| } |
| |
| RecordPacketReceipt(kFirstDecimatedPacket, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket); |
| CheckAckTimeout(ack_time); |
| |
| // The 10th received packet causes an ack to be sent. |
| for (uint64_t i = 1; i < 10; ++i) { |
| RecordPacketReceipt(kFirstDecimatedPacket + i, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + i); |
| } |
| CheckAckTimeout(clock_.ApproximateNow()); |
| } |
| |
| TEST_F(UberReceivedPacketManagerTest, SendDelayedAckDecimationWithReordering) { |
| EXPECT_FALSE(HasPendingAck()); |
| UberReceivedPacketManagerPeer::SetAckMode(manager_.get(), |
| ACK_DECIMATION_WITH_REORDERING); |
| |
| // The ack time should be based on min_rtt/4, since it's less than the |
| // default delayed ack time. |
| QuicTime ack_time = clock_.ApproximateNow() + kMinRttMs * 0.25; |
| // Process all the packets in order so there aren't missing packets. |
| uint64_t kFirstDecimatedPacket = 101; |
| for (uint64_t i = 1; i < kFirstDecimatedPacket; ++i) { |
| RecordPacketReceipt(i, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, i); |
| if (i % 2 == 0) { |
| // Ack every 2 packets by default. |
| CheckAckTimeout(clock_.ApproximateNow()); |
| } else { |
| CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime); |
| } |
| } |
| |
| // Receive one packet out of order and then the rest in order. |
| // The loop leaves a one packet gap between acks sent to simulate some loss. |
| for (int j = 0; j < 3; ++j) { |
| // Process packet 10 first and ensure the timeout is one eighth min_rtt. |
| RecordPacketReceipt(kFirstDecimatedPacket + 9 + (j * 11), |
| clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + 9 + (j * 11)); |
| ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(5); |
| CheckAckTimeout(ack_time); |
| |
| // The 10th received packet causes an ack to be sent. |
| for (int i = 0; i < 9; ++i) { |
| RecordPacketReceipt(kFirstDecimatedPacket + i + (j * 11), |
| clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, |
| kFirstDecimatedPacket + i + (j * 11)); |
| } |
| CheckAckTimeout(clock_.ApproximateNow()); |
| } |
| } |
| |
| TEST_F(UberReceivedPacketManagerTest, |
| SendDelayedAckDecimationWithLargeReordering) { |
| EXPECT_FALSE(HasPendingAck()); |
| UberReceivedPacketManagerPeer::SetAckMode(manager_.get(), |
| ACK_DECIMATION_WITH_REORDERING); |
| // The ack time should be based on min_rtt/4, since it's less than the |
| // default delayed ack time. |
| QuicTime ack_time = clock_.ApproximateNow() + kMinRttMs * 0.25; |
| |
| // Process all the packets in order so there aren't missing packets. |
| uint64_t kFirstDecimatedPacket = 101; |
| for (uint64_t i = 1; i < kFirstDecimatedPacket; ++i) { |
| RecordPacketReceipt(i, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, i); |
| if (i % 2 == 0) { |
| // Ack every 2 packets by default. |
| CheckAckTimeout(clock_.ApproximateNow()); |
| } else { |
| CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime); |
| } |
| } |
| |
| RecordPacketReceipt(kFirstDecimatedPacket, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket); |
| CheckAckTimeout(ack_time); |
| |
| RecordPacketReceipt(kFirstDecimatedPacket + 19, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + 19); |
| ack_time = clock_.ApproximateNow() + kMinRttMs * 0.125; |
| CheckAckTimeout(ack_time); |
| |
| // The 10th received packet causes an ack to be sent. |
| for (int i = 1; i < 9; ++i) { |
| RecordPacketReceipt(kFirstDecimatedPacket + i, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + i); |
| } |
| CheckAckTimeout(clock_.ApproximateNow()); |
| |
| // The next packet received in order will cause an immediate ack, because it |
| // fills a hole. |
| RecordPacketReceipt(kFirstDecimatedPacket + 10, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + 10); |
| CheckAckTimeout(clock_.ApproximateNow()); |
| } |
| |
| TEST_F(UberReceivedPacketManagerTest, |
| SendDelayedAckDecimationWithReorderingEighthRtt) { |
| EXPECT_FALSE(HasPendingAck()); |
| UberReceivedPacketManagerPeer::SetAckMode(manager_.get(), |
| ACK_DECIMATION_WITH_REORDERING); |
| UberReceivedPacketManagerPeer::SetAckDecimationDelay(manager_.get(), 0.125); |
| // The ack time should be based on min_rtt/8, since it's less than the |
| // default delayed ack time. |
| QuicTime ack_time = clock_.ApproximateNow() + kMinRttMs * 0.125; |
| |
| // Process all the packets in order so there aren't missing packets. |
| uint64_t kFirstDecimatedPacket = 101; |
| for (uint64_t i = 1; i < kFirstDecimatedPacket; ++i) { |
| RecordPacketReceipt(i, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, i); |
| if (i % 2 == 0) { |
| // Ack every 2 packets by default. |
| CheckAckTimeout(clock_.ApproximateNow()); |
| } else { |
| CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime); |
| } |
| } |
| |
| RecordPacketReceipt(kFirstDecimatedPacket, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket); |
| CheckAckTimeout(ack_time); |
| |
| // Process packet 10 first and ensure the timeout is one eighth min_rtt. |
| RecordPacketReceipt(kFirstDecimatedPacket + 9, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + 9); |
| CheckAckTimeout(ack_time); |
| |
| // The 10th received packet causes an ack to be sent. |
| for (int i = 1; i < 9; ++i) { |
| RecordPacketReceipt(kFirstDecimatedPacket + i, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck + i, kFirstDecimatedPacket); |
| } |
| CheckAckTimeout(clock_.ApproximateNow()); |
| } |
| |
| TEST_F(UberReceivedPacketManagerTest, |
| SendDelayedAckDecimationWithLargeReorderingEighthRtt) { |
| EXPECT_FALSE(HasPendingAck()); |
| UberReceivedPacketManagerPeer::SetAckMode(manager_.get(), |
| ACK_DECIMATION_WITH_REORDERING); |
| UberReceivedPacketManagerPeer::SetAckDecimationDelay(manager_.get(), 0.125); |
| |
| // The ack time should be based on min_rtt/8, since it's less than the |
| // default delayed ack time. |
| QuicTime ack_time = clock_.ApproximateNow() + kMinRttMs * 0.125; |
| // Process all the packets in order so there aren't missing packets. |
| uint64_t kFirstDecimatedPacket = 101; |
| for (uint64_t i = 1; i < kFirstDecimatedPacket; ++i) { |
| RecordPacketReceipt(i, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, i); |
| if (i % 2 == 0) { |
| // Ack every 2 packets by default. |
| CheckAckTimeout(clock_.ApproximateNow()); |
| } else { |
| CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime); |
| } |
| } |
| |
| RecordPacketReceipt(kFirstDecimatedPacket, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket); |
| CheckAckTimeout(ack_time); |
| |
| RecordPacketReceipt(kFirstDecimatedPacket + 19, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + 19); |
| CheckAckTimeout(ack_time); |
| |
| // The 10th received packet causes an ack to be sent. |
| for (int i = 1; i < 9; ++i) { |
| RecordPacketReceipt(kFirstDecimatedPacket + i, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + i); |
| } |
| CheckAckTimeout(clock_.ApproximateNow()); |
| |
| // The next packet received in order will cause an immediate ack, because it |
| // fills a hole. |
| RecordPacketReceipt(kFirstDecimatedPacket + 10, clock_.ApproximateNow()); |
| MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + 10); |
| CheckAckTimeout(clock_.ApproximateNow()); |
| } |
| |
| TEST_F(UberReceivedPacketManagerTest, |
| DontWaitForPacketsBeforeMultiplePacketNumberSpaces) { |
| manager_->EnableMultiplePacketNumberSpacesSupport(); |
| EXPECT_FALSE( |
| manager_->GetLargestObserved(ENCRYPTION_HANDSHAKE).IsInitialized()); |
| EXPECT_FALSE( |
| manager_->GetLargestObserved(ENCRYPTION_FORWARD_SECURE).IsInitialized()); |
| RecordPacketReceipt(ENCRYPTION_HANDSHAKE, 2); |
| RecordPacketReceipt(ENCRYPTION_HANDSHAKE, 4); |
| RecordPacketReceipt(ENCRYPTION_FORWARD_SECURE, 3); |
| RecordPacketReceipt(ENCRYPTION_FORWARD_SECURE, 7); |
| EXPECT_EQ(QuicPacketNumber(4), |
| manager_->GetLargestObserved(ENCRYPTION_HANDSHAKE)); |
| EXPECT_EQ(QuicPacketNumber(7), |
| manager_->GetLargestObserved(ENCRYPTION_FORWARD_SECURE)); |
| |
| EXPECT_TRUE( |
| manager_->IsAwaitingPacket(ENCRYPTION_HANDSHAKE, QuicPacketNumber(3))); |
| EXPECT_FALSE(manager_->IsAwaitingPacket(ENCRYPTION_FORWARD_SECURE, |
| QuicPacketNumber(3))); |
| EXPECT_TRUE(manager_->IsAwaitingPacket(ENCRYPTION_FORWARD_SECURE, |
| QuicPacketNumber(4))); |
| |
| manager_->DontWaitForPacketsBefore(ENCRYPTION_FORWARD_SECURE, |
| QuicPacketNumber(5)); |
| EXPECT_TRUE( |
| manager_->IsAwaitingPacket(ENCRYPTION_HANDSHAKE, QuicPacketNumber(3))); |
| EXPECT_FALSE(manager_->IsAwaitingPacket(ENCRYPTION_FORWARD_SECURE, |
| QuicPacketNumber(4))); |
| } |
| |
| TEST_F(UberReceivedPacketManagerTest, AckSendingDifferentPacketNumberSpaces) { |
| manager_->EnableMultiplePacketNumberSpacesSupport(); |
| EXPECT_FALSE(HasPendingAck()); |
| EXPECT_FALSE(manager_->IsAckFrameUpdated()); |
| |
| RecordPacketReceipt(ENCRYPTION_HANDSHAKE, 3); |
| EXPECT_TRUE(manager_->IsAckFrameUpdated()); |
| MaybeUpdateAckTimeout(kInstigateAck, ENCRYPTION_HANDSHAKE, 3); |
| EXPECT_TRUE(HasPendingAck()); |
| // Delayed ack is scheduled. |
| CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime); |
| |
| RecordPacketReceipt(ENCRYPTION_FORWARD_SECURE, 3); |
| MaybeUpdateAckTimeout(kInstigateAck, ENCRYPTION_FORWARD_SECURE, 3); |
| EXPECT_TRUE(HasPendingAck()); |
| // Delayed ack is scheduled. |
| CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime); |
| |
| RecordPacketReceipt(ENCRYPTION_FORWARD_SECURE, 2); |
| MaybeUpdateAckTimeout(kInstigateAck, ENCRYPTION_FORWARD_SECURE, 2); |
| // Application data ACK should be sent immediately. |
| CheckAckTimeout(clock_.ApproximateNow()); |
| // Delayed ACK of handshake data is pending. |
| CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime); |
| |
| // Send delayed handshake data ACK. |
| clock_.AdvanceTime(kDelayedAckTime); |
| CheckAckTimeout(clock_.ApproximateNow()); |
| EXPECT_FALSE(HasPendingAck()); |
| } |
| |
| } // namespace |
| } // namespace test |
| } // namespace quic |