summaryrefslogtreecommitdiffstats
path: root/net/quic/congestion_control
diff options
context:
space:
mode:
authorrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-30 04:03:04 +0000
committerrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-30 04:03:04 +0000
commitc5e1aca90ddc180362e0663648c482b874436adf (patch)
tree5f2a71349aaebe5fae92f5651ae8f5bf7a0db366 /net/quic/congestion_control
parentf13d7a712f2455a7e9699c12d7ac4d4c604c819f (diff)
downloadchromium_src-c5e1aca90ddc180362e0663648c482b874436adf.zip
chromium_src-c5e1aca90ddc180362e0663648c482b874436adf.tar.gz
chromium_src-c5e1aca90ddc180362e0663648c482b874436adf.tar.bz2
Land Recent QUIC Changes.
Cleanup: remove BlockedWriterInterface from QuicPacketWriter. No behavior changes. Merge internal change: 60499316 https://codereview.chromium.org/135363006/ Properly trigger OnCanWrite processing from PacketDroppingTestWriter. Re-enable the LargePostWithPacketLossAndBlockedSocket test. Testing only. Dialing back the loss from 30% to 10% seems to have stabilized the test. Merge internal change: 60479729 https://codereview.chromium.org/131503016/ Use LOG_IF instead of LOG_IF_FIRST_N in a few places, as per avd's suggestion. Merge internal change: 60382807 https://codereview.chromium.org/149163004/ Change the default RTT from 60ms to 100ms, which is more typical of internal server's. Merge internal change: 60366147 https://codereview.chromium.org/146583006/ Remove an impossible check in QuicConnection for when a packet is retransmitted before it is sent. Updating the tests also found and fixed an edge case where a truncated ack could cause the SentPacketManager to raise the high water mark above a pending packet. Merge internal change: 60169343 https://codereview.chromium.org/145123003/ Export primary insecure and secure QUIC config id via internal server status pages. Merge internal change: 60108488 https://codereview.chromium.org/137423015/ Export SCIDs, QUIC secret seed names and orbits to varz. Merge internal change: 60107113 https://codereview.chromium.org/144033006/ Refactor QuicConnection to use explicit notification for getting onto the write blocked list. Remove the PacketWriter interface from QuicDispatcher. Merge internal change: 60103466 Fix build. Build got broken by a race between presubmit tests and me editing the file that was in the process of being submitted. :( Merge internal change: 60104577 https://codereview.chromium.org/149263002/ Remove the word Payload from AddFrame methods in QUIC framer. Merge internal change: 60101552 https://codereview.chromium.org/131513022/ Fixes QUIC's Cubic sender to use correct alpha when in Reno mode. Merge internal change: 60088487 https://codereview.chromium.org/136453013/ Add DFATALs to QuicFramer branches where packet creation fails. Merge internal change: 60077767 https://codereview.chromium.org/148073002/ Fix a QUIC bug where previously undecryptable packets were not decrypted before sending out an ack when the encryption level changed. Merge internal change: 60051502 Added logging for all frame types. Added code to dump frames and packet_headers. Changes to make QuicHttpStreamTest work. https://codereview.chromium.org/144063012/ R=rch@chromium.org Review URL: https://codereview.chromium.org/146033003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@247827 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/quic/congestion_control')
-rw-r--r--net/quic/congestion_control/cubic.cc46
-rw-r--r--net/quic/congestion_control/cubic_test.cc35
-rw-r--r--net/quic/congestion_control/tcp_cubic_sender.cc2
-rw-r--r--net/quic/congestion_control/tcp_cubic_sender_test.cc4
4 files changed, 57 insertions, 30 deletions
diff --git a/net/quic/congestion_control/cubic.cc b/net/quic/congestion_control/cubic.cc
index 2212098..938faaea 100644
--- a/net/quic/congestion_control/cubic.cc
+++ b/net/quic/congestion_control/cubic.cc
@@ -26,10 +26,26 @@ const int kCubeScale = 40; // 1024*1024^3 (first 1024 is from 0.100^3)
const int kCubeCongestionWindowScale = 410;
const uint64 kCubeFactor = (GG_UINT64_C(1) << kCubeScale) /
kCubeCongestionWindowScale;
-const uint32 kBetaSPDY = 939; // Back off factor after loss for SPDY, reduces
- // the CWND by 1/12th.
-const uint32 kBetaLastMax = 871; // Additional back off factor after loss for
- // the stored max value.
+
+const uint32 kNumConnections = 2;
+const float kBeta = static_cast<float>(0.7); // Default Cubic backoff factor.
+// Additional backoff factor when loss occurs in the concave part of the Cubic
+// curve. This additional backoff factor is expected to give up bandwidth to
+// new concurrent flows and speed up convergence.
+const float kBetaLastMax = static_cast<float>(0.85);
+
+// kNConnectionBeta is the backoff factor after loss for our N-connection
+// emulation, which emulates the effective backoff of an ensemble of N TCP-Reno
+// connections on a single loss event. The effective multiplier is computed as:
+const float kNConnectionBeta = (kNumConnections - 1 + kBeta) / kNumConnections;
+
+// TCPFriendly alpha is described in Section 3.3 of the CUBIC paper. Note that
+// kBeta here is a cwnd multiplier, and is equal to 1-beta from the CUBIC paper.
+// We derive the equivalent kNConnectionAlpha for an N-connection emulation as:
+const float kNConnectionAlpha = 3 * kNumConnections * kNumConnections *
+ (1 - kNConnectionBeta) / (1 + kNConnectionBeta);
+// TODO(jri): Compute kNConnectionBeta and kNConnectionAlpha from
+// number of active streams.
} // namespace
Cubic::Cubic(const QuicClock* clock)
@@ -57,12 +73,12 @@ QuicTcpCongestionWindow Cubic::CongestionWindowAfterPacketLoss(
// We never reached the old max, so assume we are competing with another
// flow. Use our extra back off factor to allow the other flow to go up.
last_max_congestion_window_ =
- (kBetaLastMax * current_congestion_window) >> 10;
+ static_cast<int>(kBetaLastMax * current_congestion_window);
} else {
last_max_congestion_window_ = current_congestion_window;
}
epoch_ = QuicTime::Zero(); // Reset time.
- return (current_congestion_window * kBetaSPDY) >> 10;
+ return static_cast<int>(current_congestion_window * kNConnectionBeta);
}
QuicTcpCongestionWindow Cubic::CongestionWindowAfterAck(
@@ -114,13 +130,21 @@ QuicTcpCongestionWindow Cubic::CongestionWindowAfterAck(
// We have a new cubic congestion window.
last_target_congestion_window_ = target_congestion_window;
- // Update estimated TCP congestion_window.
- // Note: we do a normal Reno congestion avoidance calculation not the
- // calculation described in section 3.3 TCP-friendly region of the document.
- while (acked_packets_count_ >= estimated_tcp_congestion_window_) {
- acked_packets_count_ -= estimated_tcp_congestion_window_;
+ DCHECK_LT(0u, estimated_tcp_congestion_window_);
+ // With dynamic beta/alpha based on number of active streams, it is possible
+ // for the required_ack_count to become much lower than acked_packets_count_
+ // suddenly, leading to more than one iteration through the following loop.
+ while (true) {
+ // Update estimated TCP congestion_window.
+ uint32 required_ack_count =
+ estimated_tcp_congestion_window_ / kNConnectionAlpha;
+ if (acked_packets_count_ < required_ack_count) {
+ break;
+ }
+ acked_packets_count_ -= required_ack_count;
estimated_tcp_congestion_window_++;
}
+
// Compute target congestion_window based on cubic target and estimated TCP
// congestion_window, use highest (fastest).
if (target_congestion_window < estimated_tcp_congestion_window_) {
diff --git a/net/quic/congestion_control/cubic_test.cc b/net/quic/congestion_control/cubic_test.cc
index 8e0d8e9..00bd37b 100644
--- a/net/quic/congestion_control/cubic_test.cc
+++ b/net/quic/congestion_control/cubic_test.cc
@@ -11,6 +11,12 @@
namespace net {
namespace test {
+const float kBeta = static_cast<float>(0.7); // Default Cubic backoff factor.
+const uint32 kNumConnections = 2;
+const float kNConnectionBeta = (kNumConnections - 1 + kBeta) / kNumConnections;
+const float kNConnectionAlpha = 3 * kNumConnections * kNumConnections *
+ (1 - kNConnectionBeta) / (1 + kNConnectionBeta);
+
class CubicTest : public ::testing::Test {
protected:
CubicTest()
@@ -24,7 +30,7 @@ class CubicTest : public ::testing::Test {
Cubic cubic_;
};
-TEST_F(CubicTest, AboveOrgin) {
+TEST_F(CubicTest, AboveOrigin) {
// Convex growth.
const QuicTime::Delta rtt_min = hundred_ms_;
uint32 current_cwnd = 10;
@@ -36,14 +42,14 @@ TEST_F(CubicTest, AboveOrgin) {
current_cwnd = expected_cwnd;
// Normal TCP phase.
for (int i = 0; i < 48; ++i) {
- for (uint32 n = 1; n < current_cwnd; ++n) {
+ for (uint32 n = 1; n < current_cwnd / kNConnectionAlpha; ++n) {
// Call once per ACK.
- EXPECT_EQ(current_cwnd,
- cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min));
+ EXPECT_NEAR(current_cwnd,
+ cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min), 1);
}
clock_.AdvanceTime(hundred_ms_);
current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min);
- EXPECT_EQ(expected_cwnd, current_cwnd);
+ EXPECT_NEAR(expected_cwnd, current_cwnd, 1);
expected_cwnd++;
}
// Cubic phase.
@@ -70,15 +76,15 @@ TEST_F(CubicTest, LossEvents) {
clock_.AdvanceTime(one_ms_);
EXPECT_EQ(expected_cwnd,
cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min));
- expected_cwnd = current_cwnd * 939 / 1024;
+ expected_cwnd = static_cast<int>(current_cwnd * kNConnectionBeta);
EXPECT_EQ(expected_cwnd,
cubic_.CongestionWindowAfterPacketLoss(current_cwnd));
- expected_cwnd = current_cwnd * 939 / 1024;
+ expected_cwnd = static_cast<int>(current_cwnd * kNConnectionBeta);
EXPECT_EQ(expected_cwnd,
cubic_.CongestionWindowAfterPacketLoss(current_cwnd));
}
-TEST_F(CubicTest, BelowOrgin) {
+TEST_F(CubicTest, BelowOrigin) {
// Concave growth.
const QuicTime::Delta rtt_min = hundred_ms_;
uint32 current_cwnd = 422;
@@ -87,23 +93,18 @@ TEST_F(CubicTest, BelowOrgin) {
clock_.AdvanceTime(one_ms_);
EXPECT_EQ(expected_cwnd,
cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min));
- expected_cwnd = current_cwnd * 939 / 1024;
+ expected_cwnd = static_cast<int>(current_cwnd * kNConnectionBeta);
EXPECT_EQ(expected_cwnd,
cubic_.CongestionWindowAfterPacketLoss(current_cwnd));
current_cwnd = expected_cwnd;
- // First update after epoch.
+ // First update after loss to initialize the epoch.
current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min);
// Cubic phase.
- for (int i = 0; i < 54; ++i) {
- for (uint32 n = 1; n < current_cwnd; ++n) {
- // Call once per ACK.
- EXPECT_EQ(current_cwnd,
- cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min));
- }
+ for (int i = 0; i < 40 ; ++i) {
clock_.AdvanceTime(hundred_ms_);
current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min);
}
- expected_cwnd = 440;
+ expected_cwnd = 422;
EXPECT_EQ(expected_cwnd, current_cwnd);
}
diff --git a/net/quic/congestion_control/tcp_cubic_sender.cc b/net/quic/congestion_control/tcp_cubic_sender.cc
index a978cf6..b44d2da 100644
--- a/net/quic/congestion_control/tcp_cubic_sender.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender.cc
@@ -24,7 +24,7 @@ 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 int kInitialRttMs = 100; // At a typical RTT 100 ms.
const float kAlpha = 0.125f;
const float kOneMinusAlpha = (1 - kAlpha);
const float kBeta = 0.25f;
diff --git a/net/quic/congestion_control/tcp_cubic_sender_test.cc b/net/quic/congestion_control/tcp_cubic_sender_test.cc
index 9faecc4..88921ba 100644
--- a/net/quic/congestion_control/tcp_cubic_sender_test.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender_test.cc
@@ -498,7 +498,9 @@ TEST_F(TcpCubicSenderTest, TcpRenoMaxCongestionWindow) {
TEST_F(TcpCubicSenderTest, TcpCubicMaxCongestionWindow) {
const QuicTcpCongestionWindow kMaxCongestionWindowTCP = 50;
- const int kNumberOfAcks = 1000;
+ // Set to 10000 to compensate for small cubic alpha.
+ const int kNumberOfAcks = 10000;
+
sender_.reset(
new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP));