Skip to content

Commit

Permalink
Land Recent QUIC Changes until 03/15/2015.
Browse files Browse the repository at this point in the history
Do not retransmit QUIC data for streams that have been reset. Protected
by FLAGS_quic_do_not_retransmit_for_reset_streams.

This is an attempt to reland cr/88179867 now that the underlying bug has
been fixed. Includes tests which crashed on the old CL and pass now.

Merge internal change: 88695223
https://codereview.chromium.org/1009243002/

Move QUIC reads to a more optimized reader.
Guarded by FLAGS_quic_use_optimized_packet_reader. This is not enabled
for the chromium's QUIC server yet.

The new QuicPacketReader is optimized to spend less time in memset and
uses a 16 packet receive buffer.  Saves 1.09 % of CPU in memset alone
according to profiling EndToEndTest.

Merge internal change: 88573234
https://codereview.chromium.org/1008313002/

Rollback of merge internal change: 87346681.

Chromium CL reviewed:
  https://codereview.chromium.org/968923005/

Chomium committed CL: "Land Recent QUIC Changes until 03/02/2015".
  https://codereview.chromium.org/968233004/

This CL was in M43 bit not in M42. It impacted last week's Dev release
and all Canary released after 03/03/2015.

*** Original change description ***

Remove TCP and BBR's max congestion window.  No practical change,
because Chrome's receive window is the limiting factor.

Adds kMaxReportedCwnd and kMaxReorderingForRtt as constants to replace
the max CWND in classes that used to rely on max CWND.

***

Merge internal change: 88545044
https://codereview.chromium.org/1003863006/

Make the SentPacketManager remove pending retransmissions for reset
streams. No behavior change yet. That will be in a flag protected followup.

Minor change to linked_hash_map's erase method to return an iterator
pointing to the new location of the element that followed the last
element erased by the function call (ala internal source code and
std:: c++).

Merge internal change: 88507368
https://codereview.chromium.org/1013583002/

Only changes comments. Replace "CID" with "connection id" in various
comments in quic_connection_test.cc

Merge internal change: 88463135
https://codereview.chromium.org/1013573002/

Provide a MockConnection constructor that takes connection_id,
perspective, and is_secure as arguments.  Used by the internal server
testing code. Clarify debugging log message in quic_dispatcher.cc.

Clarify debugging log message in quic_dispatcher.cc. Improve testing
infrastructure.

Merge internal change: 88461470
https://codereview.chromium.org/1008293002/

Add a kBYTE congestion option to QUIC to negotiate the TcpCubicBytesSender.

Merge internal change: 88328620
https://codereview.chromium.org/1009203003/

Add support for the MIN1 connection option to TcpCubicBytesSender.
This sender is currently unused.

Allows TcpCubicBytesSender to have a min cwnd of 1 packet in bytes.

Merge internal change: 88167032
https://codereview.chromium.org/1008283002/

R=rch@chromium.org

Review URL: https://codereview.chromium.org/1008323002

Cr-Commit-Position: refs/heads/master@{#320819}
  • Loading branch information
rtenneti authored and Commit bot committed Mar 16, 2015
1 parent 1c376a8 commit fb3fa6c
Show file tree
Hide file tree
Showing 30 changed files with 676 additions and 78 deletions.
2 changes: 2 additions & 0 deletions net/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -1155,6 +1155,8 @@ if (is_linux) {
"tools/quic/quic_epoll_connection_helper.h",
"tools/quic/quic_in_memory_cache.cc",
"tools/quic/quic_in_memory_cache.h",
"tools/quic/quic_packet_reader.cc",
"tools/quic/quic_packet_reader.h",
"tools/quic/quic_packet_writer_wrapper.cc",
"tools/quic/quic_packet_writer_wrapper.h",
"tools/quic/quic_per_connection_packet_writer.cc",
Expand Down
21 changes: 13 additions & 8 deletions net/base/linked_hash_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,23 +124,28 @@ class linked_hash_map {
return 1;
}

// Erases values with the provided iterator. If the provided iterator is
// invalid or there is inconsistency between the map and list, a CHECK() error
// will occur.
void erase(iterator position) {
// Erases the item that 'position' points to. Returns an iterator that points
// to the item that comes immediately after the deleted item in the list, or
// end().
// If the provided iterator is invalid or there is inconsistency between the
// map and list, a CHECK() error will occur.
iterator erase(iterator position) {
typename MapType::iterator found = map_.find(position->first);
CHECK(found->second == position)
<< "Inconsisent iterator for map and list, or the iterator is invalid.";

list_.erase(position);
map_.erase(found);
return list_.erase(position);
}

// Erases values between first and last, not including last.
void erase(iterator first, iterator last) {
// Erases all the items in the range [first, last). Returns an iterator that
// points to the item that comes immediately after the last deleted item in
// the list, or end().
iterator erase(iterator first, iterator last) {
while (first != last && first != end()) {
erase(first++);
first = erase(first);
}
return first;
}

// Finds the element with the given key. Returns an iterator to the
Expand Down
2 changes: 2 additions & 0 deletions net/net.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -1215,6 +1215,8 @@
'tools/quic/quic_epoll_connection_helper.h',
'tools/quic/quic_in_memory_cache.cc',
'tools/quic/quic_in_memory_cache.h',
'tools/quic/quic_packet_reader.cc',
'tools/quic/quic_packet_reader.h',
'tools/quic/quic_packet_writer_wrapper.cc',
'tools/quic/quic_packet_writer_wrapper.h',
'tools/quic/quic_per_connection_packet_writer.cc',
Expand Down
17 changes: 14 additions & 3 deletions net/quic/congestion_control/send_algorithm_interface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "net/quic/congestion_control/send_algorithm_interface.h"

#include "net/quic/congestion_control/tcp_cubic_bytes_sender.h"
#include "net/quic/congestion_control/tcp_cubic_sender.h"
#include "net/quic/quic_protocol.h"

Expand All @@ -21,15 +22,25 @@ SendAlgorithmInterface* SendAlgorithmInterface::Create(
switch (congestion_control_type) {
case kCubic:
return new TcpCubicSender(clock, rtt_stats, false /* don't use Reno */,
initial_congestion_window, stats);
initial_congestion_window,
kMaxTcpCongestionWindow, stats);
case kCubicBytes:
return new TcpCubicBytesSender(
clock, rtt_stats, false /* don't use Reno */,
initial_congestion_window, kMaxTcpCongestionWindow, stats);
case kReno:
return new TcpCubicSender(clock, rtt_stats, true /* use Reno */,
initial_congestion_window, stats);
initial_congestion_window,
kMaxTcpCongestionWindow, stats);
case kRenoBytes:
return new TcpCubicBytesSender(clock, rtt_stats, true /* use Reno */,
initial_congestion_window,
kMaxTcpCongestionWindow, stats);
case kBBR:
// TODO(rtenneti): Enable BbrTcpSender.
#if 0
return new BbrTcpSender(clock, rtt_stats, initial_congestion_window,
stats);
kMaxTcpCongestionWindow, stats);
#endif
LOG(DFATAL) << "BbrTcpSender is not supported.";
return nullptr;
Expand Down
24 changes: 17 additions & 7 deletions net/quic/congestion_control/tcp_cubic_bytes_sender.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace {
// Constants based on TCP defaults.
// The minimum cwnd based on RFC 3782 (TCP NewReno) for cwnd reductions on a
// fast retransmission.
const QuicByteCount kMinimumCongestionWindow = 2 * kDefaultTCPMSS;
const QuicByteCount kDefaultMinimumCongestionWindow = 2 * kDefaultTCPMSS;
const QuicByteCount kMaxSegmentSize = kDefaultTCPMSS;
const int kMaxBurstLength = 3;
const float kRenoBeta = 0.7f; // Reno backoff factor.
Expand All @@ -31,6 +31,7 @@ TcpCubicBytesSender::TcpCubicBytesSender(
const RttStats* rtt_stats,
bool reno,
QuicPacketCount initial_tcp_congestion_window,
QuicPacketCount max_congestion_window,
QuicConnectionStats* stats)
: hybrid_slow_start_(clock),
cubic_(clock),
Expand All @@ -43,6 +44,8 @@ TcpCubicBytesSender::TcpCubicBytesSender(
largest_acked_sequence_number_(0),
largest_sent_at_last_cutback_(0),
congestion_window_(initial_tcp_congestion_window * kMaxSegmentSize),
min_congestion_window_(kDefaultMinimumCongestionWindow),
max_congestion_window_(max_congestion_window * kMaxSegmentSize),
slowstart_threshold_(std::numeric_limits<uint64>::max()),
last_cutback_exited_slowstart_(false),
clock_(clock) {
Expand All @@ -60,6 +63,11 @@ void TcpCubicBytesSender::SetFromConfig(const QuicConfig& config,
// Initial window experiment.
congestion_window_ = 10 * kMaxSegmentSize;
}
if (config.HasReceivedConnectionOptions() &&
ContainsQuicTag(config.ReceivedConnectionOptions(), kMIN1)) {
// Min CWND experiment.
min_congestion_window_ = kMaxSegmentSize;
}
if (using_pacing) {
// Disable the ack train mode in hystart when pacing is enabled, since it
// may be falsely triggered.
Expand All @@ -86,8 +94,7 @@ bool TcpCubicBytesSender::ResumeConnectionState(
// Make sure CWND is in appropriate range (in case of bad data).
QuicByteCount new_congestion_window = bandwidth.ToBytesPerPeriod(rtt_ms);
congestion_window_ =
max(min(new_congestion_window,
kMaxCongestionWindowForBandwidthResumption * kMaxSegmentSize),
max(min(new_congestion_window, kMaxTcpCongestionWindow * kMaxSegmentSize),
kMinCongestionWindowForBandwidthResumption * kMaxSegmentSize);

// TODO(rjshade): Set appropriate CWND when previous connection was in slow
Expand Down Expand Up @@ -173,8 +180,8 @@ void TcpCubicBytesSender::OnPacketLost(QuicPacketSequenceNumber sequence_number,
}
slowstart_threshold_ = congestion_window_;
// Enforce TCP's minimum congestion window of 2*MSS.
if (congestion_window_ < kMinimumCongestionWindow) {
congestion_window_ = kMinimumCongestionWindow;
if (congestion_window_ < min_congestion_window_) {
congestion_window_ = min_congestion_window_;
}
largest_sent_at_last_cutback_ = largest_sent_sequence_number_;
// Reset packet count from congestion avoidance mode. We start counting again
Expand Down Expand Up @@ -298,6 +305,9 @@ void TcpCubicBytesSender::MaybeIncreaseCwnd(
// window we have available.
return;
}
if (congestion_window_ >= max_congestion_window_) {
return;
}
if (InSlowStart()) {
// TCP slow start, exponential growth, increase by one for each ACK.
congestion_window_ += kMaxSegmentSize;
Expand Down Expand Up @@ -336,11 +346,11 @@ void TcpCubicBytesSender::OnRetransmissionTimeout(bool packets_retransmitted) {
cubic_.Reset();
hybrid_slow_start_.Restart();
slowstart_threshold_ = congestion_window_ / 2;
congestion_window_ = kMinimumCongestionWindow;
congestion_window_ = min_congestion_window_;
}

CongestionControlType TcpCubicBytesSender::GetCongestionControlType() const {
return reno_ ? kReno : kCubic;
return reno_ ? kRenoBytes : kCubicBytes;
}

} // namespace net
7 changes: 7 additions & 0 deletions net/quic/congestion_control/tcp_cubic_bytes_sender.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class NET_EXPORT_PRIVATE TcpCubicBytesSender : public SendAlgorithmInterface {
const RttStats* rtt_stats,
bool reno,
QuicPacketCount initial_tcp_congestion_window,
QuicPacketCount max_congestion_window,
QuicConnectionStats* stats);
~TcpCubicBytesSender() override;

Expand Down Expand Up @@ -112,6 +113,12 @@ class NET_EXPORT_PRIVATE TcpCubicBytesSender : public SendAlgorithmInterface {
// Congestion window in bytes.
QuicByteCount congestion_window_;

// Minimum congestion window in bytes.
QuicByteCount min_congestion_window_;

// Maximum congestion window in bytes.
QuicByteCount max_congestion_window_;

// Slow start congestion window in bytes, aka ssthresh.
QuicByteCount slowstart_threshold_;

Expand Down
5 changes: 3 additions & 2 deletions net/quic/congestion_control/tcp_cubic_bytes_sender_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class TcpCubicBytesSenderPeer : public TcpCubicBytesSender {
&rtt_stats_,
reno,
kInitialCongestionWindowPackets,
kMaxTcpCongestionWindow,
&stats_) {}

const HybridSlowStart& hybrid_slow_start() const {
Expand Down Expand Up @@ -625,9 +626,9 @@ TEST_F(TcpCubicBytesSenderTest, BandwidthResumption) {

// Resumed CWND is limited to be in a sensible range.
cached_network_params.set_bandwidth_estimate_bytes_per_second(
(kMaxCongestionWindowForBandwidthResumption + 1) * kDefaultTCPMSS);
(kMaxTcpCongestionWindow + 1) * kDefaultTCPMSS);
EXPECT_TRUE(sender_->ResumeConnectionState(cached_network_params));
EXPECT_EQ(kMaxCongestionWindowForBandwidthResumption * kDefaultTCPMSS,
EXPECT_EQ(kMaxTcpCongestionWindow * kDefaultTCPMSS,
sender_->GetCongestionWindow());

cached_network_params.set_bandwidth_estimate_bytes_per_second(
Expand Down
36 changes: 22 additions & 14 deletions net/quic/congestion_control/tcp_cubic_sender.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,23 @@ TcpCubicSender::TcpCubicSender(const QuicClock* clock,
const RttStats* rtt_stats,
bool reno,
QuicPacketCount initial_tcp_congestion_window,
QuicPacketCount max_tcp_congestion_window,
QuicConnectionStats* stats)
: hybrid_slow_start_(clock),
cubic_(clock),
rtt_stats_(rtt_stats),
stats_(stats),
reno_(reno),
num_connections_(kDefaultNumConnections),
num_acked_packets_(0),
congestion_window_count_(0),
largest_sent_sequence_number_(0),
largest_acked_sequence_number_(0),
largest_sent_at_last_cutback_(0),
congestion_window_(initial_tcp_congestion_window),
min_congestion_window_(kDefaultMinimumCongestionWindow),
slowstart_threshold_(std::numeric_limits<uint64>::max()),
slowstart_threshold_(max_tcp_congestion_window),
last_cutback_exited_slowstart_(false),
max_tcp_congestion_window_(max_tcp_congestion_window),
clock_(clock) {
}

Expand Down Expand Up @@ -93,9 +95,8 @@ bool TcpCubicSender::ResumeConnectionState(
// Make sure CWND is in appropriate range (in case of bad data).
QuicPacketCount new_congestion_window =
bandwidth.ToBytesPerPeriod(rtt_ms) / kMaxPacketSize;
congestion_window_ = max(
min(new_congestion_window, kMaxCongestionWindowForBandwidthResumption),
kMinCongestionWindowForBandwidthResumption);
congestion_window_ = max(min(new_congestion_window, kMaxTcpCongestionWindow),
kMinCongestionWindowForBandwidthResumption);

// TODO(rjshade): Set appropriate CWND when previous connection was in slow
// start at time of estimate.
Expand Down Expand Up @@ -186,7 +187,7 @@ void TcpCubicSender::OnPacketLost(QuicPacketSequenceNumber sequence_number,
largest_sent_at_last_cutback_ = largest_sent_sequence_number_;
// reset packet count from congestion avoidance mode. We start
// counting again when we're out of recovery.
num_acked_packets_ = 0;
congestion_window_count_ = 0;
DVLOG(1) << "Incoming loss; congestion window: " << congestion_window_
<< " slowstart threshold: " << slowstart_threshold_;
}
Expand Down Expand Up @@ -307,29 +308,36 @@ void TcpCubicSender::MaybeIncreaseCwnd(
return;
}
if (InSlowStart()) {
// TCP slow start, exponential growth, increase by one for each ACK.
++congestion_window_;
// congestion_window_cnt is the number of acks since last change of snd_cwnd
if (congestion_window_ < max_tcp_congestion_window_) {
// TCP slow start, exponential growth, increase by one for each ACK.
++congestion_window_;
}
DVLOG(1) << "Slow start; congestion window: " << congestion_window_
<< " slowstart threshold: " << slowstart_threshold_;
return;
}
if (congestion_window_ >= max_tcp_congestion_window_) {
return;
}
// Congestion avoidance
if (reno_) {
// Classic Reno congestion avoidance.
++num_acked_packets_;
++congestion_window_count_;
// Divide by num_connections to smoothly increase the CWND at a faster
// rate than conventional Reno.
if (num_acked_packets_ * num_connections_ >= congestion_window_) {
if (congestion_window_count_ * num_connections_ >= congestion_window_) {
++congestion_window_;
num_acked_packets_ = 0;
congestion_window_count_ = 0;
}

DVLOG(1) << "Reno; congestion window: " << congestion_window_
<< " slowstart threshold: " << slowstart_threshold_
<< " congestion window count: " << num_acked_packets_;
<< " congestion window count: " << congestion_window_count_;
} else {
congestion_window_ = cubic_.CongestionWindowAfterAck(congestion_window_,
rtt_stats_->min_rtt());
congestion_window_ = min(max_tcp_congestion_window_,
cubic_.CongestionWindowAfterAck(
congestion_window_, rtt_stats_->min_rtt()));
DVLOG(1) << "Cubic; congestion window: " << congestion_window_
<< " slowstart threshold: " << slowstart_threshold_;
}
Expand Down
7 changes: 6 additions & 1 deletion net/quic/congestion_control/tcp_cubic_sender.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ class TcpCubicSenderPeer;

class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface {
public:
// Reno option and max_tcp_congestion_window are provided for testing.
TcpCubicSender(const QuicClock* clock,
const RttStats* rtt_stats,
bool reno,
QuicPacketCount initial_tcp_congestion_window,
QuicPacketCount max_tcp_congestion_window,
QuicConnectionStats* stats);
~TcpCubicSender() override;

Expand Down Expand Up @@ -99,7 +101,7 @@ class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface {
uint32 num_connections_;

// ACK counter for the Reno implementation.
uint64 num_acked_packets_;
uint64 congestion_window_count_;

// Track the largest packet that has been sent.
QuicPacketSequenceNumber largest_sent_sequence_number_;
Expand All @@ -123,6 +125,9 @@ class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface {
// Used for stats collection of slowstart_packets_lost
bool last_cutback_exited_slowstart_;

// Maximum number of outstanding packets for tcp.
QuicPacketCount max_tcp_congestion_window_;

const QuicClock* clock_;

DISALLOW_COPY_AND_ASSIGN(TcpCubicSender);
Expand Down
Loading

0 comments on commit fb3fa6c

Please sign in to comment.