Skip to content

Commit

Permalink
Land Recent QUIC Changes until 04/30/2015.
Browse files Browse the repository at this point in the history
Deprecate --FLAGS_quic_do_not_retransmit_for_reset_streams.

Merge internal change: 92249265
https://codereview.chromium.org/1111703003/

Remove QUIC v23

This means that the headers stream only speaks SPDY/4.
This removes the congestion feedback tag vector from the handshake.

Merge internal change: 92245766
https://codereview.chromium.org/1115883002/

Fix a minor bug in TcpCubicSender in the conversion from packets to bytes.

Merge internal change: 92010035
https://codereview.chromium.org/1103163006/

Don't calculate or send bandwidth resumption source address tokens when
the bandwidth resumption experiment is disabled.

Estimated to save 0.5% of CPU on bandaid.

Merge internal change: 92003353
https://codereview.chromium.org/1113833003/

Allocate encrypted packets into a buffer on the stack.

Estimated to save ~4% of CPU.

Merge internal change: 92000931
https://codereview.chromium.org/1115873002/

Flag-protected. Add SREJ support to quic crypto server config.

ProcessClientHello and BuildRejection now take two extra arugments,
indicating a) that the server should generate stateless rejects and b)
if stateless, the new connection ID that should be added to the message.

In theory, every reject emitted could be a stateless reject.  The
tests have been modified with two new parameters:

1.  Stateless reject support enabled via flag.
2.  Server configured to emit stateless rejects.

They then check to ensure that, if enabled, the reject is formatted
correctly.

In chromium, set FLAGS_enable_quic_stateless_reject_support to false.

Merge internal change: 91946386
https://codereview.chromium.org/1112693005/

Break out QUIC's balsa-specific SPDY utilities from SpdyUtils to
SpdyBalsaUtils to help ease the process of merging to Chrome.

Merge internal change: 91854176
https://codereview.chromium.org/1112923002/

Prevent a crash when the stream frame is NULL. Log an detailed DFATAL
and close the connection instead.

Merge internal change: 91820383
https://codereview.chromium.org/1111413004/

Doing a better job of cleaning up quic udp proxy state.

Fully tearing down the client we use for probing connectivity to core
when we do UDP proxying, while preserving the file descriptor.

Chrome specific change: make CleanUpUDPSocket virtual.

Merge internal change: 91805238
https://codereview.chromium.org/1120433002/

Update QuicPacketGeneratorTest to save every packet when it's serialized
into a vector instead of into separate variables.  Test only change.

Merge internal change: 91631596
https://codereview.chromium.org/1105283003/

Update QuicPacketGeneratorTest to save every packet when it's serialized
into a vector instead of into separate variables.  Test only change.

Merge internal change: 91631596
https://codereview.chromium.org/1105283003/

Change QuicPacketGenerator's destructor to use the more compact for
syntax.  No functional change.

Merge internal change: 91620560
https://codereview.chromium.org/1117503002/

Adding a comment to make clear the toy server is a toy.

Merge internal change: 91604221
https://codereview.chromium.org/1113713002/

Minor code QUIC readability improvements.  No functional changes.

Merge internal change: 91545808
https://codereview.chromium.org/1116543002/

Add QuicClientCryptoConfig stateless-reject support.

(This change is not flag-protected, since it only affects the
client-side.)

When the QuicClientCryptoConfig receives a stateless reject, it will
read the server-designated connection ID from the reject message.  It
will store that ID in its cached config for subsequent use.

The Cache itself can now store a server-designated connection-id for
one-time use.  Clients can query the cache to see whether it stores a
server-designated connection-ID.  If so, the client can consume the
ID.  Subsequent queries will indicate that there is no
server-designated connection-ID until another stateless reject is
returned.

Note:  Currently, the cached config state only stores one
server-designated connection ID at a time.

Merge internal change: 91419089
https://codereview.chromium.org/1116463004/

Adding EXPECT_CALLs to prevent gMock warnings. Replacing scoped_ptr with
unique_ptr. Lowering some DLOG(INFO)s to DVLOG(1).

n/a (Tests and debug logging only.)

Merge internal change: 91343963
https://codereview.chromium.org/1117483002/

Remove unused argument TransmissionType from QUIC's ShouldGeneratePacket.
No functional change.

Merge internal change: 91300968
https://codereview.chromium.org/1113553003/

Reorganize the packet validity check code.  Add checks to not create
connections for packets with large seq. nos. or truncated conn. IDs.

Reorganize the packet validity checks to make the packet sequence number
accessible to the dispatcher's packet-classification logic: Put most of
the logic in OnUnauthenticatedHeader, which is called after the sequence
number is decoded.

Add validity checks and tests of the validity checks.

Merge internal change: 91299299
https://codereview.chromium.org/1110243002/

Setting QoS for UDP proxy backends (two machine canary on internal servers).

Merge internal change: 91293512
https://codereview.chromium.org/1109793006/

R=rch@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#327851}
  • Loading branch information
rtenneti authored and Commit bot committed May 1, 2015
1 parent 8370255 commit e0ee6eb
Show file tree
Hide file tree
Showing 71 changed files with 1,219 additions and 857 deletions.
4 changes: 2 additions & 2 deletions net/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -745,8 +745,8 @@ source_set("balsa") {
"tools/balsa/split.cc",
"tools/balsa/split.h",
"tools/balsa/string_piece_utils.h",
"tools/quic/spdy_utils.cc",
"tools/quic/spdy_utils.h",
"tools/quic/spdy_balsa_utils.cc",
"tools/quic/spdy_balsa_utils.h",
]
deps = [
":net",
Expand Down
4 changes: 2 additions & 2 deletions net/net.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -765,8 +765,8 @@
'tools/balsa/split.cc',
'tools/balsa/split.h',
'tools/balsa/string_piece_utils.h',
'tools/quic/spdy_utils.cc',
'tools/quic/spdy_utils.h',
'tools/quic/spdy_balsa_utils.cc',
'tools/quic/spdy_balsa_utils.h',
],
},
{
Expand Down
3 changes: 1 addition & 2 deletions net/quic/congestion_control/cubic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,7 @@ QuicPacketCount Cubic::CongestionWindowAfterAck(
time_to_origin_point_ =
static_cast<uint32>(cbrt(kCubeFactor * (last_max_congestion_window_ -
current_congestion_window)));
origin_point_congestion_window_ =
last_max_congestion_window_;
origin_point_congestion_window_ = last_max_congestion_window_;
}
}
// Change the time unit from microseconds to 2^10 fractions per second. Take
Expand Down
4 changes: 2 additions & 2 deletions net/quic/congestion_control/hybrid_slow_start.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ bool HybridSlowStart::IsEndOfRound(QuicPacketSequenceNumber ack) const {

bool HybridSlowStart::ShouldExitSlowStart(QuicTime::Delta latest_rtt,
QuicTime::Delta min_rtt,
int64 congestion_window) {
QuicPacketCount congestion_window) {
if (!started_) {
// Time to start the hybrid slow start.
StartReceiveRound(last_sent_sequence_number_);
Expand All @@ -87,7 +87,7 @@ bool HybridSlowStart::ShouldExitSlowStart(QuicTime::Delta latest_rtt,
}
// We only need to check this once per round.
if (rtt_sample_count_ == kHybridStartMinSamples) {
// Divide min_rtt by 16 to get a rtt increase threshold for exiting.
// Divide min_rtt by 8 to get a rtt increase threshold for exiting.
int64 min_rtt_increase_threshold_us = min_rtt.ToMicroseconds() >>
kHybridStartDelayFactorExp;
// Ensure the rtt threshold is never less than 2ms or more than 16ms.
Expand Down
2 changes: 1 addition & 1 deletion net/quic/congestion_control/hybrid_slow_start.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class NET_EXPORT_PRIVATE HybridSlowStart {
// congestion_window: the congestion window in packets.
bool ShouldExitSlowStart(QuicTime::Delta rtt,
QuicTime::Delta min_rtt,
int64 congestion_window);
QuicPacketCount congestion_window);

// Start a new slow start phase.
void Restart();
Expand Down
13 changes: 7 additions & 6 deletions net/quic/congestion_control/tcp_cubic_bytes_sender.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace {
// fast retransmission.
const QuicByteCount kDefaultMinimumCongestionWindow = 2 * kDefaultTCPMSS;
const QuicByteCount kMaxSegmentSize = kDefaultTCPMSS;
const int kMaxBurstLength = 3;
const QuicByteCount kMaxBurstBytes = 3 * kMaxSegmentSize;
const float kRenoBeta = 0.7f; // Reno backoff factor.
const uint32 kDefaultNumConnections = 2; // N-connection emulation.
} // namespace
Expand All @@ -48,7 +48,7 @@ TcpCubicBytesSender::TcpCubicBytesSender(
min_congestion_window_(kDefaultMinimumCongestionWindow),
min4_mode_(false),
max_congestion_window_(max_congestion_window * kMaxSegmentSize),
slowstart_threshold_(std::numeric_limits<uint64>::max()),
slowstart_threshold_(max_congestion_window * kMaxSegmentSize),
last_cutback_exited_slowstart_(false),
clock_(clock) {
}
Expand Down Expand Up @@ -298,11 +298,10 @@ bool TcpCubicBytesSender::IsCwndLimited(QuicByteCount bytes_in_flight) const {
if (bytes_in_flight >= congestion_window_) {
return true;
}
const QuicByteCount max_burst = kMaxBurstLength * kMaxSegmentSize;
const QuicByteCount available_bytes = congestion_window_ - bytes_in_flight;
const bool slow_start_limited =
InSlowStart() && bytes_in_flight > congestion_window_ / 2;
return slow_start_limited || available_bytes <= max_burst;
return slow_start_limited || available_bytes <= kMaxBurstBytes;
}

bool TcpCubicBytesSender::InRecovery() const {
Expand Down Expand Up @@ -348,8 +347,10 @@ void TcpCubicBytesSender::MaybeIncreaseCwnd(
<< " slowstart threshold: " << slowstart_threshold_
<< " congestion window count: " << num_acked_packets_;
} else {
congestion_window_ = cubic_.CongestionWindowAfterAck(
acked_bytes, congestion_window_, rtt_stats_->min_rtt());
congestion_window_ =
min(max_congestion_window_,
cubic_.CongestionWindowAfterAck(acked_bytes, congestion_window_,
rtt_stats_->min_rtt()));
DVLOG(1) << "Cubic; congestion window: " << congestion_window_
<< " slowstart threshold: " << slowstart_threshold_;
}
Expand Down
21 changes: 8 additions & 13 deletions net/quic/congestion_control/tcp_cubic_sender.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace {
// fast retransmission. The cwnd after a timeout is still 1.
const QuicPacketCount kDefaultMinimumCongestionWindow = 2;
const QuicByteCount kMaxSegmentSize = kDefaultTCPMSS;
const int kMaxBurstLength = 3;
const QuicByteCount kMaxBurstBytes = 3 * kMaxSegmentSize;
const float kRenoBeta = 0.7f; // Reno backoff factor.
const uint32 kDefaultNumConnections = 2; // N-connection emulation.
} // namespace
Expand Down Expand Up @@ -295,17 +295,15 @@ QuicByteCount TcpCubicSender::GetSlowStartThreshold() const {
}

bool TcpCubicSender::IsCwndLimited(QuicByteCount bytes_in_flight) const {
const QuicByteCount congestion_window_bytes = congestion_window_ *
kMaxSegmentSize;
const QuicByteCount congestion_window_bytes = GetCongestionWindow();
if (bytes_in_flight >= congestion_window_bytes) {
return true;
}
const QuicByteCount max_burst = kMaxBurstLength * kMaxSegmentSize;
const QuicByteCount available_bytes =
congestion_window_bytes - bytes_in_flight;
const bool slow_start_limited = InSlowStart() &&
bytes_in_flight > congestion_window_bytes / 2;
return slow_start_limited || available_bytes <= max_burst;
return slow_start_limited || available_bytes <= kMaxBurstBytes;
}

bool TcpCubicSender::InRecovery() const {
Expand All @@ -324,19 +322,16 @@ void TcpCubicSender::MaybeIncreaseCwnd(
// window we have available.
return;
}
if (congestion_window_ >= max_tcp_congestion_window_) {
return;
}
if (InSlowStart()) {
// 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_;
}
// 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.
Expand Down
1 change: 0 additions & 1 deletion net/quic/crypto/crypto_handshake_message.cc
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,6 @@ string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
break;
case kKEXS:
case kAEAD:
case kCGST:
case kCOPT:
case kPDMD:
case kVER:
Expand Down
2 changes: 0 additions & 2 deletions net/quic/crypto/crypto_protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,6 @@ const QuicTag kNONC = TAG('N', 'O', 'N', 'C'); // The client's nonce
const QuicTag kKEXS = TAG('K', 'E', 'X', 'S'); // Key exchange methods
const QuicTag kAEAD = TAG('A', 'E', 'A', 'D'); // Authenticated
// encryption algorithms
const QuicTag kCGST = TAG('C', 'G', 'S', 'T'); // Congestion control
// feedback types
const QuicTag kCOPT = TAG('C', 'O', 'P', 'T'); // Connection options
const QuicTag kICSL = TAG('I', 'C', 'S', 'L'); // Idle connection state
// lifetime
Expand Down
89 changes: 74 additions & 15 deletions net/quic/crypto/crypto_server_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "testing/gtest/include/gtest/gtest.h"

using base::StringPiece;
using std::endl;
using std::ostream;
using std::string;
using std::vector;
Expand All @@ -45,24 +46,44 @@ class QuicCryptoServerConfigPeer {
// Run tests with both parities of
// FLAGS_use_early_return_when_verifying_chlo.
struct TestParams {
explicit TestParams(bool use_early_return_when_verifying_chlo)
explicit TestParams(bool use_early_return_when_verifying_chlo,
bool enable_stateless_rejects,
bool use_stateless_rejects)
: use_early_return_when_verifying_chlo(
use_early_return_when_verifying_chlo) {}
use_early_return_when_verifying_chlo),
enable_stateless_rejects(enable_stateless_rejects),
use_stateless_rejects(use_stateless_rejects) {}

friend ostream& operator<<(ostream& os, const TestParams& p) {
os << "{ use_early_return_when_verifying_chlo: "
<< p.use_early_return_when_verifying_chlo << " }";
<< p.use_early_return_when_verifying_chlo << endl;
os << " enable_stateless_rejects: " << p.enable_stateless_rejects << endl;
os << " use_stateless_rejects: " << p.use_stateless_rejects << " }";
return os;
}

bool use_early_return_when_verifying_chlo;
// This only enables the stateless reject feature via the feature-flag.
// It does not force the crypto server to emit stateless rejects.
bool enable_stateless_rejects;
// If true, this forces the server to send a stateless reject when
// rejecting messages. This should be a no-op if
// enable_stateless_rejects is false.
bool use_stateless_rejects;
};

// Constructs various test permutations.
vector<TestParams> GetTestParams() {
vector<TestParams> params;
params.push_back(TestParams(false));
params.push_back(TestParams(true));
static const bool kTrueFalse[] = {true, false};
for (bool use_early_return : kTrueFalse) {
for (bool enable_stateless_rejects : kTrueFalse) {
for (bool use_stateless_rejects : kTrueFalse) {
params.push_back(TestParams(use_early_return, enable_stateless_rejects,
use_stateless_rejects));
}
}
}
return params;
}

Expand All @@ -79,6 +100,9 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {

FLAGS_use_early_return_when_verifying_chlo =
GetParam().use_early_return_when_verifying_chlo;
FLAGS_enable_quic_stateless_reject_support =
GetParam().enable_stateless_rejects;
use_stateless_rejects_ = GetParam().use_stateless_rejects;
}

void SetUp() override {
Expand Down Expand Up @@ -110,11 +134,12 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
ShouldSucceed(client_hello);
// The message should be rejected because the source-address token is
// missing.
ASSERT_EQ(kREJ, out_.tag());
CheckRejectTag();
const HandshakeFailureReason kRejectReasons[] = {
SERVER_CONFIG_INCHOATE_HELLO_FAILURE
};
CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
CheckForServerDesignatedConnectionId();

StringPiece srct;
ASSERT_TRUE(out_.GetStringPiece(kSourceAddressTokenTag, &srct));
Expand Down Expand Up @@ -219,9 +244,12 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
const char* error_substr) {
IPAddressNumber server_ip;
string error_details;
QuicConnectionId server_designated_connection_id =
rand_for_id_generation_.RandUint64();
QuicErrorCode error = config_.ProcessClientHello(
result, 1 /* ConnectionId */, server_ip, client_address_,
supported_versions_.front(), supported_versions_, &clock_, rand_,
supported_versions_.front(), supported_versions_,
use_stateless_rejects_, server_designated_connection_id, &clock_, rand_,
&params_, &out_, &error_details);

if (should_succeed) {
Expand Down Expand Up @@ -278,8 +306,39 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
}
}

// If the server is rejecting statelessly, make sure it contains a
// server-designated connection id. Once the check is complete,
// allow the random id-generator to move to the next value.
void CheckForServerDesignatedConnectionId() {
QuicConnectionId server_designated_connection_id;
if (!RejectsAreStateless()) {
EXPECT_EQ(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND,
out_.GetUint64(kRCID, &server_designated_connection_id));
} else {
ASSERT_EQ(QUIC_NO_ERROR,
out_.GetUint64(kRCID, &server_designated_connection_id));
EXPECT_EQ(rand_for_id_generation_.RandUint64(),
server_designated_connection_id);
}
rand_for_id_generation_.ChangeValue();
}

void CheckRejectTag() {
if (RejectsAreStateless()) {
ASSERT_EQ(kSREJ, out_.tag());
} else {
ASSERT_EQ(kREJ, out_.tag());
}
}

bool RejectsAreStateless() {
return GetParam().enable_stateless_rejects &&
GetParam().use_stateless_rejects;
}

protected:
QuicRandom* const rand_;
MockRandom rand_for_id_generation_;
MockClock clock_;
const IPEndPoint client_address_;
QuicVersionVector supported_versions_;
Expand All @@ -289,6 +348,7 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
QuicCryptoNegotiatedParameters params_;
CryptoHandshakeMessage out_;
uint8 orbit_[kOrbitSize];
bool use_stateless_rejects_;

// These strings contain hex escaped values from the server suitable for
// passing to |InchoateClientHello| when constructing client hello messages.
Expand All @@ -297,7 +357,7 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
};

// Run all CryptoServerTest with both values of
// FLAGS_use_early_return_when_verifying_chlo
// FLAGS_use_early_return_when_verifying_chlo.
INSTANTIATE_TEST_CASE_P(CryptoServerTests,
CryptoServerTest,
::testing::ValuesIn(GetTestParams()));
Expand Down Expand Up @@ -444,7 +504,7 @@ TEST_P(CryptoServerTest, CorruptServerConfig) {
"$padding", static_cast<int>(kClientHelloMinimumSize),
nullptr);
ShouldSucceed(msg);
ASSERT_EQ(kREJ, out_.tag());
CheckRejectTag();
const HandshakeFailureReason kRejectReasons[] = {
SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE
};
Expand All @@ -465,7 +525,7 @@ TEST_P(CryptoServerTest, CorruptSourceAddressToken) {
"$padding", static_cast<int>(kClientHelloMinimumSize),
nullptr);
ShouldSucceed(msg);
ASSERT_EQ(kREJ, out_.tag());
CheckRejectTag();
const HandshakeFailureReason kRejectReasons[] = {
SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
};
Expand All @@ -486,7 +546,7 @@ TEST_P(CryptoServerTest, CorruptClientNonceAndSourceAddressToken) {
"$padding", static_cast<int>(kClientHelloMinimumSize),
nullptr);
ShouldSucceed(msg);
ASSERT_EQ(kREJ, out_.tag());
CheckRejectTag();
const HandshakeFailureReason kRejectReasons[] = {
SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE,
CLIENT_NONCE_INVALID_FAILURE
Expand All @@ -509,7 +569,7 @@ TEST_P(CryptoServerTest, CorruptMultipleTags) {
"$padding", static_cast<int>(kClientHelloMinimumSize),
nullptr);
ShouldSucceed(msg);
ASSERT_EQ(kREJ, out_.tag());
CheckRejectTag();
const HandshakeFailureReason kRejectReasons[] = {
SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE,
CLIENT_NONCE_INVALID_FAILURE,
Expand All @@ -534,7 +594,7 @@ TEST_P(CryptoServerTest, ReplayProtection) {
ShouldSucceed(msg);
// The message should be rejected because the strike-register is still
// quiescent.
ASSERT_EQ(kREJ, out_.tag());
CheckRejectTag();

const HandshakeFailureReason kRejectReasons[] = {
CLIENT_NONCE_INVALID_TIME_FAILURE
Expand Down Expand Up @@ -595,7 +655,6 @@ TEST(CryptoServerConfigGenerationTest, SCIDVaries) {
EXPECT_NE(scid_a, scid_b);
}


TEST(CryptoServerConfigGenerationTest, SCIDIsHashOfServerConfig) {
MockRandom rand_a;
const QuicCryptoServerConfig::ConfigOptions options;
Expand Down Expand Up @@ -706,7 +765,7 @@ TEST_P(AsyncStrikeServerVerificationTest, AsyncReplayProtection) {
ASSERT_TRUE(called);
EXPECT_EQ(0, strike_register_client_->PendingVerifications());
// The message should be rejected now.
EXPECT_EQ(kREJ, out_.tag());
CheckRejectTag();
}

} // namespace test
Expand Down
Loading

0 comments on commit e0ee6eb

Please sign in to comment.