summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-20 21:58:10 +0000
committerrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-20 21:58:10 +0000
commit622f947654352f081315f661c74b4bb3a4a30bf9 (patch)
treee6585127a46b7179be6f0b675487be56c769ccec
parent1cefd4b5ac141a1137511b695f4f2f19a8afc086 (diff)
downloadchromium_src-622f947654352f081315f661c74b4bb3a4a30bf9.zip
chromium_src-622f947654352f081315f661c74b4bb3a4a30bf9.tar.gz
chromium_src-622f947654352f081315f661c74b4bb3a4a30bf9.tar.bz2
Land Recent QUIC Changes.
QUIC - fixing lint errors found while sync'ing with server. Merge internal change: 56944792 Fix a QUIC bug where the congestion manager was telling the send algorithm of a loss once one nack was received, but only retransmitted when 3 were received. Merge internal change: 56922588 Enables pacing of QUIC packets, via a new flag. If set, the client will always use pacing, however, the server will only pace if the client negotiates pacing. This allows us to use finch to control the behavior so we can analyze the performance impact. Adds a new FLAGS_use_quic_pacing to enable pacing of QUIC packets. It defaults to false. Merge internal change: 56869575 Move QUIC's rto count from the connection to the congestion manager. Merge internal change: 56787945 Use the packet size of CHLO packets to set the QUIC max_packet_size for the server. Merge internal change: 56758103 Move QUIC's nack counter into QuicCongestionManager from QuicSentPacketManager. Merge internal change: 56746459 Only retransmit the minimum number of packets in QUIC(in TCP's case, 2) when the RTO fires, instead of retransmitting the entire window. Based on conversations with Jana, it appears we should be reducing our congestion window, and the most important mitigation may be implementing a tail loss probe. Merge internal change: 56693737 QUIC - minor cleanup of code (lint errors), found while merging. R=rch@chromium.org Review URL: https://codereview.chromium.org/77613002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@236311 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--net/quic/congestion_control/fix_rate_sender.cc9
-rw-r--r--net/quic/congestion_control/fix_rate_sender.h9
-rw-r--r--net/quic/congestion_control/inter_arrival_sender.cc21
-rw-r--r--net/quic/congestion_control/inter_arrival_sender.h13
-rw-r--r--net/quic/congestion_control/inter_arrival_sender_test.cc2
-rw-r--r--net/quic/congestion_control/pacing_sender.cc51
-rw-r--r--net/quic/congestion_control/pacing_sender.h4
-rw-r--r--net/quic/congestion_control/pacing_sender_test.cc29
-rw-r--r--net/quic/congestion_control/quic_congestion_manager.cc188
-rw-r--r--net/quic/congestion_control/quic_congestion_manager.h44
-rw-r--r--net/quic/congestion_control/quic_congestion_manager_test.cc288
-rw-r--r--net/quic/congestion_control/send_algorithm_interface.cc1
-rw-r--r--net/quic/congestion_control/send_algorithm_interface.h34
-rw-r--r--net/quic/congestion_control/tcp_cubic_sender.cc25
-rw-r--r--net/quic/congestion_control/tcp_cubic_sender.h5
-rw-r--r--net/quic/congestion_control/tcp_cubic_sender_test.cc8
-rw-r--r--net/quic/crypto/crypto_protocol.h2
-rw-r--r--net/quic/quic_config.cc30
-rw-r--r--net/quic/quic_config.h7
-rw-r--r--net/quic/quic_config_test.cc20
-rw-r--r--net/quic/quic_connection.cc87
-rw-r--r--net/quic/quic_connection.h18
-rw-r--r--net/quic/quic_connection_test.cc38
-rw-r--r--net/quic/quic_packet_creator_test.cc19
-rw-r--r--net/quic/quic_protocol.cc1
-rw-r--r--net/quic/quic_sent_packet_manager.cc44
-rw-r--r--net/quic/quic_sent_packet_manager.h14
-rw-r--r--net/quic/quic_sent_packet_manager_test.cc22
-rw-r--r--net/quic/quic_session.h6
-rw-r--r--net/quic/quic_stream_factory.cc2
-rw-r--r--net/quic/test_tools/quic_test_utils.h21
-rw-r--r--net/tools/quic/end_to_end_test.cc124
-rw-r--r--net/tools/quic/quic_client.cc2
-rw-r--r--net/tools/quic/test_tools/quic_test_client.cc11
-rw-r--r--net/tools/quic/test_tools/quic_test_client.h2
35 files changed, 767 insertions, 434 deletions
diff --git a/net/quic/congestion_control/fix_rate_sender.cc b/net/quic/congestion_control/fix_rate_sender.cc
index 3448f9f..4da69bd 100644
--- a/net/quic/congestion_control/fix_rate_sender.cc
+++ b/net/quic/congestion_control/fix_rate_sender.cc
@@ -32,7 +32,10 @@ FixRateSender::~FixRateSender() {
}
void FixRateSender::SetFromConfig(const QuicConfig& config, bool is_server) {
- max_segment_size_ = config.server_max_packet_size();
+}
+
+void FixRateSender::SetMaxPacketSize(QuicByteCount max_packet_size) {
+ max_segment_size_ = max_packet_size;
paced_sender_.set_max_segment_size(max_segment_size_);
}
@@ -65,7 +68,7 @@ void FixRateSender::OnIncomingAck(
latest_rtt_ = rtt;
}
-void FixRateSender::OnIncomingLoss(QuicPacketSequenceNumber /*largest_loss*/,
+void FixRateSender::OnIncomingLoss(QuicPacketSequenceNumber /*sequence_number*/,
QuicTime /*ack_receive_time*/) {
// Ignore losses for fix rate sender.
}
@@ -84,6 +87,8 @@ bool FixRateSender::OnPacketSent(
return true;
}
+void FixRateSender::OnRetransmissionTimeout() { }
+
void FixRateSender::OnPacketAbandoned(
QuicPacketSequenceNumber /*sequence_number*/,
QuicByteCount /*abandoned_bytes*/) {
diff --git a/net/quic/congestion_control/fix_rate_sender.h b/net/quic/congestion_control/fix_rate_sender.h
index aebc1f6..6903695 100644
--- a/net/quic/congestion_control/fix_rate_sender.h
+++ b/net/quic/congestion_control/fix_rate_sender.h
@@ -23,9 +23,9 @@ class NET_EXPORT_PRIVATE FixRateSender : public SendAlgorithmInterface {
explicit FixRateSender(const QuicClock* clock);
virtual ~FixRateSender();
- virtual void SetFromConfig(const QuicConfig& config, bool is_server) OVERRIDE;
-
// Start implementation of SendAlgorithmInterface.
+ virtual void SetFromConfig(const QuicConfig& config, bool is_server) OVERRIDE;
+ virtual void SetMaxPacketSize(QuicByteCount max_packet_size) OVERRIDE;
virtual void OnIncomingQuicCongestionFeedbackFrame(
const QuicCongestionFeedbackFrame& feedback,
QuicTime feedback_receive_time,
@@ -33,14 +33,15 @@ class NET_EXPORT_PRIVATE FixRateSender : public SendAlgorithmInterface {
virtual void OnIncomingAck(QuicPacketSequenceNumber acked_sequence_number,
QuicByteCount acked_bytes,
QuicTime::Delta rtt) OVERRIDE;
- virtual void OnIncomingLoss(QuicPacketSequenceNumber largest_loss,
+ virtual void OnIncomingLoss(QuicPacketSequenceNumber sequence_number,
QuicTime ack_receive_time) OVERRIDE;
virtual bool OnPacketSent(
QuicTime sent_time,
- QuicPacketSequenceNumber equence_number,
+ QuicPacketSequenceNumber sequence_number,
QuicByteCount bytes,
TransmissionType transmission_type,
HasRetransmittableData has_retransmittable_data) OVERRIDE;
+ virtual void OnRetransmissionTimeout() OVERRIDE;
virtual void OnPacketAbandoned(QuicPacketSequenceNumber sequence_number,
QuicByteCount abandoned_bytes) OVERRIDE;
virtual QuicTime::Delta TimeUntilSend(
diff --git a/net/quic/congestion_control/inter_arrival_sender.cc b/net/quic/congestion_control/inter_arrival_sender.cc
index 6b28dae..78a46f3 100644
--- a/net/quic/congestion_control/inter_arrival_sender.cc
+++ b/net/quic/congestion_control/inter_arrival_sender.cc
@@ -46,7 +46,10 @@ InterArrivalSender::~InterArrivalSender() {
void InterArrivalSender::SetFromConfig(const QuicConfig& config,
bool is_server) {
- max_segment_size_ = config.server_max_packet_size();
+}
+
+void InterArrivalSender::SetMaxPacketSize(QuicByteCount max_packet_size) {
+ max_segment_size_ = max_packet_size;
paced_sender_->set_max_segment_size(max_segment_size_);
probe_->set_max_segment_size(max_segment_size_);
}
@@ -70,11 +73,11 @@ QuicBandwidth InterArrivalSender::CalculateSentBandwidth(
QuicTime::Delta max_diff = QuicTime::Delta::Zero();
for (; history_rit != sent_packets_map.rend(); ++history_rit) {
QuicTime::Delta diff =
- feedback_receive_time.Subtract(history_rit->second->SendTimestamp());
+ feedback_receive_time.Subtract(history_rit->second->send_timestamp());
if (diff > kBitrateSmoothingPeriod) {
break;
}
- sum_bytes_sent += history_rit->second->BytesSent();
+ sum_bytes_sent += history_rit->second->bytes_sent();
max_diff = diff;
}
if (max_diff < kMinBitrateSmoothingPeriod) {
@@ -111,8 +114,8 @@ void InterArrivalSender::OnIncomingQuicCongestionFeedbackFrame(
continue;
}
QuicTime time_received = received_it->second;
- QuicTime time_sent = sent_it->second->SendTimestamp();
- QuicByteCount bytes_sent = sent_it->second->BytesSent();
+ QuicTime time_sent = sent_it->second->send_timestamp();
+ QuicByteCount bytes_sent = sent_it->second->bytes_sent();
channel_estimator_->OnAcknowledgedPacket(
sequence_number, bytes_sent, time_sent, time_received);
@@ -126,7 +129,7 @@ void InterArrivalSender::OnIncomingQuicCongestionFeedbackFrame(
// No more sent packets; hence this must be the last.
last_of_send_time = true;
} else {
- if (time_sent != next_sent_it->second->SendTimestamp()) {
+ if (time_sent != next_sent_it->second->send_timestamp()) {
// Next sent packet have a different send time.
last_of_send_time = true;
}
@@ -232,7 +235,7 @@ void InterArrivalSender::OnIncomingAck(
}
void InterArrivalSender::OnIncomingLoss(
- QuicPacketSequenceNumber /*largest_loss*/,
+ QuicPacketSequenceNumber /*sequence_number*/,
QuicTime ack_receive_time) {
// Packet loss was reported.
if (!probing_) {
@@ -258,6 +261,10 @@ bool InterArrivalSender::OnPacketSent(
return true;
}
+void InterArrivalSender::OnRetransmissionTimeout() {
+ // TODO(ianswett): Decrease the available bandwidth.
+}
+
void InterArrivalSender::OnPacketAbandoned(
QuicPacketSequenceNumber /*sequence_number*/,
QuicByteCount abandoned_bytes) {
diff --git a/net/quic/congestion_control/inter_arrival_sender.h b/net/quic/congestion_control/inter_arrival_sender.h
index 6131bbc..bbf4612 100644
--- a/net/quic/congestion_control/inter_arrival_sender.h
+++ b/net/quic/congestion_control/inter_arrival_sender.h
@@ -27,41 +27,36 @@ class NET_EXPORT_PRIVATE InterArrivalSender : public SendAlgorithmInterface {
explicit InterArrivalSender(const QuicClock* clock);
virtual ~InterArrivalSender();
- virtual void SetFromConfig(const QuicConfig& config, bool is_server) OVERRIDE;
-
static QuicBandwidth CalculateSentBandwidth(
const SendAlgorithmInterface::SentPacketsMap& sent_packets_map,
QuicTime feedback_receive_time);
// Start implementation of SendAlgorithmInterface.
+ virtual void SetFromConfig(const QuicConfig& config, bool is_server) OVERRIDE;
+ virtual void SetMaxPacketSize(QuicByteCount max_packet_size) OVERRIDE;
virtual void OnIncomingQuicCongestionFeedbackFrame(
const QuicCongestionFeedbackFrame& feedback,
QuicTime feedback_receive_time,
const SentPacketsMap& sent_packets) OVERRIDE;
-
virtual void OnIncomingAck(QuicPacketSequenceNumber acked_sequence_number,
QuicByteCount acked_bytes,
QuicTime::Delta rtt) OVERRIDE;
-
- virtual void OnIncomingLoss(QuicPacketSequenceNumber largest_loss,
+ virtual void OnIncomingLoss(QuicPacketSequenceNumber sequence_number,
QuicTime ack_receive_time) OVERRIDE;
-
virtual bool OnPacketSent(
QuicTime sent_time,
QuicPacketSequenceNumber sequence_number,
QuicByteCount bytes,
TransmissionType transmission_type,
HasRetransmittableData has_retransmittable_data) OVERRIDE;
-
+ virtual void OnRetransmissionTimeout() OVERRIDE;
virtual void OnPacketAbandoned(QuicPacketSequenceNumber sequence_number,
QuicByteCount abandoned_bytes) OVERRIDE;
-
virtual QuicTime::Delta TimeUntilSend(
QuicTime now,
TransmissionType transmission_type,
HasRetransmittableData has_retransmittable_data,
IsHandshake handshake) OVERRIDE;
-
virtual QuicBandwidth BandwidthEstimate() const OVERRIDE;
virtual QuicTime::Delta SmoothedRtt() const OVERRIDE;
virtual QuicTime::Delta RetransmissionDelay() const OVERRIDE;
diff --git a/net/quic/congestion_control/inter_arrival_sender_test.cc b/net/quic/congestion_control/inter_arrival_sender_test.cc
index d0a7775..1e16163 100644
--- a/net/quic/congestion_control/inter_arrival_sender_test.cc
+++ b/net/quic/congestion_control/inter_arrival_sender_test.cc
@@ -41,7 +41,7 @@ class InterArrivalSenderTest : public ::testing::Test {
QuicByteCount bytes_in_packet = kDefaultMaxPacketSize;
sent_packets_[sequence_number_] =
new class SendAlgorithmInterface::SentPacket(
- bytes_in_packet, send_clock_.Now());
+ bytes_in_packet, send_clock_.Now(), HAS_RETRANSMITTABLE_DATA);
sender_.OnPacketSent(send_clock_.Now(), sequence_number_, bytes_in_packet,
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
diff --git a/net/quic/congestion_control/pacing_sender.cc b/net/quic/congestion_control/pacing_sender.cc
index fa18461..9725a6d 100644
--- a/net/quic/congestion_control/pacing_sender.cc
+++ b/net/quic/congestion_control/pacing_sender.cc
@@ -17,8 +17,12 @@ PacingSender::PacingSender(SendAlgorithmInterface* sender,
PacingSender::~PacingSender() {}
+void PacingSender::SetMaxPacketSize(QuicByteCount max_packet_size) {
+ max_segment_size_ = max_packet_size;
+ sender_->SetMaxPacketSize(max_packet_size);
+}
+
void PacingSender::SetFromConfig(const QuicConfig& config, bool is_server) {
- max_segment_size_ = config.server_max_packet_size();
sender_->SetFromConfig(config, is_server);
}
@@ -37,22 +41,34 @@ void PacingSender::OnIncomingAck(
sender_->OnIncomingAck(acked_sequence_number, acked_bytes, rtt);
}
-void PacingSender::OnIncomingLoss(QuicPacketSequenceNumber largest_loss,
+void PacingSender::OnIncomingLoss(QuicPacketSequenceNumber sequence_number,
QuicTime ack_receive_time) {
- sender_->OnIncomingLoss(largest_loss, ack_receive_time);
+ sender_->OnIncomingLoss(sequence_number, ack_receive_time);
}
-bool PacingSender::OnPacketSent(QuicTime sent_time,
- QuicPacketSequenceNumber sequence_number,
- QuicByteCount bytes,
- TransmissionType transmission_type,
- HasRetransmittableData is_retransmittable) {
- // The next packet should be sent as soon as the current packets has
- // been transferred.
- next_packet_send_time_ =
- next_packet_send_time_.Add(BandwidthEstimate().TransferTime(bytes));
+bool PacingSender::OnPacketSent(
+ QuicTime sent_time,
+ QuicPacketSequenceNumber sequence_number,
+ QuicByteCount bytes,
+ TransmissionType transmission_type,
+ HasRetransmittableData has_retransmittable_data) {
+ // Only pace data packets.
+ if (has_retransmittable_data == HAS_RETRANSMITTABLE_DATA) {
+ // The next packet should be sent as soon as the current packets has
+ // been transferred. We pace at twice the rate of the underlying
+ // sender's bandwidth estimate to help ensure that pacing doesn't become
+ // a bottleneck.
+ const float kPacingAggression = 2;
+ QuicTime::Delta delay =
+ BandwidthEstimate().Scale(kPacingAggression).TransferTime(bytes);
+ next_packet_send_time_ = next_packet_send_time_.Add(delay);
+ }
return sender_->OnPacketSent(sent_time, sequence_number, bytes,
- transmission_type, is_retransmittable);
+ transmission_type, has_retransmittable_data);
+}
+
+void PacingSender::OnRetransmissionTimeout() {
+ sender_->OnRetransmissionTimeout();
}
void PacingSender::OnPacketAbandoned(QuicPacketSequenceNumber sequence_number,
@@ -74,6 +90,12 @@ QuicTime::Delta PacingSender::TimeUntilSend(
return time_until_send;
}
+ if (has_retransmittable_data == NO_RETRANSMITTABLE_DATA) {
+ // Don't pace ACK packets, since they do not count against CWND and do not
+ // cause CWND to grow.
+ return QuicTime::Delta::Zero();
+ }
+
if (!was_last_send_delayed_ &&
(!next_packet_send_time_.IsInitialized() ||
now > next_packet_send_time_.Add(alarm_granularity_))) {
@@ -86,11 +108,14 @@ QuicTime::Delta PacingSender::TimeUntilSend(
// If the end of the epoch is far enough in the future, delay the send.
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();
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 4446c0c..f0de935 100644
--- a/net/quic/congestion_control/pacing_sender.h
+++ b/net/quic/congestion_control/pacing_sender.h
@@ -32,6 +32,7 @@ class NET_EXPORT_PRIVATE PacingSender : public SendAlgorithmInterface {
// SendAlgorithmInterface methods.
virtual void SetFromConfig(const QuicConfig& config, bool is_server) OVERRIDE;
+ virtual void SetMaxPacketSize(QuicByteCount max_packet_size) OVERRIDE;
virtual void OnIncomingQuicCongestionFeedbackFrame(
const QuicCongestionFeedbackFrame& feedback,
QuicTime feedback_receive_time,
@@ -39,13 +40,14 @@ class NET_EXPORT_PRIVATE PacingSender : public SendAlgorithmInterface {
virtual void OnIncomingAck(QuicPacketSequenceNumber acked_sequence_number,
QuicByteCount acked_bytes,
QuicTime::Delta rtt) OVERRIDE;
- virtual void OnIncomingLoss(QuicPacketSequenceNumber largest_loss,
+ virtual void OnIncomingLoss(QuicPacketSequenceNumber sequence_number,
QuicTime ack_receive_time) OVERRIDE;
virtual bool OnPacketSent(QuicTime sent_time,
QuicPacketSequenceNumber sequence_number,
QuicByteCount bytes,
TransmissionType transmission_type,
HasRetransmittableData is_retransmittable) OVERRIDE;
+ virtual void OnRetransmissionTimeout() OVERRIDE;
virtual void OnPacketAbandoned(QuicPacketSequenceNumber sequence_number,
QuicByteCount abandoned_bytes) OVERRIDE;
virtual QuicTime::Delta TimeUntilSend(
diff --git a/net/quic/congestion_control/pacing_sender_test.cc b/net/quic/congestion_control/pacing_sender_test.cc
index b27ede0..dfc78b8 100644
--- a/net/quic/congestion_control/pacing_sender_test.cc
+++ b/net/quic/congestion_control/pacing_sender_test.cc
@@ -55,6 +55,29 @@ class PacingSenderTest : public ::testing::Test {
HAS_RETRANSMITTABLE_DATA);
}
+ void CheckAckIsSentImmediately() {
+ // In order for the ack to be sendable, the underlying sender must
+ // permit it to be sent immediately.
+ EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
+ NOT_RETRANSMISSION,
+ NO_RETRANSMITTABLE_DATA,
+ NOT_HANDSHAKE))
+ .WillOnce(Return(zero_time_));
+ // Verify that the ACK can be sent immediately.
+ EXPECT_EQ(zero_time_,
+ pacing_sender_->TimeUntilSend(clock_.Now(), NOT_RETRANSMISSION,
+ NO_RETRANSMITTABLE_DATA,
+ NOT_HANDSHAKE));
+
+ // Actually send the packet.
+ EXPECT_CALL(*mock_sender_,
+ OnPacketSent(clock_.Now(), sequence_number_, kMaxPacketSize,
+ NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA));
+ pacing_sender_->OnPacketSent(clock_.Now(), sequence_number_++,
+ kMaxPacketSize, NOT_RETRANSMISSION,
+ NO_RETRANSMITTABLE_DATA);
+ }
+
void CheckPacketIsDelayed(QuicTime::Delta delay) {
// In order for the packet to be sendable, the underlying sender must
// permit it to be sent immediately.
@@ -103,10 +126,11 @@ TEST_F(PacingSenderTest, SendNow) {
}
TEST_F(PacingSenderTest, VariousSending) {
- // Configure bandwith of 1 packet per 1 ms.
+ // Configure bandwith of 1 packet per 2 ms, for which the pacing rate
+ // will be 1 packet per 1 ms.
EXPECT_CALL(*mock_sender_, BandwidthEstimate())
.WillRepeatedly(Return(QuicBandwidth::FromBytesAndTimeDelta(
- kMaxPacketSize, QuicTime::Delta::FromMilliseconds(1))));
+ kMaxPacketSize, QuicTime::Delta::FromMilliseconds(2))));
CheckPacketIsSentImmediately();
CheckPacketIsSentImmediately();
@@ -121,6 +145,7 @@ TEST_F(PacingSenderTest, VariousSending) {
CheckPacketIsSentImmediately();
CheckPacketIsSentImmediately();
CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+ CheckAckIsSentImmediately();
// Wake up late.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(4));
diff --git a/net/quic/congestion_control/quic_congestion_manager.cc b/net/quic/congestion_control/quic_congestion_manager.cc
index 66a7478..c292fe7 100644
--- a/net/quic/congestion_control/quic_congestion_manager.cc
+++ b/net/quic/congestion_control/quic_congestion_manager.cc
@@ -8,9 +8,26 @@
#include <map>
#include "base/stl_util.h"
+#include "net/quic/congestion_control/pacing_sender.h"
#include "net/quic/congestion_control/receive_algorithm_interface.h"
#include "net/quic/congestion_control/send_algorithm_interface.h"
+#include "net/quic/quic_protocol.h"
+using std::map;
+using std::min;
+
+// A test-only flag to prevent the RTO from backing off when multiple sequential
+// tail drops occur.
+bool FLAGS_limit_rto_increase_for_tests = false;
+
+// Do not remove this flag until the Finch-trials described in b/11706275
+// are complete.
+// If true, QUIC connections will support the use of a pacing algorithm when
+// sending packets, in an attempt to reduce packet loss. The client must also
+// request pacing for the server to enable it.
+bool FLAGS_enable_quic_pacing = false;
+
+namespace net {
namespace {
static const int kBitrateSmoothingPeriodMs = 1000;
static const int kHistoryPeriodMs = 5000;
@@ -22,26 +39,30 @@ static const int kDefaultRetransmissionTimeMs = 500;
static const int kMinRetransmissionTimeMs = 200;
static const int kMaxRetransmissionTimeMs = 60000;
static const size_t kMaxRetransmissions = 10;
-static const size_t kTailDropWindowSize = 5;
-static const size_t kTailDropMaxRetransmissions = 4;
+
+// We want to make sure if we get a nack packet which triggers several
+// retransmissions, we don't queue up too many packets. 10 is TCP's default
+// initial congestion window(RFC 6928).
+static const size_t kMaxRetransmissionsPerAck = kDefaultInitialWindow;
+
+// TCP retransmits after 3 nacks.
+// TODO(ianswett): Change to match TCP's rule of retransmitting once an ack
+// at least 3 sequence numbers larger arrives.
+static const size_t kNumberOfNacksBeforeRetransmission = 3;
COMPILE_ASSERT(kHistoryPeriodMs >= kBitrateSmoothingPeriodMs,
history_must_be_longer_or_equal_to_the_smoothing_period);
} // namespace
-using std::map;
-using std::min;
-
-namespace net {
-
QuicCongestionManager::QuicCongestionManager(
const QuicClock* clock,
CongestionFeedbackType type)
: clock_(clock),
receive_algorithm_(ReceiveAlgorithmInterface::Create(clock, type)),
send_algorithm_(SendAlgorithmInterface::Create(clock, type)),
- largest_missing_(0),
- rtt_sample_(QuicTime::Delta::Infinite()) {
+ rtt_sample_(QuicTime::Delta::Infinite()),
+ consecutive_rto_count_(0),
+ using_pacing_(false) {
}
QuicCongestionManager::~QuicCongestionManager() {
@@ -58,34 +79,53 @@ void QuicCongestionManager::SetFromConfig(const QuicConfig& config,
rtt_sample_ =
QuicTime::Delta::FromMicroseconds(config.initial_round_trip_time_us());
}
+ if (config.congestion_control() == kPACE) {
+ MaybeEnablePacing();
+ }
send_algorithm_->SetFromConfig(config, is_server);
}
+void QuicCongestionManager::SetMaxPacketSize(QuicByteCount max_packet_size) {
+ send_algorithm_->SetMaxPacketSize(max_packet_size);
+}
+
void QuicCongestionManager::OnPacketSent(
QuicPacketSequenceNumber sequence_number,
QuicTime sent_time,
QuicByteCount bytes,
TransmissionType transmission_type,
HasRetransmittableData has_retransmittable_data) {
+ DCHECK_LT(0u, sequence_number);
DCHECK(!ContainsKey(pending_packets_, sequence_number));
- if (send_algorithm_->OnPacketSent(sent_time, sequence_number, bytes,
- transmission_type,
- has_retransmittable_data)) {
- packet_history_map_[sequence_number] =
- new class SendAlgorithmInterface::SentPacket(bytes, sent_time);
- pending_packets_[sequence_number] = bytes;
- CleanupPacketHistory();
+ // Only track packets the send algorithm wants us to track.
+ if (!send_algorithm_->OnPacketSent(sent_time, sequence_number, bytes,
+ transmission_type,
+ has_retransmittable_data)) {
+ return;
}
+ packet_history_map_[sequence_number] = new SendAlgorithmInterface::SentPacket(
+ bytes, sent_time, has_retransmittable_data);
+ pending_packets_.insert(sequence_number);
+ CleanupPacketHistory();
+}
+
+void QuicCongestionManager::OnRetransmissionTimeout() {
+ ++consecutive_rto_count_;
+ send_algorithm_->OnRetransmissionTimeout();
+}
+
+void QuicCongestionManager::OnLeastUnackedIncreased() {
+ consecutive_rto_count_ = 0;
}
-// Called when a packet is timed out.
void QuicCongestionManager::OnPacketAbandoned(
QuicPacketSequenceNumber sequence_number) {
- PendingPacketsMap::iterator it = pending_packets_.find(sequence_number);
+ SequenceNumberSet::iterator it = pending_packets_.find(sequence_number);
if (it != pending_packets_.end()) {
- // Shouldn't this report loss as well? (decrease cgst window).
- send_algorithm_->OnPacketAbandoned(sequence_number, it->second);
+ DCHECK(ContainsKey(packet_history_map_, sequence_number));
+ send_algorithm_->OnPacketAbandoned(
+ sequence_number, packet_history_map_[sequence_number]->bytes_sent());
pending_packets_.erase(it);
}
}
@@ -96,8 +136,9 @@ void QuicCongestionManager::OnIncomingQuicCongestionFeedbackFrame(
frame, feedback_receive_time, packet_history_map_);
}
-void QuicCongestionManager::OnIncomingAckFrame(const QuicAckFrame& frame,
- QuicTime ack_receive_time) {
+SequenceNumberSet QuicCongestionManager::OnIncomingAckFrame(
+ const QuicAckFrame& frame,
+ QuicTime ack_receive_time) {
// We calculate the RTT based on the highest ACKed sequence number, the lower
// sequence numbers will include the ACK aggregation delay.
SendAlgorithmInterface::SentPacketsMap::iterator history_it =
@@ -105,7 +146,7 @@ void QuicCongestionManager::OnIncomingAckFrame(const QuicAckFrame& frame,
// TODO(satyamshekhar): largest_observed might be missing.
if (history_it != packet_history_map_.end()) {
QuicTime::Delta send_delta = ack_receive_time.Subtract(
- history_it->second->SendTimestamp());
+ history_it->second->send_timestamp());
if (send_delta > frame.received_info.delta_time_largest_observed) {
rtt_sample_ = send_delta.Subtract(
frame.received_info.delta_time_largest_observed);
@@ -121,35 +162,58 @@ void QuicCongestionManager::OnIncomingAckFrame(const QuicAckFrame& frame,
// from pending_packets_.
// * Remove all missing packets.
// * Send each ACK in the list to send_algorithm_.
- PendingPacketsMap::iterator it, it_upper;
- it = pending_packets_.begin();
- it_upper = pending_packets_.upper_bound(frame.received_info.largest_observed);
+ SequenceNumberSet::iterator it = pending_packets_.begin();
+ SequenceNumberSet::iterator it_upper =
+ pending_packets_.upper_bound(frame.received_info.largest_observed);
- bool new_packet_loss_reported = false;
+ SequenceNumberSet retransmission_packets;
while (it != it_upper) {
- QuicPacketSequenceNumber sequence_number = it->first;
+ QuicPacketSequenceNumber sequence_number = *it;
if (!IsAwaitingPacket(frame.received_info, sequence_number)) {
// Not missing, hence implicitly acked.
- send_algorithm_->OnIncomingAck(sequence_number, it->second, rtt_sample_);
+ size_t bytes_sent = packet_history_map_[sequence_number]->bytes_sent();
+ send_algorithm_->OnIncomingAck(sequence_number, bytes_sent, rtt_sample_);
pending_packets_.erase(it++); // Must be incremented post to work.
- } else {
- if (sequence_number > largest_missing_) {
- // We have a new loss reported.
- new_packet_loss_reported = true;
- largest_missing_ = sequence_number;
- }
+ continue;
+ }
+
+ // The peer got packets after this sequence number. This is an explicit
+ // nack.
+ DVLOG(1) << "still missing packet " << sequence_number;
+ DCHECK(ContainsKey(packet_history_map_, sequence_number));
+ const SendAlgorithmInterface::SentPacket* sent_packet =
+ packet_history_map_[sequence_number];
+ packet_history_map_[sequence_number]->Nack();
+
+ // If the nack count hasn't been reached, continue.
+ if (sent_packet->nack_count() < kNumberOfNacksBeforeRetransmission) {
++it;
+ continue;
}
- }
- if (new_packet_loss_reported) {
+
+ // If the number of retransmissions has maxed out, don't lose or retransmit
+ // any more packets.
+ if (retransmission_packets.size() >= kMaxRetransmissionsPerAck) {
+ ++it;
+ continue;
+ }
+
// TODO(ianswett): OnIncomingLoss is also called from TCPCubicSender when
// an FEC packet is lost, but FEC loss information should be shared among
// congestion managers. Additionally, if it's expected the FEC packet may
// repair the loss, it should be recorded as a loss to the congestion
// manager, but not retransmitted until it's known whether the FEC packet
// arrived.
- send_algorithm_->OnIncomingLoss(largest_missing_, ack_receive_time);
+ send_algorithm_->OnIncomingLoss(sequence_number, ack_receive_time);
+
+ if (sent_packet->has_retransmittable_data() == HAS_RETRANSMITTABLE_DATA) {
+ retransmission_packets.insert(sequence_number);
+ }
+
+ ++it;
}
+
+ return retransmission_packets;
}
QuicTime::Delta QuicCongestionManager::TimeUntilSend(
@@ -196,18 +260,21 @@ const QuicTime::Delta QuicCongestionManager::DelayedAckTime() {
return QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs/2);
}
-const QuicTime::Delta QuicCongestionManager::GetRetransmissionDelay(
- size_t unacked_packets_count,
- size_t number_retransmissions) const {
- if (unacked_packets_count <= kTailDropWindowSize) {
- // Avoid exponential backoff of RTO when there are only a few packets
- // outstanding. This helps avoid the situation where fake packet loss
- // causes a packet and it's retransmission to be dropped causing
- // test timouts.
- if (number_retransmissions <= kTailDropMaxRetransmissions) {
- number_retransmissions = 0;
- } else {
- number_retransmissions -= kTailDropMaxRetransmissions;
+const QuicTime::Delta QuicCongestionManager::GetRetransmissionDelay() const {
+ size_t number_retransmissions = consecutive_rto_count_;
+ if (FLAGS_limit_rto_increase_for_tests) {
+ const size_t kTailDropWindowSize = 5;
+ const size_t kTailDropMaxRetransmissions = 4;
+ if (pending_packets_.size() <= kTailDropWindowSize) {
+ // Avoid exponential backoff of RTO when there are only a few packets
+ // outstanding. This helps avoid the situation where fake packet loss
+ // causes a packet and it's retransmission to be dropped causing
+ // test timouts.
+ if (number_retransmissions <= kTailDropMaxRetransmissions) {
+ number_retransmissions = 0;
+ } else {
+ number_retransmissions -= kTailDropMaxRetransmissions;
+ }
}
}
@@ -256,13 +323,32 @@ void QuicCongestionManager::CleanupPacketHistory() {
SendAlgorithmInterface::SentPacketsMap::iterator history_it =
packet_history_map_.begin();
for (; history_it != packet_history_map_.end(); ++history_it) {
- if (now.Subtract(history_it->second->SendTimestamp()) <= kHistoryPeriod) {
+ if (now.Subtract(history_it->second->send_timestamp()) <= kHistoryPeriod) {
return;
}
+ // Don't remove packets which have not been acked.
+ if (ContainsKey(pending_packets_, history_it->first)) {
+ continue;
+ }
delete history_it->second;
packet_history_map_.erase(history_it);
history_it = packet_history_map_.begin();
}
}
+void QuicCongestionManager::MaybeEnablePacing() {
+ if (!FLAGS_enable_quic_pacing) {
+ return;
+ }
+
+ if (using_pacing_) {
+ return;
+ }
+
+ using_pacing_ = true;
+ send_algorithm_.reset(
+ new PacingSender(send_algorithm_.release(),
+ QuicTime::Delta::FromMicroseconds(1)));
+}
+
} // namespace net
diff --git a/net/quic/congestion_control/quic_congestion_manager.h b/net/quic/congestion_control/quic_congestion_manager.h
index a62e484..5c8d965 100644
--- a/net/quic/congestion_control/quic_congestion_manager.h
+++ b/net/quic/congestion_control/quic_congestion_manager.h
@@ -16,6 +16,9 @@
#include "net/quic/quic_bandwidth.h"
#include "net/quic/quic_protocol.h"
+NET_EXPORT_PRIVATE extern bool FLAGS_limit_rto_increase_for_tests;
+NET_EXPORT_PRIVATE extern bool FLAGS_enable_quic_pacing;
+
namespace net {
namespace test {
@@ -34,9 +37,13 @@ class NET_EXPORT_PRIVATE QuicCongestionManager {
virtual void SetFromConfig(const QuicConfig& config, bool is_server);
+ virtual void SetMaxPacketSize(QuicByteCount max_packet_size);
+
// Called when we have received an ack frame from peer.
- virtual void OnIncomingAckFrame(const QuicAckFrame& frame,
- QuicTime ack_receive_time);
+ // Returns a set containing all the sequence numbers to be nack retransmitted
+ // as a result of the ack.
+ virtual SequenceNumberSet OnIncomingAckFrame(const QuicAckFrame& frame,
+ QuicTime ack_receive_time);
// Called when a congestion feedback frame is received from peer.
virtual void OnIncomingQuicCongestionFeedbackFrame(
@@ -51,7 +58,15 @@ class NET_EXPORT_PRIVATE QuicCongestionManager {
TransmissionType transmission_type,
HasRetransmittableData has_retransmittable_data);
- // Called when a packet is timed out.
+ // Called when the retransmission timer expires.
+ virtual void OnRetransmissionTimeout();
+
+ // Called when the least unacked sequence number increases, indicating the
+ // consecutive rto count should be reset to 0.
+ virtual void OnLeastUnackedIncreased();
+
+ // Called when a packet is timed out, such as an RTO. Removes the bytes from
+ // the congestion manager, but does not change the congestion window size.
virtual void OnPacketAbandoned(QuicPacketSequenceNumber sequence_number);
// Calculate the time until we can send the next packet to the wire.
@@ -87,12 +102,8 @@ class NET_EXPORT_PRIVATE QuicCongestionManager {
// Returns amount of time for delayed ack timer.
const QuicTime::Delta DelayedAckTime();
- // Returns the current RTO delay. |unacked_packet_count| is the number of
- // currently outstanding packets. |number_retransmissions| is the number of
- // sequential retransmission timeouts that have occrued.
- const QuicTime::Delta GetRetransmissionDelay(
- size_t unacked_packets_count,
- size_t number_retransmissions) const;
+ // Returns the current RTO delay.
+ const QuicTime::Delta GetRetransmissionDelay() const;
// Returns the estimated smoothed RTT calculated by the congestion algorithm.
const QuicTime::Delta SmoothedRtt() const;
@@ -108,20 +119,31 @@ class NET_EXPORT_PRIVATE QuicCongestionManager {
// Sets the value of the current congestion window to |window|.
void SetCongestionWindow(QuicByteCount window);
+ // Enables pacing if it has not already been enabled, and if
+ // FLAGS_enable_quic_pacing is set.
+ void MaybeEnablePacing();
+
+ bool using_pacing() const { return using_pacing_; }
+
private:
friend class test::QuicConnectionPeer;
friend class test::QuicCongestionManagerPeer;
- typedef std::map<QuicPacketSequenceNumber, size_t> PendingPacketsMap;
void CleanupPacketHistory();
const QuicClock* clock_;
scoped_ptr<ReceiveAlgorithmInterface> receive_algorithm_;
scoped_ptr<SendAlgorithmInterface> send_algorithm_;
+ // Tracks the send time, size, and nack count of sent packets. Packets are
+ // removed after 5 seconds and they've been removed from pending_packets_.
SendAlgorithmInterface::SentPacketsMap packet_history_map_;
- PendingPacketsMap pending_packets_;
+ // Packets that are outstanding and have not been abandoned or lost.
+ SequenceNumberSet pending_packets_;
QuicPacketSequenceNumber largest_missing_;
QuicTime::Delta rtt_sample_; // RTT estimate from the most recent ACK.
+ // Number of times the RTO timer has fired in a row without receiving an ack.
+ size_t consecutive_rto_count_;
+ bool using_pacing_;
DISALLOW_COPY_AND_ASSIGN(QuicCongestionManager);
};
diff --git a/net/quic/congestion_control/quic_congestion_manager_test.cc b/net/quic/congestion_control/quic_congestion_manager_test.cc
index 4e434b0..f08743f 100644
--- a/net/quic/congestion_control/quic_congestion_manager_test.cc
+++ b/net/quic/congestion_control/quic_congestion_manager_test.cc
@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "net/quic/congestion_control/quic_congestion_manager.h"
+
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "net/quic/congestion_control/inter_arrival_sender.h"
-#include "net/quic/congestion_control/quic_congestion_manager.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/quic_test_utils.h"
@@ -37,6 +38,10 @@ class QuicCongestionManagerPeer : public QuicCongestionManager {
return packet_history_map_;
}
+ size_t GetNackCount(QuicPacketSequenceNumber sequence_number) const {
+ return packet_history_map_.find(sequence_number)->second->nack_count();
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(QuicCongestionManagerPeer);
};
@@ -47,6 +52,14 @@ class QuicCongestionManagerTest : public ::testing::Test {
manager_.reset(new QuicCongestionManagerPeer(&clock_, congestion_type));
}
+ MockSendAlgorithm* SetUpMockSender() {
+ SetUpCongestionType(kFixRate);
+
+ MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
+ manager_->SetSendAlgorithm(send_algorithm);
+ return send_algorithm;
+ }
+
static const HasRetransmittableData kIgnored = HAS_RETRANSMITTABLE_DATA;
MockClock clock_;
@@ -63,17 +76,17 @@ TEST_F(QuicCongestionManagerTest, Bandwidth) {
feedback.fix_rate.bitrate = QuicBandwidth::FromKBytesPerSecond(100);
manager_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now());
- for (int i = 1; i <= 100; ++i) {
+ for (QuicPacketSequenceNumber i = 1; i <= 100; ++i) {
QuicTime::Delta advance_time = manager_->TimeUntilSend(
clock_.Now(), NOT_RETRANSMISSION, kIgnored, NOT_HANDSHAKE);
clock_.AdvanceTime(advance_time);
EXPECT_TRUE(manager_->TimeUntilSend(
clock_.Now(), NOT_RETRANSMISSION, kIgnored, NOT_HANDSHAKE).IsZero());
manager_->OnPacketSent(i, clock_.Now(), 1000, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
+ HAS_RETRANSMITTABLE_DATA);
// Ack the packet we sent.
ack.received_info.largest_observed = i;
- manager_->OnIncomingAckFrame(ack, clock_.Now());
+ EXPECT_EQ(0u, manager_->OnIncomingAckFrame(ack, clock_.Now()).size());
}
EXPECT_EQ(100, manager_->BandwidthEstimate().ToKBytesPerSecond());
EXPECT_NEAR(100,
@@ -94,15 +107,15 @@ TEST_F(QuicCongestionManagerTest, BandwidthWith1SecondGap) {
manager_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now());
for (QuicPacketSequenceNumber sequence_number = 1; sequence_number <= 100;
- ++sequence_number) {
+ ++sequence_number) {
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
EXPECT_TRUE(manager_->TimeUntilSend(
clock_.Now(), NOT_RETRANSMISSION, kIgnored, NOT_HANDSHAKE).IsZero());
manager_->OnPacketSent(sequence_number, clock_.Now(), 1000,
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
// Ack the packet we sent.
ack.received_info.largest_observed = sequence_number;
- manager_->OnIncomingAckFrame(ack, clock_.Now());
+ EXPECT_EQ(0u, manager_->OnIncomingAckFrame(ack, clock_.Now()).size());
}
EXPECT_EQ(100000, manager_->BandwidthEstimate().ToBytesPerSecond());
EXPECT_NEAR(100000,
@@ -125,11 +138,11 @@ TEST_F(QuicCongestionManagerTest, BandwidthWith1SecondGap) {
EXPECT_TRUE(manager_->TimeUntilSend(
clock_.Now(), NOT_RETRANSMISSION, kIgnored, NOT_HANDSHAKE).IsZero());
manager_->OnPacketSent(i + 100, clock_.Now(), 1000, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
+ HAS_RETRANSMITTABLE_DATA);
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
// Ack the packet we sent.
ack.received_info.largest_observed = i + 100;
- manager_->OnIncomingAckFrame(ack, clock_.Now());
+ EXPECT_EQ(0u, manager_->OnIncomingAckFrame(ack, clock_.Now()).size());
}
EXPECT_EQ(100, manager_->BandwidthEstimate().ToKBytesPerSecond());
EXPECT_NEAR(100,
@@ -139,11 +152,201 @@ TEST_F(QuicCongestionManagerTest, BandwidthWith1SecondGap) {
2);
}
-TEST_F(QuicCongestionManagerTest, Rtt) {
+TEST_F(QuicCongestionManagerTest, NackRetransmit1Packet) {
+ MockSendAlgorithm* send_algorithm = SetUpMockSender();
+
+ const size_t kNumSentPackets = 4;
+ // Transmit 4 packets.
+ for (size_t i = 1; i <= kNumSentPackets; ++i) {
+ EXPECT_CALL(*send_algorithm, OnPacketSent(_, _, _, _, _))
+ .Times(1).WillOnce(Return(true));
+ manager_->OnPacketSent(i, clock_.Now(), 1000,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ }
+
+ // Nack the first packet 3 times with increasing largest observed.
+ QuicAckFrame ack;
+ ack.received_info.delta_time_largest_observed =
+ QuicTime::Delta::FromMilliseconds(5);
+ ack.received_info.missing_packets.insert(1);
+ for (size_t i = 1; i <= 3; ++i) {
+ ack.received_info.largest_observed = i + 1;
+ EXPECT_CALL(*send_algorithm, OnIncomingAck(i + 1, _, _)).Times(1);
+ if (i == 3) {
+ EXPECT_CALL(*send_algorithm, OnIncomingLoss(1, _)).Times(1);
+ }
+ SequenceNumberSet retransmissions =
+ manager_->OnIncomingAckFrame(ack, clock_.Now());
+ EXPECT_EQ(i == 3 ? 1u : 0u, retransmissions.size());
+ EXPECT_EQ(i, manager_->GetNackCount(1));
+ }
+}
+
+TEST_F(QuicCongestionManagerTest, NackRetransmit10Packets) {
+ MockSendAlgorithm* send_algorithm = SetUpMockSender();
+
+ const size_t kNumSentPackets = 20;
+ // Transmit 20 packets.
+ for (QuicPacketSequenceNumber i = 1; i <= kNumSentPackets; ++i) {
+ EXPECT_CALL(*send_algorithm, OnPacketSent(_, _, _, _, _))
+ .Times(1).WillOnce(Return(true));
+ manager_->OnPacketSent(i, clock_.Now(), 1000,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ }
+
+ // Nack the first 19 packets 3 times.
+ QuicAckFrame ack;
+ ack.received_info.largest_observed = kNumSentPackets;
+ ack.received_info.delta_time_largest_observed =
+ QuicTime::Delta::FromMilliseconds(5);
+ for (size_t i = 1; i < kNumSentPackets; ++i) {
+ ack.received_info.missing_packets.insert(i);
+ }
+ for (size_t i = 1; i <= 3; ++i) {
+ if (i == 1) {
+ EXPECT_CALL(*send_algorithm,
+ OnIncomingAck(kNumSentPackets, _, _)).Times(1);
+ }
+ if (i == 3) {
+ EXPECT_CALL(*send_algorithm, OnIncomingLoss(_, _)).Times(10);
+ }
+ SequenceNumberSet retransmissions =
+ manager_->OnIncomingAckFrame(ack, clock_.Now());
+ EXPECT_EQ(i == 3 ? 10u : 0u, retransmissions.size());
+ for (QuicPacketSequenceNumber j = 1; j < kNumSentPackets; ++j) {
+ EXPECT_EQ(i, manager_->GetNackCount(j));
+ }
+ }
+}
+
+TEST_F(QuicCongestionManagerTest, NackRetransmit10PacketsAlternateAcks) {
+ MockSendAlgorithm* send_algorithm = SetUpMockSender();
+
+ const size_t kNumSentPackets = 30;
+ // Transmit 15 packets of data and 15 ack packets. The send algorithm will
+ // inform the congestion manager not to save the acks by returning false.
+ for (QuicPacketSequenceNumber i = 1; i <= kNumSentPackets; ++i) {
+ EXPECT_CALL(*send_algorithm, OnPacketSent(_, _, _, _, _))
+ .Times(1).WillOnce(Return(i % 2 == 0 ? false : true));
+ manager_->OnPacketSent(
+ i, clock_.Now(), 1000, NOT_RETRANSMISSION,
+ i % 2 == 0 ? NO_RETRANSMITTABLE_DATA : HAS_RETRANSMITTABLE_DATA);
+ }
+
+ // Nack the first 29 packets 3 times.
+ QuicAckFrame ack;
+ ack.received_info.largest_observed = kNumSentPackets;
+ ack.received_info.delta_time_largest_observed =
+ QuicTime::Delta::FromMilliseconds(5);
+ for (size_t i = 1; i < kNumSentPackets; ++i) {
+ ack.received_info.missing_packets.insert(i);
+ }
+ SequenceNumberSet retransmissions;
+ for (size_t i = 1; i <= 3; ++i) {
+ // We never actually get an ack call, since the kNumSentPackets packet was
+ // not saved.
+ if (i == 3) {
+ EXPECT_CALL(*send_algorithm, OnIncomingLoss(_, _)).Times(10);
+ }
+ retransmissions = manager_->OnIncomingAckFrame(ack, clock_.Now());
+ EXPECT_EQ(i == 3 ? 10u : 0u, retransmissions.size());
+ // Only non-ack packets have a nack count.
+ for (size_t j = 1; j < kNumSentPackets; j += 2) {
+ EXPECT_EQ(i, manager_->GetNackCount(j));
+ }
+ }
+ // Ensure only the odd packets were retransmitted, since the others were not
+ // retransmittable(ie: acks).
+ for (SequenceNumberSet::const_iterator it = retransmissions.begin();
+ it != retransmissions.end(); ++it) {
+ EXPECT_EQ(1u, *it % 2);
+ }
+}
+
+TEST_F(QuicCongestionManagerTest, NackTwiceThenAck) {
+ MockSendAlgorithm* send_algorithm = SetUpMockSender();
+
+ // Transmit 4 packets.
+ for (QuicPacketSequenceNumber i = 1; i <= 4; ++i) {
+ EXPECT_CALL(*send_algorithm, OnPacketSent(_, _, _, _, _))
+ .Times(1).WillOnce(Return(true));
+ manager_->OnPacketSent(i, clock_.Now(), 1000,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ }
+
+ // Nack the first packet 2 times, then ack it.
+ QuicAckFrame ack;
+ ack.received_info.missing_packets.insert(1);
+ for (size_t i = 1; i <= 3; ++i) {
+ if (i == 3) {
+ ack.received_info.missing_packets.clear();
+ }
+ ack.received_info.largest_observed = i + 1;
+ ack.received_info.delta_time_largest_observed =
+ QuicTime::Delta::FromMilliseconds(5);
+ EXPECT_CALL(*send_algorithm,
+ OnIncomingAck(_, _, _)).Times(i == 3 ? 2 : 1);
+ SequenceNumberSet retransmissions =
+ manager_->OnIncomingAckFrame(ack, clock_.Now());
+ EXPECT_EQ(0u, retransmissions.size());
+ // The nack count remains at 2 when the packet is acked.
+ EXPECT_EQ(i == 3 ? 2u : i, manager_->GetNackCount(1));
+ }
+}
+
+// TODO(ianswett): Change this to RetransmitOnOneAck once ack counting is based
+// on the distance between the sequence number and the largest observed, not
+// just the number of ack frames processed.
+TEST_F(QuicCongestionManagerTest, NoRetransmitOnOneAck) {
+ SetUpCongestionType(kFixRate);
+
+ // Transmit 4 packets.
+ for (QuicPacketSequenceNumber i = 1; i <= 4; ++i) {
+ manager_->OnPacketSent(i, clock_.Now(), 1000,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ }
+
+ // Nack the first packet 2 times, then ack it.
+ QuicAckFrame ack;
+ ack.received_info.missing_packets.insert(1);
+ ack.received_info.largest_observed = 4;
+ ack.received_info.delta_time_largest_observed =
+ QuicTime::Delta::FromMilliseconds(5);
+ SequenceNumberSet retransmissions =
+ manager_->OnIncomingAckFrame(ack, clock_.Now());
+ EXPECT_EQ(0u, retransmissions.size());
+ // The nack count is 1 for packet 1.
+ EXPECT_EQ(1u, manager_->GetNackCount(1));
+}
+
+TEST_F(QuicCongestionManagerTest, NoRetransmitOnOneAckMultipleNacks) {
SetUpCongestionType(kFixRate);
- MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
- manager_->SetSendAlgorithm(send_algorithm);
+ // Transmit 4 packets.
+ for (QuicPacketSequenceNumber i = 1; i <= 4; ++i) {
+ manager_->OnPacketSent(i, clock_.Now(), 1000,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ }
+
+ // Nack packets 1 through 3.
+ QuicAckFrame ack;
+ for (int i = 1; i <= 3; ++i) {
+ ack.received_info.missing_packets.insert(i);
+ }
+ ack.received_info.largest_observed = 4;
+ ack.received_info.delta_time_largest_observed =
+ QuicTime::Delta::FromMilliseconds(5);
+ SequenceNumberSet retransmissions =
+ manager_->OnIncomingAckFrame(ack, clock_.Now());
+ EXPECT_EQ(0u, retransmissions.size());
+ // The nack count is 1 for all nacked packets.
+ for (QuicPacketSequenceNumber i = 1; i <= 3; ++i) {
+ EXPECT_EQ(1u, manager_->GetNackCount(i));
+ }
+}
+
+TEST_F(QuicCongestionManagerTest, Rtt) {
+ MockSendAlgorithm* send_algorithm = SetUpMockSender();
QuicPacketSequenceNumber sequence_number = 1;
QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(15);
@@ -169,10 +372,7 @@ TEST_F(QuicCongestionManagerTest, RttWithInvalidDelta) {
// Expect that the RTT is equal to the local time elapsed, since the
// delta_time_largest_observed is larger than the local time elapsed
// and is hence invalid.
- SetUpCongestionType(kFixRate);
-
- MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
- manager_->SetSendAlgorithm(send_algorithm);
+ MockSendAlgorithm* send_algorithm = SetUpMockSender();
QuicPacketSequenceNumber sequence_number = 1;
QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(10);
@@ -197,10 +397,7 @@ TEST_F(QuicCongestionManagerTest, RttWithInvalidDelta) {
TEST_F(QuicCongestionManagerTest, RttWithInfiniteDelta) {
// Expect that the RTT is equal to the local time elapsed, since the
// delta_time_largest_observed is infinite, and is hence invalid.
- SetUpCongestionType(kFixRate);
-
- MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
- manager_->SetSendAlgorithm(send_algorithm);
+ MockSendAlgorithm* send_algorithm = SetUpMockSender();
QuicPacketSequenceNumber sequence_number = 1;
QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(10);
@@ -224,10 +421,7 @@ TEST_F(QuicCongestionManagerTest, RttWithInfiniteDelta) {
TEST_F(QuicCongestionManagerTest, RttZeroDelta) {
// Expect that the RTT is the time between send and receive since the
// delta_time_largest_observed is zero.
- SetUpCongestionType(kFixRate);
-
- MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
- manager_->SetSendAlgorithm(send_algorithm);
+ MockSendAlgorithm* send_algorithm = SetUpMockSender();
QuicPacketSequenceNumber sequence_number = 1;
QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(10);
@@ -249,68 +443,64 @@ TEST_F(QuicCongestionManagerTest, RttZeroDelta) {
}
TEST_F(QuicCongestionManagerTest, GetTransmissionDelayMin) {
- SetUpCongestionType(kFixRate);
-
- MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
- manager_->SetSendAlgorithm(send_algorithm);
+ MockSendAlgorithm* send_algorithm = SetUpMockSender();
+ EXPECT_CALL(*send_algorithm, OnRetransmissionTimeout());
QuicTime::Delta delay = QuicTime::Delta::FromMilliseconds(1);
EXPECT_CALL(*send_algorithm, RetransmissionDelay())
.WillOnce(Return(delay));
+ manager_->OnRetransmissionTimeout();
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200),
- manager_->GetRetransmissionDelay(1, 1));
+ manager_->GetRetransmissionDelay());
}
TEST_F(QuicCongestionManagerTest, GetTransmissionDelayMax) {
- SetUpCongestionType(kFixRate);
-
- MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
- manager_->SetSendAlgorithm(send_algorithm);
+ MockSendAlgorithm* send_algorithm = SetUpMockSender();
+ EXPECT_CALL(*send_algorithm, OnRetransmissionTimeout());
QuicTime::Delta delay = QuicTime::Delta::FromSeconds(500);
EXPECT_CALL(*send_algorithm, RetransmissionDelay())
.WillOnce(Return(delay));
+ manager_->OnRetransmissionTimeout();
EXPECT_EQ(QuicTime::Delta::FromSeconds(60),
- manager_->GetRetransmissionDelay(1, 1));
+ manager_->GetRetransmissionDelay());
}
TEST_F(QuicCongestionManagerTest, GetTransmissionDelay) {
- SetUpCongestionType(kFixRate);
-
- MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
- manager_->SetSendAlgorithm(send_algorithm);
+ MockSendAlgorithm* send_algorithm = SetUpMockSender();
QuicTime::Delta delay = QuicTime::Delta::FromMilliseconds(500);
EXPECT_CALL(*send_algorithm, RetransmissionDelay())
.WillRepeatedly(Return(delay));
- const int kUnackedPackets = 6;
// Delay should back off exponentially.
for (int i = 0; i < 5; ++i) {
- EXPECT_EQ(delay, manager_->GetRetransmissionDelay(kUnackedPackets, i));
+ EXPECT_EQ(delay, manager_->GetRetransmissionDelay());
delay = delay.Add(delay);
+ EXPECT_CALL(*send_algorithm, OnRetransmissionTimeout());
+ manager_->OnRetransmissionTimeout();
}
}
-TEST_F(QuicCongestionManagerTest, GetTransmissionDelayTailDrop) {
- SetUpCongestionType(kFixRate);
-
- MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
- manager_->SetSendAlgorithm(send_algorithm);
+TEST_F(QuicCongestionManagerTest, GetTestTransmissionDelayTailDrop) {
+ FLAGS_limit_rto_increase_for_tests = true;
+ MockSendAlgorithm* send_algorithm = SetUpMockSender();
QuicTime::Delta delay = QuicTime::Delta::FromMilliseconds(500);
EXPECT_CALL(*send_algorithm, RetransmissionDelay())
.WillRepeatedly(Return(delay));
- // No backoff for the first 5 retransmission.
+ // No backoff for the first 5 retransmissions.
for (int i = 0; i < 5; ++i) {
- EXPECT_EQ(delay, manager_->GetRetransmissionDelay(1, i));
+ EXPECT_EQ(delay, manager_->GetRetransmissionDelay());
+ EXPECT_CALL(*send_algorithm, OnRetransmissionTimeout());
+ manager_->OnRetransmissionTimeout();
}
- // Then backoff starts
- EXPECT_EQ(delay.Add(delay), manager_->GetRetransmissionDelay(1, 5));
+ // Then backoff starts.
+ EXPECT_EQ(delay.Add(delay), manager_->GetRetransmissionDelay());
}
} // namespace test
diff --git a/net/quic/congestion_control/send_algorithm_interface.cc b/net/quic/congestion_control/send_algorithm_interface.cc
index 5ab9879..493d84e 100644
--- a/net/quic/congestion_control/send_algorithm_interface.cc
+++ b/net/quic/congestion_control/send_algorithm_interface.cc
@@ -4,7 +4,6 @@
#include "net/quic/congestion_control/send_algorithm_interface.h"
-#include "net/quic/congestion_control/cubic.h"
#include "net/quic/congestion_control/fix_rate_sender.h"
#include "net/quic/congestion_control/tcp_cubic_sender.h"
#include "net/quic/quic_protocol.h"
diff --git a/net/quic/congestion_control/send_algorithm_interface.h b/net/quic/congestion_control/send_algorithm_interface.h
index 2e61c9e1..df72e05 100644
--- a/net/quic/congestion_control/send_algorithm_interface.h
+++ b/net/quic/congestion_control/send_algorithm_interface.h
@@ -23,16 +23,30 @@ class NET_EXPORT_PRIVATE SendAlgorithmInterface {
public:
class SentPacket {
public:
- SentPacket(QuicByteCount bytes, QuicTime timestamp)
+ SentPacket(QuicByteCount bytes,
+ QuicTime timestamp,
+ HasRetransmittableData has_retransmittable_data)
: bytes_sent_(bytes),
- send_timestamp_(timestamp) {
+ send_timestamp_(timestamp),
+ has_retransmittable_data_(has_retransmittable_data),
+ nack_count_(0) {
+ }
+ QuicByteCount bytes_sent() const { return bytes_sent_; }
+ const QuicTime& send_timestamp() const { return send_timestamp_; }
+ HasRetransmittableData has_retransmittable_data() const {
+ return has_retransmittable_data_;
+ }
+ size_t nack_count() const { return nack_count_; }
+
+ void Nack() {
+ ++nack_count_;
}
- QuicByteCount BytesSent() { return bytes_sent_; }
- QuicTime& SendTimestamp() { return send_timestamp_; }
private:
QuicByteCount bytes_sent_;
QuicTime send_timestamp_;
+ HasRetransmittableData has_retransmittable_data_;
+ size_t nack_count_;
};
typedef std::map<QuicPacketSequenceNumber, SentPacket*> SentPacketsMap;
@@ -44,6 +58,9 @@ class NET_EXPORT_PRIVATE SendAlgorithmInterface {
virtual void SetFromConfig(const QuicConfig& config, bool is_server) = 0;
+ // Sets the maximum size of packets that will be sent.
+ virtual void SetMaxPacketSize(QuicByteCount max_packet_size) = 0;
+
// Called when we receive congestion feedback from remote peer.
virtual void OnIncomingQuicCongestionFeedbackFrame(
const QuicCongestionFeedbackFrame& feedback,
@@ -55,9 +72,9 @@ class NET_EXPORT_PRIVATE SendAlgorithmInterface {
QuicByteCount acked_bytes,
QuicTime::Delta rtt) = 0;
- // Indicates a loss event of one or more packets. |largest_loss| is the
- // largest packet lost in this event.
- virtual void OnIncomingLoss(QuicPacketSequenceNumber largest_loss,
+ // Indicates a loss event of one packet. |sequence_number| is the
+ // sequence number of the lost packet.
+ virtual void OnIncomingLoss(QuicPacketSequenceNumber sequence_number,
QuicTime ack_receive_time) = 0;
// Inform that we sent x bytes to the wire, and if that was a retransmission.
@@ -71,6 +88,9 @@ class NET_EXPORT_PRIVATE SendAlgorithmInterface {
TransmissionType transmission_type,
HasRetransmittableData is_retransmittable) = 0;
+ // Called when the retransmission timeout fires.
+ virtual void OnRetransmissionTimeout() = 0;
+
// Called when a packet is timed out.
virtual void OnPacketAbandoned(QuicPacketSequenceNumber sequence_number,
QuicByteCount abandoned_bytes) = 0;
diff --git a/net/quic/congestion_control/tcp_cubic_sender.cc b/net/quic/congestion_control/tcp_cubic_sender.cc
index c52524e..346cb73 100644
--- a/net/quic/congestion_control/tcp_cubic_sender.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender.cc
@@ -22,6 +22,7 @@ const QuicByteCount kMaxSegmentSize = kDefaultTCPMSS;
const QuicByteCount kDefaultReceiveWindow = 64000;
const int64 kInitialCongestionWindow = 10;
const int kMaxBurstLength = 3;
+// Constants used for RTT calculation.
const int kInitialRttMs = 60; // At a typical RTT 60 ms.
const float kAlpha = 0.125f;
const float kOneMinusAlpha = (1 - kAlpha);
@@ -57,10 +58,12 @@ TcpCubicSender::~TcpCubicSender() {
UMA_HISTOGRAM_COUNTS("Net.QuicSession.FinalTcpCwnd", congestion_window_);
}
+void TcpCubicSender::SetMaxPacketSize(QuicByteCount /*max_packet_size*/) {
+}
+
void TcpCubicSender::SetFromConfig(const QuicConfig& config, bool is_server) {
if (is_server) {
// Set the initial window size.
- // Ignoring the max packet size and always using TCP's default MSS.
congestion_window_ = config.server_initial_congestion_window();
}
}
@@ -100,12 +103,12 @@ void TcpCubicSender::OnIncomingAck(
}
}
-void TcpCubicSender::OnIncomingLoss(QuicPacketSequenceNumber largest_loss,
+void TcpCubicSender::OnIncomingLoss(QuicPacketSequenceNumber sequence_number,
QuicTime /*ack_receive_time*/) {
// TCP NewReno (RFC6582) says that once a loss occurs, any losses in packets
// already sent should be treated as a single loss event, since it's expected.
- if (largest_loss <= largest_sent_at_last_cutback_) {
- DLOG(INFO) << "Ignoring loss for largest_missing:" << largest_loss
+ if (sequence_number <= largest_sent_at_last_cutback_) {
+ DLOG(INFO) << "Ignoring loss for largest_missing:" << sequence_number
<< " because it was sent prior to the last CWND cutback.";
return;
}
@@ -140,8 +143,11 @@ bool TcpCubicSender::OnPacketSent(QuicTime /*sent_time*/,
}
bytes_in_flight_ += bytes;
- DCHECK_LT(largest_sent_sequence_number_, sequence_number);
- largest_sent_sequence_number_ = sequence_number;
+ if (largest_sent_sequence_number_ < sequence_number) {
+ // TODO(rch): Ensure that packets are really sent in order.
+ // DCHECK_LT(largest_sent_sequence_number_, sequence_number);
+ largest_sent_sequence_number_ = sequence_number;
+ }
if (transmission_type == NOT_RETRANSMISSION && update_end_sequence_number_) {
end_sequence_number_ = sequence_number;
if (AvailableSendWindow() == 0) {
@@ -153,7 +159,7 @@ bool TcpCubicSender::OnPacketSent(QuicTime /*sent_time*/,
}
void TcpCubicSender::OnPacketAbandoned(QuicPacketSequenceNumber sequence_number,
- QuicByteCount abandoned_bytes) {
+ QuicByteCount abandoned_bytes) {
DCHECK_GE(bytes_in_flight_, abandoned_bytes);
bytes_in_flight_ -= abandoned_bytes;
}
@@ -274,10 +280,9 @@ void TcpCubicSender::CongestionAvoidance(QuicPacketSequenceNumber ack) {
}
}
-// TODO(pwestin): what is the timout value?
-void TcpCubicSender::OnTimeOut() {
+void TcpCubicSender::OnRetransmissionTimeout() {
cubic_.Reset();
- congestion_window_ = 1;
+ congestion_window_ = kMinimumCongestionWindow;
}
void TcpCubicSender::AckAccounting(QuicTime::Delta rtt) {
diff --git a/net/quic/congestion_control/tcp_cubic_sender.h b/net/quic/congestion_control/tcp_cubic_sender.h
index 82befbf..b233fa3 100644
--- a/net/quic/congestion_control/tcp_cubic_sender.h
+++ b/net/quic/congestion_control/tcp_cubic_sender.h
@@ -35,9 +35,9 @@ class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface {
QuicTcpCongestionWindow max_tcp_congestion_window);
virtual ~TcpCubicSender();
- virtual void SetFromConfig(const QuicConfig& config, bool is_server) OVERRIDE;
-
// Start implementation of SendAlgorithmInterface.
+ virtual void SetFromConfig(const QuicConfig& config, bool is_server) OVERRIDE;
+ virtual void SetMaxPacketSize(QuicByteCount max_packet_size) OVERRIDE;
virtual void OnIncomingQuicCongestionFeedbackFrame(
const QuicCongestionFeedbackFrame& feedback,
QuicTime feedback_receive_time,
@@ -52,6 +52,7 @@ class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface {
QuicByteCount bytes,
TransmissionType transmission_type,
HasRetransmittableData is_retransmittable) OVERRIDE;
+ virtual void OnRetransmissionTimeout() OVERRIDE;
virtual void OnPacketAbandoned(QuicPacketSequenceNumber sequence_number,
QuicByteCount abandoned_bytes) OVERRIDE;
virtual QuicTime::Delta TimeUntilSend(
diff --git a/net/quic/congestion_control/tcp_cubic_sender_test.cc b/net/quic/congestion_control/tcp_cubic_sender_test.cc
index 42c8bb8..1b0fc25 100644
--- a/net/quic/congestion_control/tcp_cubic_sender_test.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender_test.cc
@@ -236,6 +236,14 @@ TEST_F(TcpCubicSenderTest, SlowStartPacketLoss) {
EXPECT_EQ(expected_send_window, sender_->SendWindow());
}
+TEST_F(TcpCubicSenderTest, RTOCongestionWindow) {
+ EXPECT_EQ(kDefaultWindowTCP, sender_->SendWindow());
+
+ // Expect the window to decrease to the minimum once the RTO fires.
+ sender_->OnRetransmissionTimeout();
+ EXPECT_EQ(2 * kDefaultTCPMSS, sender_->SendWindow());
+}
+
TEST_F(TcpCubicSenderTest, RetransmissionDelay) {
const int64 kRttMs = 10;
const int64 kDeviationMs = 3;
diff --git a/net/quic/crypto/crypto_protocol.h b/net/quic/crypto/crypto_protocol.h
index a064418..bb67f17 100644
--- a/net/quic/crypto/crypto_protocol.h
+++ b/net/quic/crypto/crypto_protocol.h
@@ -45,6 +45,7 @@ const QuicTag kAESG = TAG('A', 'E', 'S', 'G'); // AES128 + GCM-12
// Congestion control feedback types
const QuicTag kQBIC = TAG('Q', 'B', 'I', 'C'); // TCP cubic
+const QuicTag kPACE = TAG('P', 'A', 'C', 'E'); // Paced TCP cubic
const QuicTag kINAR = TAG('I', 'N', 'A', 'R'); // Inter arrival
// Proof types (i.e. certificate types)
@@ -71,7 +72,6 @@ const QuicTag kMSPC = TAG('M', 'S', 'P', 'C'); // Max streams per connection.
const QuicTag kIRTT = TAG('I', 'R', 'T', 'T'); // Estimated initial RTT in us.
const QuicTag kSWND = TAG('S', 'W', 'N', 'D'); // Server's Initial congestion
// window.
-const QuicTag kSMSS = TAG('S', 'M', 'S', 'S'); // Server's maximum packet size.
const QuicTag kSNI = TAG('S', 'N', 'I', '\0'); // Server name
// indication
const QuicTag kPUBS = TAG('P', 'U', 'B', 'S'); // Public key values
diff --git a/net/quic/quic_config.cc b/net/quic/quic_config.cc
index 3fa8211..f9fcbfc 100644
--- a/net/quic/quic_config.cc
+++ b/net/quic/quic_config.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include "base/logging.h"
+#include "net/quic/congestion_control/quic_congestion_manager.h"
using std::string;
@@ -229,12 +230,10 @@ QuicConfig::QuicConfig() :
max_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
server_initial_congestion_window_(
kSWND, QuicNegotiableValue::PRESENCE_OPTIONAL),
- server_max_packet_size_(kSMSS, QuicNegotiableValue::PRESENCE_OPTIONAL),
initial_round_trip_time_us_(kIRTT, QuicNegotiableValue::PRESENCE_OPTIONAL) {
// All optional non-zero parameters should be initialized here.
server_initial_congestion_window_.set(kMaxInitialWindow,
kDefaultInitialWindow);
- server_max_packet_size_.set(kMaxPacketSize, kDefaultMaxPacketSize);
}
QuicConfig::~QuicConfig() {}
@@ -295,15 +294,6 @@ uint32 QuicConfig::server_initial_congestion_window() const {
return server_initial_congestion_window_.GetUint32();
}
-void QuicConfig::set_server_max_packet_size(size_t max_bytes,
- size_t default_bytes) {
- server_max_packet_size_.set(max_bytes, default_bytes);
-}
-
-uint32 QuicConfig::server_max_packet_size() const {
- return server_max_packet_size_.GetUint32();
-}
-
void QuicConfig::set_initial_round_trip_time_us(size_t max_rtt,
size_t default_rtt) {
initial_round_trip_time_us_.set(max_rtt, default_rtt);
@@ -322,12 +312,16 @@ bool QuicConfig::negotiated() {
keepalive_timeout_seconds_.negotiated() &&
max_streams_per_connection_.negotiated() &&
server_initial_congestion_window_.negotiated() &&
- server_max_packet_size_.negotiated() &&
initial_round_trip_time_us_.negotiated();
}
void QuicConfig::SetDefaults() {
- congestion_control_.set(QuicTagVector(1, kQBIC), kQBIC);
+ QuicTagVector congestion_control;
+ if (FLAGS_enable_quic_pacing) {
+ congestion_control.push_back(kPACE);
+ }
+ congestion_control.push_back(kQBIC);
+ congestion_control_.set(congestion_control, kQBIC);
idle_connection_state_lifetime_seconds_.set(kDefaultTimeoutSecs,
kDefaultInitialTimeoutSecs);
// kKATO is optional. Return 0 if not negotiated.
@@ -338,7 +332,6 @@ void QuicConfig::SetDefaults() {
kDefaultMaxTimeForCryptoHandshakeSecs);
server_initial_congestion_window_.set(kMaxInitialWindow,
kDefaultInitialWindow);
- server_max_packet_size_.set(kMaxPacketSize, kDefaultMaxPacketSize);
}
void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
@@ -347,7 +340,6 @@ void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
keepalive_timeout_seconds_.ToHandshakeMessage(out);
max_streams_per_connection_.ToHandshakeMessage(out);
server_initial_congestion_window_.ToHandshakeMessage(out);
- server_max_packet_size_.ToHandshakeMessage(out);
// TODO(ianswett): Don't transmit parameters which are optional and not set.
initial_round_trip_time_us_.ToHandshakeMessage(out);
}
@@ -378,10 +370,6 @@ QuicErrorCode QuicConfig::ProcessClientHello(
client_hello, error_details);
}
if (error == QUIC_NO_ERROR) {
- error = server_max_packet_size_.ProcessClientHello(
- client_hello, error_details);
- }
- if (error == QUIC_NO_ERROR) {
error = initial_round_trip_time_us_.ProcessClientHello(
client_hello, error_details);
}
@@ -414,10 +402,6 @@ QuicErrorCode QuicConfig::ProcessServerHello(
server_hello, error_details);
}
if (error == QUIC_NO_ERROR) {
- error = server_max_packet_size_.ProcessServerHello(
- server_hello, error_details);
- }
- if (error == QUIC_NO_ERROR) {
error = initial_round_trip_time_us_.ProcessServerHello(
server_hello, error_details);
}
diff --git a/net/quic/quic_config.h b/net/quic/quic_config.h
index 9328c67..2632212 100644
--- a/net/quic/quic_config.h
+++ b/net/quic/quic_config.h
@@ -167,11 +167,6 @@ class NET_EXPORT_PRIVATE QuicConfig {
uint32 server_initial_congestion_window() const;
- // Sets the server's max packet size and default max packet size in bytes.
- void set_server_max_packet_size(size_t max_bytes, size_t default_bytes);
-
- uint32 server_max_packet_size() const;
-
// Sets an estimated initial round trip time in us.
void set_initial_round_trip_time_us(size_t max_rtt, size_t default_rtt);
@@ -210,8 +205,6 @@ class NET_EXPORT_PRIVATE QuicConfig {
QuicTime::Delta max_time_before_crypto_handshake_;
// Initial congestion window in packets.
QuicNegotiableUint32 server_initial_congestion_window_;
- // Maximum packet size for the server to send in bytes.
- QuicNegotiableUint32 server_max_packet_size_;
// Initial round trip time estimate in microseconds.
QuicNegotiableUint32 initial_round_trip_time_us_;
};
diff --git a/net/quic/quic_config_test.cc b/net/quic/quic_config_test.cc
index c7ed364..1529672 100644
--- a/net/quic/quic_config_test.cc
+++ b/net/quic/quic_config_test.cc
@@ -4,10 +4,12 @@
#include "net/quic/quic_config.h"
+#include "net/quic/congestion_control/quic_congestion_manager.h"
#include "net/quic/crypto/crypto_handshake.h"
#include "net/quic/crypto/crypto_protocol.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_time.h"
+#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
using std::string;
@@ -49,6 +51,21 @@ TEST_F(QuicConfigTest, ToHandshakeMessage) {
EXPECT_EQ(kQBIC, *out);
}
+TEST_F(QuicConfigTest, ToHandshakeMessageWithPacing) {
+ ValueRestore<bool> old_flag(&FLAGS_enable_quic_pacing, true);
+
+ config_.SetDefaults();
+ CryptoHandshakeMessage msg;
+ config_.ToHandshakeMessage(&msg);
+
+ const QuicTag* out;
+ size_t out_len;
+ EXPECT_EQ(QUIC_NO_ERROR, msg.GetTaglist(kCGST, &out, &out_len));
+ EXPECT_EQ(2u, out_len);
+ EXPECT_EQ(kPACE, out[0]);
+ EXPECT_EQ(kQBIC, out[1]);
+}
+
TEST_F(QuicConfigTest, ProcessClientHello) {
QuicConfig client_config;
QuicTagVector cgst;
@@ -91,8 +108,6 @@ TEST_F(QuicConfigTest, ProcessServerHello) {
server_config.set_max_streams_per_connection(
kDefaultMaxStreamsPerConnection / 2,
kDefaultMaxStreamsPerConnection / 2);
- server_config.set_server_max_packet_size(kDefaultMaxPacketSize / 2,
- kDefaultMaxPacketSize / 2);
server_config.set_server_initial_congestion_window(kDefaultInitialWindow / 2,
kDefaultInitialWindow / 2);
server_config.set_initial_round_trip_time_us(
@@ -110,7 +125,6 @@ TEST_F(QuicConfigTest, ProcessServerHello) {
config_.idle_connection_state_lifetime());
EXPECT_EQ(kDefaultMaxStreamsPerConnection / 2,
config_.max_streams_per_connection());
- EXPECT_EQ(kDefaultMaxPacketSize / 2, config_.server_max_packet_size());
EXPECT_EQ(kDefaultInitialWindow / 2,
config_.server_initial_congestion_window());
EXPECT_EQ(QuicTime::Delta::FromSeconds(0), config_.keepalive_timeout());
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index b1d7fba..a97f513 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -53,16 +53,6 @@ namespace {
// This will likely have to be tuned.
const QuicPacketSequenceNumber kMaxPacketGap = 5000;
-// We want to make sure if we get a nack packet which triggers several
-// retransmissions, we don't queue up too many packets. 10 is TCP's default
-// initial congestion window(RFC 6928).
-const size_t kMaxRetransmissionsPerAck = kDefaultInitialWindow;
-
-// TCP retransmits after 3 nacks.
-// TODO(ianswett): Change to match TCP's rule of retransmitting once an ack
-// at least 3 sequence numbers larger arrives.
-const size_t kNumberOfNacksBeforeRetransmission = 3;
-
// Limit the number of FEC groups to two. If we get enough out of order packets
// that this becomes limiting, we can revisit.
const size_t kMaxFecGroups = 2;
@@ -234,11 +224,14 @@ QuicConnection::QuicConnection(QuicGuid guid,
congestion_manager_(clock_, kTCP),
sent_packet_manager_(is_server, this),
version_negotiation_state_(START_NEGOTIATION),
- consecutive_rto_count_(0),
is_server_(is_server),
connected_(true),
received_truncated_ack_(false),
address_migrating_(false) {
+ if (!is_server_) {
+ // Pacing will be enabled if the client negotiates it.
+ congestion_manager_.MaybeEnablePacing();
+ }
DLOG(INFO) << ENDPOINT << "Created connection with guid: " << guid;
timeout_alarm_->Set(clock_->ApproximateNow().Add(idle_network_timeout_));
framer_.set_visitor(this);
@@ -255,14 +248,8 @@ QuicConnection::~QuicConnection() {
}
void QuicConnection::SetFromConfig(const QuicConfig& config) {
- DCHECK_LT(0u, config.server_max_packet_size());
DCHECK_LT(0u, config.server_initial_congestion_window());
SetIdleNetworkTimeout(config.idle_connection_state_lifetime());
- // Set the max packet length only when QUIC_VERSION_12 or later is supported,
- // with explicitly truncated acks.
- if (version() > QUIC_VERSION_11 && is_server_) {
- options()->max_packet_length = config.server_max_packet_size();
- }
congestion_manager_.SetFromConfig(config, is_server_);
// TODO(satyamshekhar): Set congestion control and ICSL also.
}
@@ -538,7 +525,6 @@ void QuicConnection::ProcessAckFrame(const QuicAckFrame& incoming_ack) {
sent_entropy_manager_.ClearEntropyBefore(
received_packet_manager_.least_packet_awaited_by_peer() - 1);
- retransmitted_nacked_packet_count_ = 0;
sent_packet_manager_.OnIncomingAck(incoming_ack.received_info,
received_truncated_ack_);
@@ -546,10 +532,18 @@ void QuicConnection::ProcessAckFrame(const QuicAckFrame& incoming_ack) {
QuicPacketSequenceNumber least_unacked_sent_after =
sent_packet_manager_.GetLeastUnackedSentPacket();
+ SequenceNumberSet retransmission_packets =
+ congestion_manager_.OnIncomingAckFrame(incoming_ack,
+ time_of_last_received_packet_);
+
+ for (SequenceNumberSet::const_iterator it = retransmission_packets.begin();
+ it != retransmission_packets.end(); ++it) {
+ RetransmitPacket(*it, NACK_RETRANSMISSION);
+ }
+
// Used to set RTO and FEC alarms.
QuicTime::Delta retransmission_delay =
- congestion_manager_.GetRetransmissionDelay(
- sent_packet_manager_.GetNumRetransmittablePackets(), 0);
+ congestion_manager_.GetRetransmissionDelay();
// If there are outstanding packets, and the least unacked sequence number
// has increased after processing this latest AckFrame, then reschedule the
@@ -561,7 +555,7 @@ void QuicConnection::ProcessAckFrame(const QuicAckFrame& incoming_ack) {
}
retransmission_alarm_->Set(
clock_->ApproximateNow().Add(retransmission_delay));
- consecutive_rto_count_ = 0;
+ congestion_manager_.OnLeastUnackedIncreased();
} else if (!sent_packet_manager_.HasUnackedPackets()) {
retransmission_alarm_->Cancel();
}
@@ -574,9 +568,6 @@ void QuicConnection::ProcessAckFrame(const QuicAckFrame& incoming_ack) {
least_unacked_sent_before < least_unacked_sent_after) {
abandon_fec_alarm_->Set(clock_->ApproximateNow().Add(retransmission_delay));
}
-
- congestion_manager_.OnIncomingAckFrame(incoming_ack,
- time_of_last_received_packet_);
}
bool QuicConnection::OnCongestionFeedbackFrame(
@@ -1031,6 +1022,14 @@ bool QuicConnection::ProcessValidatedPacket() {
time_of_last_received_packet_ = clock_->Now();
DVLOG(1) << ENDPOINT << "time of last received packet: "
<< time_of_last_received_packet_.ToDebuggingValue();
+
+ // Set the max packet length only when QUIC_VERSION_12 or later is supported,
+ // with explicitly truncated acks.
+ if (version() > QUIC_VERSION_11 && is_server_ &&
+ encryption_level_ == ENCRYPTION_NONE &&
+ last_size_ > options()->max_packet_length) {
+ options()->max_packet_length = last_size_;
+ }
return true;
}
@@ -1161,9 +1160,16 @@ bool QuicConnection::ShouldGeneratePacket(
bool QuicConnection::CanWrite(TransmissionType transmission_type,
HasRetransmittableData retransmittable,
IsHandshake handshake) {
+ if (write_blocked_) {
+ return false;
+ }
+
+ // TODO(rch): consider removing this check so that if an ACK comes in
+ // before the alarm goes it, we might be able send out a packet.
// This check assumes that if the send alarm is set, it applies equally to all
// types of transmissions.
- if (write_blocked_ || send_alarm_->IsSet()) {
+ if (send_alarm_->IsSet()) {
+ DLOG(INFO) << "Send alarm set. Not sending.";
return false;
}
@@ -1178,6 +1184,7 @@ bool QuicConnection::CanWrite(TransmissionType transmission_type,
if (!delay.IsZero()) {
send_alarm_->Cancel();
send_alarm_->Set(now.Add(delay));
+ DLOG(INFO) << "Delaying sending.";
return false;
}
return true;
@@ -1198,9 +1205,7 @@ void QuicConnection::SetupRetransmission(
}
QuicTime::Delta retransmission_delay =
- congestion_manager_.GetRetransmissionDelay(
- sent_packet_manager_.GetNumRetransmittablePackets(),
- consecutive_rto_count_);
+ congestion_manager_.GetRetransmissionDelay();
retransmission_alarm_->Set(
clock_->ApproximateNow().Add(retransmission_delay));
}
@@ -1211,9 +1216,7 @@ void QuicConnection::SetupAbandonFecTimer(
return;
}
QuicTime::Delta retransmission_delay =
- congestion_manager_.GetRetransmissionDelay(
- sent_packet_manager_.GetNumRetransmittablePackets(),
- consecutive_rto_count_);
+ congestion_manager_.GetRetransmissionDelay();
abandon_fec_alarm_->Set(clock_->ApproximateNow().Add(retransmission_delay));
}
@@ -1267,9 +1270,9 @@ bool QuicConnection::WritePacket(EncryptionLevel level,
}
if (encrypted->length() > options()->max_packet_length) {
- LOG(DFATAL) << ENDPOINT
- << "Writing an encrypted packet larger than max_packet_length:"
- << options()->max_packet_length;
+ LOG(DFATAL) << "Writing an encrypted packet larger than max_packet_length:"
+ << options()->max_packet_length << " encrypted length: "
+ << encrypted->length();
}
DLOG(INFO) << ENDPOINT << "Sending packet number " << sequence_number
<< " : " << (packet->is_fec_packet() ? "FEC " :
@@ -1462,15 +1465,6 @@ QuicPacketSequenceNumber QuicConnection::GetNextPacketSequenceNumber() {
return packet_creator_.sequence_number() + 1;
}
-void QuicConnection::OnPacketNacked(QuicPacketSequenceNumber sequence_number,
- size_t nack_count) {
- if (nack_count >= kNumberOfNacksBeforeRetransmission &&
- retransmitted_nacked_packet_count_ < kMaxRetransmissionsPerAck) {
- ++retransmitted_nacked_packet_count_;
- RetransmitPacket(sequence_number, NACK_RETRANSMISSION);
- }
-}
-
bool QuicConnection::SendOrQueuePacket(EncryptionLevel level,
const SerializedPacket& packet,
TransmissionType transmission_type) {
@@ -1522,7 +1516,8 @@ void QuicConnection::OnRetransmissionTimeout() {
// TODO(ianswett): When an RTO fires, but the connection has not been
// established as forward secure, re-send the client hello first.
++stats_.rto_count;
- ++consecutive_rto_count_;
+
+ congestion_manager_.OnRetransmissionTimeout();
// Attempt to send all the unacked packets when the RTO fires, let the
// congestion manager decide how many to send immediately and the remaining
@@ -1561,9 +1556,7 @@ QuicTime QuicConnection::OnAbandonFecTimeout() {
// Abandon all the FEC packets older than the current RTO, then reschedule
// the alarm if there are more pending fec packets.
QuicTime::Delta retransmission_delay =
- congestion_manager_.GetRetransmissionDelay(
- sent_packet_manager_.GetNumRetransmittablePackets(),
- consecutive_rto_count_);
+ congestion_manager_.GetRetransmissionDelay();
QuicTime max_send_time =
clock_->ApproximateNow().Subtract(retransmission_delay);
bool abandoned_packet = false;
diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h
index 501ade9..ca3ace0 100644
--- a/net/quic/quic_connection.h
+++ b/net/quic/quic_connection.h
@@ -303,8 +303,6 @@ class NET_EXPORT_PRIVATE QuicConnection
// QuicSentPacketManager::HelperInterface
virtual QuicPacketSequenceNumber GetNextPacketSequenceNumber() OVERRIDE;
- virtual void OnPacketNacked(QuicPacketSequenceNumber sequence_number,
- size_t nack_count) OVERRIDE;
// Accessors
void set_visitor(QuicConnectionVisitorInterface* visitor) {
@@ -369,11 +367,11 @@ class NET_EXPORT_PRIVATE QuicConnection
// by the same policy as the RTO alarm, but is a separate alarm.
QuicTime OnAbandonFecTimeout();
- // Retransmits unacked packets which were sent with initial encryption, if
- // |initial_encryption_only| is true, otherwise retransmits all unacked
- // packets. Used when the negotiated protocol version is different than what
- // was initially assumed and when the visitor wants to re-transmit packets
- // with initial encryption when the initial encrypter changes.
+ // Retransmits all unacked packets with retransmittable frames if
+ // |retransmission_type| is ALL_PACKETS, otherwise retransmits only initially
+ // encrypted packets. Used when the negotiated protocol version is different
+ // from what was initially assumed and when the visitor wants to re-transmit
+ // initially encrypted packets when the initial encrypter changes.
void RetransmitUnackedPackets(RetransmissionType retransmission_type);
// Changes the encrypter used for level |level| to |encrypter|. The function
@@ -670,9 +668,6 @@ class NET_EXPORT_PRIVATE QuicConnection
std::vector<QuicRstStreamFrame> last_rst_frames_;
std::vector<QuicGoAwayFrame> last_goaway_frames_;
std::vector<QuicConnectionCloseFrame> last_close_frames_;
- // Then number of packets retransmitted because of nacks
- // while processed the current ack frame.
- size_t retransmitted_nacked_packet_count_;
QuicCongestionFeedbackFrame outgoing_congestion_feedback_;
@@ -762,9 +757,6 @@ class NET_EXPORT_PRIVATE QuicConnection
// The state of connection in version negotiation finite state machine.
QuicVersionNegotiationState version_negotiation_state_;
- // Number of times the RTO timer has fired in a row without receiving an ack.
- size_t consecutive_rto_count_;
-
// Tracks if the connection was created by the server.
bool is_server_;
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc
index a44b013..e5719e1 100644
--- a/net/quic/quic_connection_test.cc
+++ b/net/quic/quic_connection_test.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/stl_util.h"
#include "net/base/net_errors.h"
+#include "net/quic/congestion_control/quic_congestion_manager.h"
#include "net/quic/congestion_control/receive_algorithm_interface.h"
#include "net/quic/congestion_control/send_algorithm_interface.h"
#include "net/quic/crypto/null_encrypter.h"
@@ -929,7 +930,6 @@ TEST_F(QuicConnectionTest, TruncatedAck) {
}
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(*send_algorithm_, OnIncomingAck(_, _, _)).Times(256);
- EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_, _)).Times(2);
int num_packets = 256 * 2 + 1;
for (int i = 0; i < num_packets; ++i) {
SendStreamDataToPeer(1, "foo", i * 3, !kFin, NULL);
@@ -1326,19 +1326,21 @@ TEST_F(QuicConnectionTest, DontAbandonAckedFEC) {
QuicAckFrame ack_fec(2, QuicTime::Zero(), 1);
// Data packet missing.
+ // TODO(ianswett): Note that this is not a sensible ack, since if the FEC was
+ // received, it would cause the covered packet to be acked as well.
ack_fec.received_info.missing_packets.insert(1);
ack_fec.received_info.entropy_hash =
QuicConnectionPeer::GetSentEntropyHash(&connection_, 2) ^
QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
EXPECT_CALL(*send_algorithm_, OnIncomingAck(_, _, _)).Times(1);
- EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_, _)).Times(1);
ProcessAckPacket(&ack_fec);
clock_.AdvanceTime(DefaultRetransmissionTime());
// Abandon only data packet, FEC has been acked.
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(sequence_number, _)).Times(1);
// Send only data packet.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
@@ -1719,6 +1721,7 @@ TEST_F(QuicConnectionTest, QueueAfterTwoRTOs) {
writer_->set_blocked(true);
clock_.AdvanceTime(DefaultRetransmissionTime());
// Only one packet should be retransmitted.
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(10);
connection_.GetRetransmissionAlarm()->Fire();
EXPECT_TRUE(connection_.HasQueuedData());
@@ -1761,7 +1764,6 @@ TEST_F(QuicConnectionTest, ResumptionAlarmThenWriteBlocked) {
TEST_F(QuicConnectionTest, LimitPacketsPerNack) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(*send_algorithm_, OnIncomingAck(12, _, _)).Times(1);
- EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_, _)).Times(1);
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(11);
int offset = 0;
// Send packets 1 to 12.
@@ -1784,10 +1786,12 @@ TEST_F(QuicConnectionTest, LimitPacketsPerNack) {
ProcessAckPacket(&nack);
ProcessAckPacket(&nack);
// The third call should trigger retransmitting 10 packets.
+ EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_, _)).Times(10);
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(10);
ProcessAckPacket(&nack);
// The fourth call should trigger retransmitting the 11th packet.
+ EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_, _)).Times(1);
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
ProcessAckPacket(&nack);
}
@@ -1795,7 +1799,6 @@ TEST_F(QuicConnectionTest, LimitPacketsPerNack) {
// Test sending multiple acks from the connection to the session.
TEST_F(QuicConnectionTest, MultipleAcks) {
EXPECT_CALL(*send_algorithm_, OnIncomingAck(_, _, _)).Times(6);
- EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_, _)).Times(1);
QuicPacketSequenceNumber last_packet;
SendStreamDataToPeer(1, "foo", 0, !kFin, &last_packet); // Packet 1
EXPECT_EQ(1u, last_packet);
@@ -2006,6 +2009,7 @@ TEST_F(QuicConnectionTest,
new TaggingEncrypter(0x02));
connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(sequence_number, _)).Times(1);
@@ -2077,6 +2081,7 @@ TEST_F(QuicConnectionTest, TestRetransmitOrder) {
EXPECT_NE(first_packet_size, second_packet_size);
// Advance the clock by huge time to make sure packets will be retransmitted.
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(10));
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(2);
{
InSequence s;
@@ -2089,6 +2094,7 @@ TEST_F(QuicConnectionTest, TestRetransmitOrder) {
// Advance again and expect the packets to be sent again in the same order.
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(20));
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(2);
{
InSequence s;
@@ -2100,7 +2106,7 @@ TEST_F(QuicConnectionTest, TestRetransmitOrder) {
connection_.GetRetransmissionAlarm()->Fire();
}
-TEST_F(QuicConnectionTest, TestRetransmissionTracking) {
+TEST_F(QuicConnectionTest, RetransmissionCountCalculation) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
QuicPacketSequenceNumber original_sequence_number;
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, NOT_RETRANSMISSION, _))
@@ -2113,6 +2119,7 @@ TEST_F(QuicConnectionTest, TestRetransmissionTracking) {
&connection_, original_sequence_number));
// Force retransmission due to RTO.
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(10));
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
EXPECT_CALL(*send_algorithm_,
OnPacketAbandoned(original_sequence_number, _)).Times(1);
QuicPacketSequenceNumber rto_sequence_number;
@@ -2191,6 +2198,7 @@ TEST_F(QuicConnectionTest, DelayRTOWithAckReceipt) {
EXPECT_GE(retransmission_alarm->deadline(), clock_.ApproximateNow());
clock_.AdvanceTime(DefaultRetransmissionTime());
EXPECT_LT(retransmission_alarm->deadline(), clock_.ApproximateNow());
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, RTO_RETRANSMISSION, _));
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _));
// Manually cancel the alarm to simulate a real test.
@@ -2201,7 +2209,7 @@ TEST_F(QuicConnectionTest, DelayRTOWithAckReceipt) {
EXPECT_TRUE(retransmission_alarm->IsSet());
QuicTime next_rto_time = retransmission_alarm->deadline();
QuicTime::Delta expected_rto =
- connection_.congestion_manager().GetRetransmissionDelay(1, 1);
+ connection_.congestion_manager().GetRetransmissionDelay();
EXPECT_EQ(next_rto_time, clock_.ApproximateNow().Add(expected_rto));
}
@@ -2410,6 +2418,7 @@ TEST_F(QuicConnectionTest, SendSchedulerDelayThenRetransmit) {
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(501));
// Test that if we send a retransmit with a delay, it ends up queued in the
// sent packet manager, but not yet serialized.
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
EXPECT_CALL(*send_algorithm_,
TimeUntilSend(_, RTO_RETRANSMISSION, _, _)).WillOnce(
testing::Return(QuicTime::Delta::FromMicroseconds(1)));
@@ -2950,6 +2959,7 @@ TEST_F(QuicConnectionTest, CheckSendStats) {
size_t second_packet_size = last_sent_packet_size();
// 2 retransmissions due to rto, 1 due to explicit nack.
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
EXPECT_CALL(*send_algorithm_,
OnPacketSent(_, _, _, RTO_RETRANSMISSION, _)).Times(2);
EXPECT_CALL(*send_algorithm_,
@@ -3163,7 +3173,6 @@ TEST_F(QuicConnectionTest, AckNotifierFailToTriggerCallback) {
EXPECT_CALL(delegate, OnAckNotification()).Times(0);;
EXPECT_CALL(*send_algorithm_, OnIncomingAck(_, _, _)).Times(2);
- EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_, _)).Times(1);
// Send some data, which will register the delegate to be notified. This will
// not be ACKed and so the delegate should never be called.
@@ -3190,9 +3199,6 @@ TEST_F(QuicConnectionTest, AckNotifierCallbackAfterRetransmission) {
// In total expect ACKs for all 4 packets.
EXPECT_CALL(*send_algorithm_, OnIncomingAck(_, _, _)).Times(4);
- // We will lose the second packet.
- EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_, _)).Times(1);
-
// Send four packets, and register to be notified on ACK of packet 2.
connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
connection_.SendStreamDataWithString(1, "bar", 0, !kFin, &delegate);
@@ -3206,6 +3212,7 @@ TEST_F(QuicConnectionTest, AckNotifierCallbackAfterRetransmission) {
// Advance time to trigger RTO, for packet 2 (which should be retransmitted as
// packet 5).
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(2, _)).Times(1);
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
@@ -3324,6 +3331,17 @@ TEST_F(QuicConnectionTest, OnPacketHeaderDebugVisitor) {
connection_.OnPacketHeader(header);
}
+TEST_F(QuicConnectionTest, Pacing) {
+ ValueRestore<bool> old_flag(&FLAGS_enable_quic_pacing, true);
+
+ TestConnection server(guid_, IPEndPoint(), helper_.get(), writer_.get(),
+ true);
+ TestConnection client(guid_, IPEndPoint(), helper_.get(), writer_.get(),
+ false);
+ EXPECT_TRUE(client.congestion_manager().using_pacing());
+ EXPECT_FALSE(server.congestion_manager().using_pacing());
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/net/quic/quic_packet_creator_test.cc b/net/quic/quic_packet_creator_test.cc
index 8db5853..9435e0a 100644
--- a/net/quic/quic_packet_creator_test.cc
+++ b/net/quic/quic_packet_creator_test.cc
@@ -27,25 +27,6 @@ namespace net {
namespace test {
namespace {
-template<typename SaveType>
-class ValueRestore {
- public:
- ValueRestore(SaveType* name, SaveType value)
- : name_(name),
- value_(*name) {
- *name_ = value;
- }
- ~ValueRestore() {
- *name_ = value_;
- }
-
- private:
- SaveType* name_;
- SaveType value_;
-
- DISALLOW_COPY_AND_ASSIGN(ValueRestore);
-};
-
class QuicPacketCreatorTest : public ::testing::TestWithParam<bool> {
protected:
QuicPacketCreatorTest()
diff --git a/net/quic/quic_protocol.cc b/net/quic/quic_protocol.cc
index f010253..961374e 100644
--- a/net/quic/quic_protocol.cc
+++ b/net/quic/quic_protocol.cc
@@ -212,7 +212,6 @@ ostream& operator<<(ostream& os, const QuicPacketHeader& header) {
return os;
}
-// TODO(ianswett): Initializing largest_observed to 0 should not be necessary.
ReceivedPacketInfo::ReceivedPacketInfo()
: largest_observed(0),
delta_time_largest_observed(QuicTime::Delta::Infinite()),
diff --git a/net/quic/quic_sent_packet_manager.cc b/net/quic/quic_sent_packet_manager.cc
index 9ecb5a7..523e745 100644
--- a/net/quic/quic_sent_packet_manager.cc
+++ b/net/quic/quic_sent_packet_manager.cc
@@ -69,23 +69,18 @@ void QuicSentPacketManager::OnSerializedPacket(
unacked_packets_[serialized_packet.sequence_number] =
TransmissionInfo(serialized_packet.retransmittable_frames,
serialized_packet.sequence_number_length);
- nack_map_[serialized_packet.sequence_number] = 0;
}
void QuicSentPacketManager::OnRetransmittedPacket(
QuicPacketSequenceNumber old_sequence_number,
QuicPacketSequenceNumber new_sequence_number) {
DCHECK(ContainsKey(unacked_packets_, old_sequence_number));
- DCHECK(ContainsKey(nack_map_, old_sequence_number));
DCHECK(ContainsKey(pending_retransmissions_, old_sequence_number));
DCHECK(unacked_packets_.empty() ||
unacked_packets_.rbegin()->first < new_sequence_number);
pending_retransmissions_.erase(old_sequence_number);
- nack_map_.erase(old_sequence_number);
- nack_map_[new_sequence_number] = 0;
-
RetransmittableFrames* frames =
unacked_packets_[old_sequence_number].retransmittable_frames;
DCHECK(frames);
@@ -146,34 +141,19 @@ void QuicSentPacketManager::HandleAckForSentPackets(
break;
}
- if (!IsAwaitingPacket(received_info, sequence_number)) {
- // Packet was acked, so remove it from our unacked packet list.
- DVLOG(1) << ENDPOINT <<"Got an ack for packet " << sequence_number;
- // If data is associated with the most recent transmission of this
- // packet, then inform the caller.
- it = MarkPacketReceivedByPeer(sequence_number);
-
- // The AckNotifierManager is informed of every ACKed sequence number.
- ack_notifier_manager_.OnPacketAcked(sequence_number);
-
+ if (IsAwaitingPacket(received_info, sequence_number)) {
+ ++it;
continue;
}
- // The peer got packets after this sequence number. This is an explicit
- // nack.
-
- // TODO(rch): move this to the congestion manager, and fix the logic.
- // This is a packet which we planned on retransmitting and has not been
- // seen at the time of this ack being sent out. See if it's our new
- // lowest unacked packet.
- DVLOG(1) << ENDPOINT << "still missing packet " << sequence_number;
- ++it;
- NackMap::iterator nack_it = nack_map_.find(sequence_number);
- if (nack_it == nack_map_.end()) {
- continue;
- }
- ++nack_it->second;
- helper_->OnPacketNacked(sequence_number, nack_it->second);
+ // Packet was acked, so remove it from our unacked packet list.
+ DVLOG(1) << ENDPOINT <<"Got an ack for packet " << sequence_number;
+ // If data is associated with the most recent transmission of this
+ // packet, then inform the caller.
+ it = MarkPacketReceivedByPeer(sequence_number);
+
+ // The AckNotifierManager is informed of every ACKed sequence number.
+ ack_notifier_manager_.OnPacketAcked(sequence_number);
}
// If we have received a trunacted ack, then we need to
@@ -193,7 +173,6 @@ void QuicSentPacketManager::HandleAckForSentPackets(
}
DCHECK(ContainsKey(previous_transmissions_map_, sequence_number));
- DCHECK(!ContainsKey(nack_map_, sequence_number));
DCHECK(!HasRetransmittableFrames(sequence_number));
unacked_packets_.erase(sequence_number);
SequenceNumberSet* previous_transmissions =
@@ -352,14 +331,12 @@ void QuicSentPacketManager::DiscardPacket(
unacked_packets_.find(sequence_number);
// Packet was not meant to be retransmitted.
if (unacked_it == unacked_packets_.end()) {
- DCHECK(!ContainsKey(nack_map_, sequence_number));
return;
}
// Delete the retransmittable frames.
delete unacked_it->second.retransmittable_frames;
unacked_packets_.erase(unacked_it);
- nack_map_.erase(sequence_number);
pending_retransmissions_.erase(sequence_number);
return;
}
@@ -413,7 +390,6 @@ bool QuicSentPacketManager::IsFecUnacked(
const RetransmittableFrames& QuicSentPacketManager::GetRetransmittableFrames(
QuicPacketSequenceNumber sequence_number) const {
DCHECK(ContainsKey(unacked_packets_, sequence_number));
- DCHECK(ContainsKey(nack_map_, sequence_number));
return *unacked_packets_.find(sequence_number)->second.retransmittable_frames;
}
diff --git a/net/quic/quic_sent_packet_manager.h b/net/quic/quic_sent_packet_manager.h
index e6878dd..d125193 100644
--- a/net/quic/quic_sent_packet_manager.h
+++ b/net/quic/quic_sent_packet_manager.h
@@ -23,7 +23,7 @@ NET_EXPORT_PRIVATE extern bool FLAGS_track_retransmission_history;
namespace net {
// Class which tracks the set of packets sent on a QUIC connection.
-// It keeps track of the retransmittable data ssociated with each
+// It keeps track of the retransmittable data associated with each
// packets. If a packet is retransmitted, it will keep track of each
// version of a packet so that if a previous transmission is acked,
// the data will not be retransmitted.
@@ -54,13 +54,6 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager {
// Called to return the sequence number of the next packet to be sent.
virtual QuicPacketSequenceNumber GetNextPacketSequenceNumber() = 0;
-
- // Called when a packet has been explicitly NACK'd. If a packet
- // has been retransmitted with mutliple sequence numbers, this will
- // only be called for the sequence number (if any) associated with
- // retransmittable frames.
- virtual void OnPacketNacked(QuicPacketSequenceNumber sequence_number,
- size_t nack_count) = 0;
};
QuicSentPacketManager(bool is_server, HelperInterface* helper);
@@ -168,7 +161,6 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager {
QuicTime> UnackedFecPacketMap;
typedef linked_hash_map<QuicPacketSequenceNumber,
TransmissionType> PendingRetransmissionMap;
- typedef base::hash_map<QuicPacketSequenceNumber, size_t> NackMap;
typedef base::hash_map<QuicPacketSequenceNumber, SequenceNumberSet*>
PreviousTransmissionMap;
@@ -216,10 +208,6 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager {
// Pending retransmissions which have not been packetized and sent yet.
PendingRetransmissionMap pending_retransmissions_;
- // Map from sequence number to the number of nacks for the packet.
- // Only the most recent transmission of packets are present in this map.
- NackMap nack_map_;
-
// Map from sequence number to set of all sequence number that this packet has
// been transmitted as. If a packet has not been retransmitted, it will not
// have an entry in this map. If any transmission of a packet has been acked
diff --git a/net/quic/quic_sent_packet_manager_test.cc b/net/quic/quic_sent_packet_manager_test.cc
index 9dd5850..5e81cc6 100644
--- a/net/quic/quic_sent_packet_manager_test.cc
+++ b/net/quic/quic_sent_packet_manager_test.cc
@@ -21,8 +21,6 @@ namespace {
class MockHelper : public QuicSentPacketManager::HelperInterface {
public:
MOCK_METHOD0(GetNextPacketSequenceNumber, QuicPacketSequenceNumber());
- MOCK_METHOD2(OnPacketNacked, void(QuicPacketSequenceNumber sequence_number,
- size_t nack_count));
};
class QuicSentPacketManagerTest : public ::testing::TestWithParam<bool> {
@@ -189,7 +187,6 @@ TEST_F(QuicSentPacketManagerTest, RetransmitThenAckPrevious) {
ReceivedPacketInfo received_info;
received_info.largest_observed = 2;
received_info.missing_packets.insert(2);
- EXPECT_CALL(helper_, OnPacketNacked(2, 1)).Times(1);
manager_.OnIncomingAck(received_info, false);
// 2 remains unacked, but no packets have retransmittable data.
@@ -230,7 +227,6 @@ TEST_F(QuicSentPacketManagerTest, SendDropAckRetransmitManyPackets) {
ReceivedPacketInfo received_info;
received_info.largest_observed = 3;
received_info.missing_packets.insert(2);
- EXPECT_CALL(helper_, OnPacketNacked(2, 1)).Times(1);
manager_.OnIncomingAck(received_info, false);
QuicPacketSequenceNumber unacked[] = { 2 };
@@ -248,8 +244,6 @@ TEST_F(QuicSentPacketManagerTest, SendDropAckRetransmitManyPackets) {
received_info.largest_observed = 5;
received_info.missing_packets.insert(2);
received_info.missing_packets.insert(4);
- EXPECT_CALL(helper_, OnPacketNacked(2, 2)).Times(1);
- EXPECT_CALL(helper_, OnPacketNacked(4, 1)).Times(1);
manager_.OnIncomingAck(received_info, false);
QuicPacketSequenceNumber unacked[] = { 2, 4 };
@@ -268,9 +262,6 @@ TEST_F(QuicSentPacketManagerTest, SendDropAckRetransmitManyPackets) {
received_info.missing_packets.insert(2);
received_info.missing_packets.insert(4);
received_info.missing_packets.insert(6);
- EXPECT_CALL(helper_, OnPacketNacked(2, 3)).Times(1);
- EXPECT_CALL(helper_, OnPacketNacked(4, 2)).Times(1);
- EXPECT_CALL(helper_, OnPacketNacked(6, 1)).Times(1);
manager_.OnIncomingAck(received_info, false);
QuicPacketSequenceNumber unacked[] = { 2, 4, 6 };
@@ -292,10 +283,6 @@ TEST_F(QuicSentPacketManagerTest, SendDropAckRetransmitManyPackets) {
received_info.missing_packets.insert(6);
received_info.missing_packets.insert(8);
received_info.missing_packets.insert(9);
- EXPECT_CALL(helper_, OnPacketNacked(4, 3)).Times(1);
- EXPECT_CALL(helper_, OnPacketNacked(6, 2)).Times(1);
- EXPECT_CALL(helper_, OnPacketNacked(8, 1)).Times(1);
- EXPECT_CALL(helper_, OnPacketNacked(9, 1)).Times(1);
manager_.OnIncomingAck(received_info, false);
QuicPacketSequenceNumber unacked[] = { 2, 4, 6, 8, 9 };
@@ -320,11 +307,6 @@ TEST_F(QuicSentPacketManagerTest, SendDropAckRetransmitManyPackets) {
received_info.missing_packets.insert(9);
received_info.missing_packets.insert(11);
received_info.missing_packets.insert(12);
- EXPECT_CALL(helper_, OnPacketNacked(6, 3)).Times(1);
- EXPECT_CALL(helper_, OnPacketNacked(8, 2)).Times(1);
- EXPECT_CALL(helper_, OnPacketNacked(9, 2)).Times(1);
- EXPECT_CALL(helper_, OnPacketNacked(11, 1)).Times(1);
- EXPECT_CALL(helper_, OnPacketNacked(12, 1)).Times(1);
manager_.OnIncomingAck(received_info, false);
QuicPacketSequenceNumber unacked[] = { 2, 4, 6, 8, 9, 11, 12 };
@@ -348,10 +330,6 @@ TEST_F(QuicSentPacketManagerTest, SendDropAckRetransmitManyPackets) {
received_info.missing_packets.insert(9);
received_info.missing_packets.insert(11);
received_info.missing_packets.insert(12);
- EXPECT_CALL(helper_, OnPacketNacked(8, 3)).Times(1);
- EXPECT_CALL(helper_, OnPacketNacked(9, 3)).Times(1);
- EXPECT_CALL(helper_, OnPacketNacked(11, 2)).Times(1);
- EXPECT_CALL(helper_, OnPacketNacked(12, 2)).Times(1);
manager_.OnIncomingAck(received_info, true);
// Truncated ack raises the high water mark by clearing out 2, 4, and 6.
diff --git a/net/quic/quic_session.h b/net/quic/quic_session.h
index 35521db..1d1cc7d 100644
--- a/net/quic/quic_session.h
+++ b/net/quic/quic_session.h
@@ -147,6 +147,12 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
void MarkWriteBlocked(QuicStreamId id, QuicPriority priority);
+ // Returns the number of streams with more data the connection can't
+ // write yet.
+ size_t NumWriteBlockedStreams() const {
+ return write_blocked_streams_.NumBlockedStreams();
+ }
+
// Marks that |stream_id| is blocked waiting to decompress the
// headers identified by |decompression_id|.
void MarkDecompressionBlocked(QuicHeaderId decompression_id,
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index 87aed16..e4578d3 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -259,8 +259,6 @@ QuicStreamFactory::QuicStreamFactory(
config_.set_idle_connection_state_lifetime(
QuicTime::Delta::FromSeconds(30),
QuicTime::Delta::FromSeconds(30));
- config_.set_server_max_packet_size(kDefaultMaxPacketSize,
- kDefaultMaxPacketSize);
cannoncial_suffixes_.push_back(string(".c.youtube.com"));
cannoncial_suffixes_.push_back(string(".googlevideo.com"));
}
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h
index d111fa0..20205e9 100644
--- a/net/quic/test_tools/quic_test_utils.h
+++ b/net/quic/test_tools/quic_test_utils.h
@@ -55,6 +55,25 @@ size_t GetMinStreamFrameSize(QuicVersion version);
// Returns QuicConfig set to default values.
QuicConfig DefaultQuicConfig();
+template<typename SaveType>
+class ValueRestore {
+ public:
+ ValueRestore(SaveType* name, SaveType value)
+ : name_(name),
+ value_(*name) {
+ *name_ = value;
+ }
+ ~ValueRestore() {
+ *name_ = value_;
+ }
+
+ private:
+ SaveType* name_;
+ SaveType value_;
+
+ DISALLOW_COPY_AND_ASSIGN(ValueRestore);
+};
+
class MockFramerVisitor : public QuicFramerVisitorInterface {
public:
MockFramerVisitor();
@@ -352,6 +371,7 @@ class MockSendAlgorithm : public SendAlgorithmInterface {
virtual ~MockSendAlgorithm();
MOCK_METHOD2(SetFromConfig, void(const QuicConfig& config, bool is_server));
+ MOCK_METHOD1(SetMaxPacketSize, void(QuicByteCount max_packet_size));
MOCK_METHOD3(OnIncomingQuicCongestionFeedbackFrame,
void(const QuicCongestionFeedbackFrame&,
QuicTime feedback_receive_time,
@@ -362,6 +382,7 @@ class MockSendAlgorithm : public SendAlgorithmInterface {
MOCK_METHOD5(OnPacketSent,
bool(QuicTime sent_time, QuicPacketSequenceNumber, QuicByteCount,
TransmissionType, HasRetransmittableData));
+ MOCK_METHOD0(OnRetransmissionTimeout, void());
MOCK_METHOD2(OnPacketAbandoned, void(QuicPacketSequenceNumber sequence_number,
QuicByteCount abandoned_bytes));
MOCK_METHOD4(TimeUntilSend, QuicTime::Delta(QuicTime now, TransmissionType,
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index 04dc745..c488902 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -11,6 +11,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "net/base/ip_endpoint.h"
+#include "net/quic/congestion_control/quic_congestion_manager.h"
#include "net/quic/congestion_control/tcp_cubic_sender.h"
#include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
#include "net/quic/crypto/null_encrypter.h"
@@ -70,11 +71,13 @@ struct TestParams {
TestParams(const QuicVersionVector& client_supported_versions,
const QuicVersionVector& server_supported_versions,
QuicVersion negotiated_version,
- bool use_padding)
+ bool use_padding,
+ bool use_pacing)
: client_supported_versions(client_supported_versions),
server_supported_versions(server_supported_versions),
negotiated_version(negotiated_version),
- use_padding(use_padding) {
+ use_padding(use_padding),
+ use_pacing(use_pacing) {
}
friend ostream& operator<<(ostream& os, const TestParams& p) {
@@ -83,7 +86,8 @@ struct TestParams {
os << " client_supported_versions: "
<< QuicVersionVectorToString(p.client_supported_versions);
os << " negotiated_version: " << QuicVersionToString(p.negotiated_version);
- os << " use_padding: " << p.use_padding << " }";
+ os << " use_padding: " << p.use_padding;
+ os << " use_pacing: " << p.use_pacing << " }";
return os;
}
@@ -91,6 +95,7 @@ struct TestParams {
QuicVersionVector server_supported_versions;
QuicVersion negotiated_version;
bool use_padding;
+ bool use_pacing;
};
// Constructs various test permutations.
@@ -98,44 +103,40 @@ vector<TestParams> GetTestParams() {
vector<TestParams> params;
QuicVersionVector all_supported_versions = QuicSupportedVersions();
- // Add an entry for server and client supporting all versions.
- params.push_back(TestParams(all_supported_versions, all_supported_versions,
- all_supported_versions[0], true));
- params.push_back(TestParams(all_supported_versions, all_supported_versions,
- all_supported_versions[0], false));
-
- // Test client supporting 1 version and server supporting all versions.
- // Simulate an old client and exercise version downgrade in the server.
- // No protocol negotiation should occur. Skip the i = 0 case because it
- // is essentially the same as the default case.
- for (size_t i = 1; i < all_supported_versions.size(); ++i) {
- QuicVersionVector client_supported_versions;
- client_supported_versions.push_back(all_supported_versions[i]);
- params.push_back(TestParams(client_supported_versions,
- all_supported_versions,
- client_supported_versions[0],
- true));
- params.push_back(TestParams(client_supported_versions,
- all_supported_versions,
- client_supported_versions[0],
- false));
- }
-
- // Test client supporting all versions and server supporting 1 version.
- // Simulate an old server and exercise version downgrade in the client.
- // Protocol negotiation should occur. Skip the i = 0 case because it is
- // essentially the same as the default case.
- for (size_t i = 1; i < all_supported_versions.size(); ++i) {
- QuicVersionVector server_supported_versions;
- server_supported_versions.push_back(all_supported_versions[i]);
- params.push_back(TestParams(all_supported_versions,
- server_supported_versions,
- server_supported_versions[0],
- true));
- params.push_back(TestParams(all_supported_versions,
- server_supported_versions,
- server_supported_versions[0],
- false));
+ for (int use_pacing = 0; use_pacing < 2; ++use_pacing) {
+ for (int use_padding = 0; use_padding < 2; ++use_padding) {
+ // Add an entry for server and client supporting all versions.
+ params.push_back(TestParams(all_supported_versions,
+ all_supported_versions,
+ all_supported_versions[0],
+ use_padding != 0, use_pacing != 0));
+
+ // Test client supporting 1 version and server supporting all versions.
+ // Simulate an old client and exercise version downgrade in the server.
+ // No protocol negotiation should occur. Skip the i = 0 case because it
+ // is essentially the same as the default case.
+ for (size_t i = 1; i < all_supported_versions.size(); ++i) {
+ QuicVersionVector client_supported_versions;
+ client_supported_versions.push_back(all_supported_versions[i]);
+ params.push_back(TestParams(client_supported_versions,
+ all_supported_versions,
+ client_supported_versions[0],
+ use_pacing != 0, use_padding != 0));
+ }
+
+ // Test client supporting all versions and server supporting 1 version.
+ // Simulate an old server and exercise version downgrade in the client.
+ // Protocol negotiation should occur. Skip the i = 0 case because it is
+ // essentially the same as the default case.
+ for (size_t i = 1; i < all_supported_versions.size(); ++i) {
+ QuicVersionVector server_supported_versions;
+ server_supported_versions.push_back(all_supported_versions[i]);
+ params.push_back(TestParams(all_supported_versions,
+ server_supported_versions,
+ server_supported_versions[0],
+ use_pacing != 0, use_padding != 0));
+ }
+ }
}
return params;
}
@@ -149,6 +150,15 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
net::IPAddressNumber ip;
CHECK(net::ParseIPLiteralToNumber("127.0.0.1", &ip));
server_address_ = IPEndPoint(ip, 0);
+
+ client_supported_versions_ = GetParam().client_supported_versions;
+ server_supported_versions_ = GetParam().server_supported_versions;
+ negotiated_version_ = GetParam().negotiated_version;
+ FLAGS_limit_rto_increase_for_tests = true;
+ FLAGS_pad_quic_handshake_packets = GetParam().use_padding;
+ FLAGS_enable_quic_pacing = GetParam().use_pacing;
+ LOG(INFO) << "Using Configuration: " << GetParam();
+
client_config_.SetDefaults();
server_config_.SetDefaults();
server_config_.set_initial_round_trip_time_us(kMaxInitialRoundTripTimeUs,
@@ -159,18 +169,6 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
"HTTP/1.1", "200", "OK", kFooResponseBody);
AddToCache("GET", "https://www.google.com/bar",
"HTTP/1.1", "200", "OK", kBarResponseBody);
-
- client_supported_versions_ = GetParam().client_supported_versions;
- server_supported_versions_ = GetParam().server_supported_versions;
- negotiated_version_ = GetParam().negotiated_version;
- FLAGS_pad_quic_handshake_packets = GetParam().use_padding;
- LOG(INFO) << "server running " << QuicVersionVectorToString(
- server_supported_versions_);
- LOG(INFO) << "client running " << QuicVersionVectorToString(
- client_supported_versions_);
- LOG(INFO) << "negotiated_version_ " << QuicVersionToString(
- negotiated_version_);
- LOG(INFO) << "use_padding " << GetParam().use_padding;
}
virtual ~EndToEndTest() {
@@ -595,6 +593,7 @@ TEST_P(EndToEndTest, DISABLED_PacketTooLarge) {
TEST_P(EndToEndTest, InvalidStream) {
ASSERT_TRUE(Initialize());
+ client_->client()->WaitForCryptoHandshakeConfirmed();
string body;
GenerateBody(&body, kMaxPacketSize);
@@ -628,6 +627,7 @@ TEST_P(EndToEndTest, DISABLED_MultipleTermination) {
ReliableQuicStreamPeer::SetStreamBytesWritten(3, stream);
client_->SendData("bar", true);
+ client_->WaitForWriteToFlush();
// By default the stream protects itself from writes after terminte is set.
// Override this to test the server handling buggy clients.
@@ -677,11 +677,9 @@ TEST_P(EndToEndTest, LimitMaxOpenStreams) {
EXPECT_EQ(2u, client_negotiated_config->max_streams_per_connection());
}
-TEST_P(EndToEndTest, LimitMaxPacketSizeAndCongestionWindowAndRTT) {
+TEST_P(EndToEndTest, LimitCongestionWindowAndRTT) {
// Client tries to negotiate twice the server's max and negotiation settles
// on the max.
- client_config_.set_server_max_packet_size(2 * kMaxPacketSize,
- kDefaultMaxPacketSize);
client_config_.set_server_initial_congestion_window(2 * kMaxInitialWindow,
kDefaultInitialWindow);
client_config_.set_initial_round_trip_time_us(1, 1);
@@ -703,16 +701,6 @@ TEST_P(EndToEndTest, LimitMaxPacketSizeAndCongestionWindowAndRTT) {
const QuicCongestionManager& server_congestion_manager =
session->connection()->congestion_manager();
- EXPECT_EQ(kMaxPacketSize, client_negotiated_config->server_max_packet_size());
- EXPECT_EQ(kDefaultMaxPacketSize,
- client_->client()->options()->max_packet_length);
- if (negotiated_version_ > QUIC_VERSION_11) {
- EXPECT_EQ(kMaxPacketSize, session->options()->max_packet_length);
- } else {
- EXPECT_EQ(kDefaultMaxPacketSize,
- session->options()->max_packet_length);
- }
-
EXPECT_EQ(kMaxInitialWindow,
client_negotiated_config->server_initial_congestion_window());
EXPECT_EQ(kMaxInitialWindow,
@@ -723,6 +711,9 @@ TEST_P(EndToEndTest, LimitMaxPacketSizeAndCongestionWindowAndRTT) {
EXPECT_EQ(kMaxInitialWindow * kDefaultTCPMSS,
server_congestion_manager.GetCongestionWindow());
+ EXPECT_EQ(FLAGS_enable_quic_pacing, server_congestion_manager.using_pacing());
+ EXPECT_EQ(FLAGS_enable_quic_pacing, client_congestion_manager.using_pacing());
+
EXPECT_EQ(1u, client_negotiated_config->initial_round_trip_time_us());
EXPECT_EQ(1u, server_negotiated_config->initial_round_trip_time_us());
@@ -778,6 +769,7 @@ TEST_P(EndToEndTest, InitialRTT) {
TEST_P(EndToEndTest, ResetConnection) {
ASSERT_TRUE(Initialize());
+ client_->client()->WaitForCryptoHandshakeConfirmed();
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
diff --git a/net/tools/quic/quic_client.cc b/net/tools/quic/quic_client.cc
index 50e2a7c..299932df 100644
--- a/net/tools/quic/quic_client.cc
+++ b/net/tools/quic/quic_client.cc
@@ -47,8 +47,6 @@ QuicClient::QuicClient(IPEndPoint server_address,
config_.SetDefaults();
// TODO(ianswett): Allow the client to change the server's max packet size and
// initial congestion window.
- config_.set_server_max_packet_size(kDefaultMaxPacketSize,
- kDefaultMaxPacketSize);
config_.set_server_initial_congestion_window(kDefaultInitialWindow,
kDefaultInitialWindow);
}
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc
index 577d12f..27b0f5c 100644
--- a/net/tools/quic/test_tools/quic_test_client.cc
+++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -220,10 +220,12 @@ ssize_t QuicTestClient::SendMessage(const HTTPMessage& message) {
scoped_ptr<BalsaHeaders> munged_headers(MungeHeaders(message.headers(),
secure_));
- return GetOrCreateStream()->SendRequest(
+ ssize_t ret = GetOrCreateStream()->SendRequest(
munged_headers.get() ? *munged_headers.get() : *message.headers(),
message.body(),
message.has_complete_message());
+ WaitForWriteToFlush();
+ return ret;
}
ssize_t QuicTestClient::SendData(string data, bool last_data) {
@@ -428,6 +430,13 @@ void QuicTestClient::UseGuid(QuicGuid guid) {
reinterpret_cast<QuicEpollClient*>(client_.get())->UseGuid(guid);
}
+void QuicTestClient::WaitForWriteToFlush() {
+ while (connected() &&
+ client()->session()->NumWriteBlockedStreams() != 0) {
+ client_->WaitForEvents();
+ }
+}
+
} // namespace test
} // namespace tools
} // namespace net
diff --git a/net/tools/quic/test_tools/quic_test_client.h b/net/tools/quic/test_tools/quic_test_client.h
index 1fa18c9..6abdac1 100644
--- a/net/tools/quic/test_tools/quic_test_client.h
+++ b/net/tools/quic/test_tools/quic_test_client.h
@@ -110,6 +110,8 @@ class QuicTestClient : public ReliableQuicStream::Visitor {
void set_priority(QuicPriority priority) { priority_ = priority; }
+ void WaitForWriteToFlush();
+
private:
void Initialize(IPEndPoint address, const string& hostname, bool secure);