summaryrefslogtreecommitdiffstats
path: root/net/quic/congestion_control
diff options
context:
space:
mode:
Diffstat (limited to 'net/quic/congestion_control')
-rw-r--r--net/quic/congestion_control/pacing_sender.cc40
-rw-r--r--net/quic/congestion_control/pacing_sender.h4
-rw-r--r--net/quic/congestion_control/pacing_sender_test.cc99
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));