diff options
Diffstat (limited to 'net/quic/congestion_control')
-rw-r--r-- | net/quic/congestion_control/pacing_sender.cc | 40 | ||||
-rw-r--r-- | net/quic/congestion_control/pacing_sender.h | 4 | ||||
-rw-r--r-- | net/quic/congestion_control/pacing_sender_test.cc | 99 |
3 files changed, 94 insertions, 49 deletions
diff --git a/net/quic/congestion_control/pacing_sender.cc b/net/quic/congestion_control/pacing_sender.cc index c487d2a..96f6c62 100644 --- a/net/quic/congestion_control/pacing_sender.cc +++ b/net/quic/congestion_control/pacing_sender.cc @@ -10,6 +10,7 @@ PacingSender::PacingSender(SendAlgorithmInterface* sender, QuicTime::Delta alarm_granularity) : sender_(sender), alarm_granularity_(alarm_granularity), + last_delayed_packet_sent_time_(QuicTime::Zero()), next_packet_send_time_(QuicTime::Zero()), was_last_send_delayed_(false), has_valid_rtt_(false) { @@ -54,7 +55,29 @@ bool PacingSender::OnPacketSent( const float kPacingAggression = 2; QuicTime::Delta delay = BandwidthEstimate().Scale(kPacingAggression).TransferTime(bytes); - next_packet_send_time_ = next_packet_send_time_.Add(delay); + // If the last send was delayed, and the alarm took a long time to get + // invoked, allow the connection to make up for lost time. + if (was_last_send_delayed_) { + next_packet_send_time_ = next_packet_send_time_.Add(delay); + // As long as we're making up time and not application limited, + // continue to consider the packets delayed. + // The send was application limited if it takes longer than the + // pacing delay between sent packets. + const bool application_limited = + last_delayed_packet_sent_time_.IsInitialized() && + sent_time > last_delayed_packet_sent_time_.Add(delay); + const bool making_up_for_lost_time = next_packet_send_time_ > sent_time; + if (making_up_for_lost_time || application_limited) { + was_last_send_delayed_ = false; + last_delayed_packet_sent_time_ = QuicTime::Zero(); + } else { + last_delayed_packet_sent_time_ = sent_time; + } + } else { + next_packet_send_time_ = + QuicTime::Max(next_packet_send_time_.Add(delay), + sent_time.Add(delay).Subtract(alarm_granularity_)); + } } return sender_->OnPacketSent(sent_time, bytes_in_flight, sequence_number, bytes, has_retransmittable_data); @@ -87,25 +110,14 @@ QuicTime::Delta PacingSender::TimeUntilSend( return QuicTime::Delta::Zero(); } - if (!was_last_send_delayed_ && - (!next_packet_send_time_.IsInitialized() || - now > next_packet_send_time_.Add(alarm_granularity_))) { - // An alarm did not go off late, instead the application is "slow" - // delivering data. In this case, we restrict the amount of lost time - // that we can make up for. - next_packet_send_time_ = now.Subtract(alarm_granularity_); - } - - // If the end of the epoch is far enough in the future, delay the send. + // If the next send time is within the alarm granularity, send immediately. if (next_packet_send_time_ > now.Add(alarm_granularity_)) { - was_last_send_delayed_ = true; DVLOG(1) << "Delaying packet: " << next_packet_send_time_.Subtract(now).ToMicroseconds(); + was_last_send_delayed_ = true; return next_packet_send_time_.Subtract(now); } - // Sent it immediately. The epoch end will be adjusted in OnPacketSent. - was_last_send_delayed_ = false; DVLOG(1) << "Sending packet now"; return QuicTime::Delta::Zero(); } diff --git a/net/quic/congestion_control/pacing_sender.h b/net/quic/congestion_control/pacing_sender.h index b1060ac..f7c2622 100644 --- a/net/quic/congestion_control/pacing_sender.h +++ b/net/quic/congestion_control/pacing_sender.h @@ -55,8 +55,10 @@ class NET_EXPORT_PRIVATE PacingSender : public SendAlgorithmInterface { private: scoped_ptr<SendAlgorithmInterface> sender_; // Underlying sender. QuicTime::Delta alarm_granularity_; + // Send time of the last packet considered delayed. + QuicTime last_delayed_packet_sent_time_; QuicTime next_packet_send_time_; // When can the next packet be sent. - bool was_last_send_delayed_; // True when the last send was delayed. + mutable bool was_last_send_delayed_; // True when the last send was delayed. bool has_valid_rtt_; // True if we have at least one RTT update. DISALLOW_COPY_AND_ASSIGN(PacingSender); diff --git a/net/quic/congestion_control/pacing_sender_test.cc b/net/quic/congestion_control/pacing_sender_test.cc index 38e5d02..2dc6960 100644 --- a/net/quic/congestion_control/pacing_sender_test.cc +++ b/net/quic/congestion_control/pacing_sender_test.cc @@ -38,15 +38,17 @@ class PacingSenderTest : public ::testing::Test { void CheckPacketIsSentImmediately() { // In order for the packet to be sendable, the underlying sender must // permit it to be sent immediately. - EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(), - kBytesInFlight, - HAS_RETRANSMITTABLE_DATA)) - .WillOnce(Return(zero_time_)); - // Verify that the packet can be sent immediately. - EXPECT_EQ(zero_time_, - pacing_sender_->TimeUntilSend(clock_.Now(), - kBytesInFlight, - HAS_RETRANSMITTABLE_DATA)); + for (int i = 0; i < 2; ++i) { + EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(), + kBytesInFlight, + HAS_RETRANSMITTABLE_DATA)) + .WillOnce(Return(zero_time_)); + // Verify that the packet can be sent immediately. + EXPECT_EQ(zero_time_, + pacing_sender_->TimeUntilSend(clock_.Now(), + kBytesInFlight, + HAS_RETRANSMITTABLE_DATA)); + } // Actually send the packet. EXPECT_CALL(*mock_sender_, @@ -82,15 +84,17 @@ class PacingSenderTest : public ::testing::Test { void CheckPacketIsDelayed(QuicTime::Delta delay) { // In order for the packet to be sendable, the underlying sender must // permit it to be sent immediately. - EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(), - kBytesInFlight, - HAS_RETRANSMITTABLE_DATA)) - .WillOnce(Return(zero_time_)); - // Verify that the packet is delayed. - EXPECT_EQ(delay.ToMicroseconds(), - pacing_sender_->TimeUntilSend( - clock_.Now(), kBytesInFlight, - HAS_RETRANSMITTABLE_DATA).ToMicroseconds()); + for (int i = 0; i < 2; ++i) { + EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(), + kBytesInFlight, + HAS_RETRANSMITTABLE_DATA)) + .WillOnce(Return(zero_time_)); + // Verify that the packet is delayed. + EXPECT_EQ(delay.ToMicroseconds(), + pacing_sender_->TimeUntilSend( + clock_.Now(), kBytesInFlight, + HAS_RETRANSMITTABLE_DATA).ToMicroseconds()); + } } const QuicTime::Delta zero_time_; @@ -102,25 +106,29 @@ class PacingSenderTest : public ::testing::Test { }; TEST_F(PacingSenderTest, NoSend) { - EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(), - kBytesInFlight, - HAS_RETRANSMITTABLE_DATA)) - .WillOnce(Return(infinite_time_)); - EXPECT_EQ(infinite_time_, - pacing_sender_->TimeUntilSend(clock_.Now(), - kBytesInFlight, - HAS_RETRANSMITTABLE_DATA)); + for (int i = 0; i < 2; ++i) { + EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(), + kBytesInFlight, + HAS_RETRANSMITTABLE_DATA)) + .WillOnce(Return(infinite_time_)); + EXPECT_EQ(infinite_time_, + pacing_sender_->TimeUntilSend(clock_.Now(), + kBytesInFlight, + HAS_RETRANSMITTABLE_DATA)); + } } TEST_F(PacingSenderTest, SendNow) { - EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(), - kBytesInFlight, - HAS_RETRANSMITTABLE_DATA)) - .WillOnce(Return(zero_time_)); - EXPECT_EQ(zero_time_, - pacing_sender_->TimeUntilSend(clock_.Now(), - kBytesInFlight, - HAS_RETRANSMITTABLE_DATA)); + for (int i = 0; i < 2; ++i) { + EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(), + kBytesInFlight, + HAS_RETRANSMITTABLE_DATA)) + .WillOnce(Return(zero_time_)); + EXPECT_EQ(zero_time_, + pacing_sender_->TimeUntilSend(clock_.Now(), + kBytesInFlight, + HAS_RETRANSMITTABLE_DATA)); + } } TEST_F(PacingSenderTest, VariousSending) { @@ -163,6 +171,29 @@ TEST_F(PacingSenderTest, VariousSending) { CheckPacketIsSentImmediately(); CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2)); + // Wake up really late. + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(8)); + CheckPacketIsSentImmediately(); + CheckPacketIsSentImmediately(); + CheckPacketIsSentImmediately(); + CheckPacketIsSentImmediately(); + CheckPacketIsSentImmediately(); + CheckPacketIsSentImmediately(); + CheckPacketIsSentImmediately(); + CheckPacketIsSentImmediately(); + CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2)); + + // Wake up really late again, but application pause partway through. + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(8)); + CheckPacketIsSentImmediately(); + CheckPacketIsSentImmediately(); + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100)); + CheckPacketIsSentImmediately(); + CheckPacketIsSentImmediately(); + CheckPacketIsSentImmediately(); + CheckPacketIsSentImmediately(); + CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2)); + // Wake up too early. CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2)); |