blob: b1e714074d7b6dd0a431730f75c8115cb7256a77 [file] [log] [blame]
// 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 <utility>
#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_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_ = std::make_unique<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_);
}
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, SendDelayedMaxAckDelay) {
EXPECT_FALSE(HasPendingAck());
QuicTime::Delta max_ack_delay = QuicTime::Delta::FromMilliseconds(100);
manager_->set_max_ack_delay(max_ack_delay);
QuicTime ack_time = clock_.ApproximateNow() + max_ack_delay;
RecordPacketReceipt(1, clock_.ApproximateNow());
MaybeUpdateAckTimeout(kInstigateAck, 1);
CheckAckTimeout(ack_time);
// Simulate delayed ack alarm firing.
clock_.AdvanceTime(max_ack_delay);
CheckAckTimeout(clock_.ApproximateNow());
}
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() +
QuicTime::Delta::FromMilliseconds(1));
// Send delayed handshake data ACK.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
CheckAckTimeout(clock_.ApproximateNow());
EXPECT_FALSE(HasPendingAck());
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());
EXPECT_FALSE(HasPendingAck());
}
} // namespace
} // namespace test
} // namespace quic