For IETF QUIC, do not detect path degrading or blackholing until handshake gets confirmed. (no change to gQUIC)
Protected by FLAGS_quic_reloadable_flag_quic_no_path_degrading_before_handshake_confirmed.
PiperOrigin-RevId: 491689909
diff --git a/quiche/quic/core/quic_connection.cc b/quiche/quic/core/quic_connection.cc
index b16c933..91fc27c 100644
--- a/quiche/quic/core/quic_connection.cc
+++ b/quiche/quic/core/quic_connection.cc
@@ -6356,6 +6356,15 @@
if (!connected_) {
return false;
}
+ if (GetQuicReloadableFlag(
+ quic_no_path_degrading_before_handshake_confirmed) &&
+ SupportsMultiplePacketNumberSpaces()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_no_path_degrading_before_handshake_confirmed, 1, 2);
+ // No path degrading detection before handshake confirmed.
+ return perspective_ == Perspective::IS_CLIENT && IsHandshakeConfirmed() &&
+ !is_path_degrading_;
+ }
// No path degrading detection before handshake completes.
if (!idle_network_detector_.handshake_timeout().IsInfinite()) {
return false;
@@ -6396,6 +6405,13 @@
if (!connected_ || blackhole_detection_disabled_) {
return false;
}
+ if (GetQuicReloadableFlag(
+ quic_no_path_degrading_before_handshake_confirmed) &&
+ SupportsMultiplePacketNumberSpaces() && !IsHandshakeConfirmed()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_no_path_degrading_before_handshake_confirmed, 2, 2);
+ return false;
+ }
// No blackhole detection before handshake completes.
if (default_enable_5rto_blackhole_detection_) {
QUIC_RELOADABLE_FLAG_COUNT_N(quic_default_enable_5rto_blackhole_detection2,
diff --git a/quiche/quic/core/quic_connection_test.cc b/quiche/quic/core/quic_connection_test.cc
index 2152a6f..e700d88 100644
--- a/quiche/quic/core/quic_connection_test.cc
+++ b/quiche/quic/core/quic_connection_test.cc
@@ -7160,6 +7160,9 @@
EXPECT_TRUE(connection_.connected());
EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
EXPECT_FALSE(connection_.IsPathDegrading());
+ EXPECT_CALL(visitor_, GetHandshakeState())
+ .WillRepeatedly(Return(HANDSHAKE_CONFIRMED));
+ connection_.OnHandshakeComplete();
const char data[] = "data";
size_t data_size = strlen(data);
@@ -7245,6 +7248,9 @@
EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
EXPECT_FALSE(connection_.IsPathDegrading());
EXPECT_FALSE(connection_.GetPingAlarm()->IsSet());
+ EXPECT_CALL(visitor_, GetHandshakeState())
+ .WillRepeatedly(Return(HANDSHAKE_CONFIRMED));
+ connection_.OnHandshakeComplete();
const char data[] = "data";
size_t data_size = strlen(data);
@@ -7290,7 +7296,7 @@
// Now there's a retransmittable packet (PING) on the wire, so the path
// degrading alarm should be set.
- EXPECT_TRUE(connection_.PathDegradingDetectionInProgress());
+ ASSERT_TRUE(connection_.PathDegradingDetectionInProgress());
delay = QuicConnectionPeer::GetSentPacketManager(&connection_)
->GetPathDegradingDelay();
EXPECT_EQ(delay, connection_.GetBlackholeDetectorAlarm()->deadline() -
@@ -7487,6 +7493,9 @@
EXPECT_TRUE(connection_.connected());
EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
EXPECT_FALSE(connection_.IsPathDegrading());
+ EXPECT_CALL(visitor_, GetHandshakeState())
+ .WillRepeatedly(Return(HANDSHAKE_CONFIRMED));
+ connection_.OnHandshakeComplete();
const char data[] = "data";
size_t data_size = strlen(data);
@@ -7546,6 +7555,23 @@
EXPECT_TRUE(connection_.IsPathDegrading());
}
+TEST_P(QuicConnectionTest, NoPathDegradingDetectionBeforeHandshakeConfirmed) {
+ EXPECT_TRUE(connection_.connected());
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
+ EXPECT_FALSE(connection_.IsPathDegrading());
+ EXPECT_CALL(visitor_, GetHandshakeState())
+ .WillRepeatedly(Return(HANDSHAKE_COMPLETE));
+
+ connection_.SendStreamDataWithString(1, "data", 0, NO_FIN);
+ if (GetQuicReloadableFlag(
+ quic_no_path_degrading_before_handshake_confirmed) &&
+ connection_.SupportsMultiplePacketNumberSpaces()) {
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
+ } else {
+ EXPECT_TRUE(connection_.PathDegradingDetectionInProgress());
+ }
+}
+
// This test verifies that the connection unmarks path as degrarding and spins
// the timer to detect future path degrading when forward progress is made
// after path has been marked degrading.
@@ -7553,6 +7579,9 @@
EXPECT_TRUE(connection_.connected());
EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
EXPECT_FALSE(connection_.IsPathDegrading());
+ EXPECT_CALL(visitor_, GetHandshakeState())
+ .WillRepeatedly(Return(HANDSHAKE_CONFIRMED));
+ connection_.OnHandshakeComplete();
const char data[] = "data";
size_t data_size = strlen(data);
@@ -9445,7 +9474,9 @@
}
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
connection_.SetFromConfig(config);
- if (GetQuicReloadableFlag(quic_default_enable_5rto_blackhole_detection2)) {
+ if (GetQuicReloadableFlag(quic_default_enable_5rto_blackhole_detection2) ||
+ GetQuicReloadableFlag(
+ quic_no_path_degrading_before_handshake_confirmed)) {
EXPECT_CALL(visitor_, GetHandshakeState())
.WillRepeatedly(Return(HANDSHAKE_CONFIRMED));
}
@@ -9495,7 +9526,9 @@
}
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
connection_.SetFromConfig(config);
- if (GetQuicReloadableFlag(quic_default_enable_5rto_blackhole_detection2)) {
+ if (GetQuicReloadableFlag(quic_default_enable_5rto_blackhole_detection2) ||
+ GetQuicReloadableFlag(
+ quic_no_path_degrading_before_handshake_confirmed)) {
EXPECT_CALL(visitor_, GetHandshakeState())
.WillRepeatedly(Return(HANDSHAKE_CONFIRMED));
}
@@ -9544,7 +9577,9 @@
config.SetConnectionOptionsToSend(connection_options);
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
connection_.SetFromConfig(config);
- if (GetQuicReloadableFlag(quic_default_enable_5rto_blackhole_detection2)) {
+ if (GetQuicReloadableFlag(quic_default_enable_5rto_blackhole_detection2) ||
+ GetQuicReloadableFlag(
+ quic_no_path_degrading_before_handshake_confirmed)) {
EXPECT_CALL(visitor_, GetHandshakeState())
.WillRepeatedly(Return(HANDSHAKE_CONFIRMED));
}
@@ -10642,7 +10677,8 @@
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
connection_.SetFromConfig(config);
EXPECT_CALL(visitor_, GetHandshakeState())
- .WillRepeatedly(Return(HANDSHAKE_COMPLETE));
+ .WillRepeatedly(Return(HANDSHAKE_CONFIRMED));
+ connection_.OnHandshakeComplete();
EXPECT_FALSE(connection_.GetBlackholeDetectorAlarm()->IsSet());
// Send stream data.
SendStreamDataToPeer(
@@ -10694,7 +10730,9 @@
connection_options.push_back(k5RTO);
config.SetConnectionOptionsToSend(connection_options);
QuicConfigPeer::SetNegotiated(&config, true);
- if (GetQuicReloadableFlag(quic_default_enable_5rto_blackhole_detection2)) {
+ if (GetQuicReloadableFlag(quic_default_enable_5rto_blackhole_detection2) ||
+ GetQuicReloadableFlag(
+ quic_no_path_degrading_before_handshake_confirmed)) {
EXPECT_CALL(visitor_, GetHandshakeState())
.WillRepeatedly(Return(HANDSHAKE_COMPLETE));
}
@@ -10708,10 +10746,20 @@
connection_.SetFromConfig(config);
connection_.SendCryptoDataWithString("foo", 0, ENCRYPTION_HANDSHAKE);
- EXPECT_TRUE(connection_.BlackholeDetectionInProgress());
+ if (GetQuicReloadableFlag(
+ quic_no_path_degrading_before_handshake_confirmed)) {
+ // No blackhole detection before handshake confirmed.
+ EXPECT_FALSE(connection_.BlackholeDetectionInProgress());
+ } else {
+ EXPECT_TRUE(connection_.BlackholeDetectionInProgress());
+ }
// Discard handshake keys.
+ EXPECT_CALL(visitor_, GetHandshakeState())
+ .WillRepeatedly(Return(HANDSHAKE_CONFIRMED));
connection_.OnHandshakeComplete();
- if (GetQuicReloadableFlag(quic_default_enable_5rto_blackhole_detection2)) {
+ if (GetQuicReloadableFlag(quic_default_enable_5rto_blackhole_detection2) ||
+ GetQuicReloadableFlag(
+ quic_no_path_degrading_before_handshake_confirmed)) {
// Verify blackhole detection stops.
EXPECT_FALSE(connection_.BlackholeDetectionInProgress());
} else {
@@ -11232,7 +11280,7 @@
connection_.NeuterUnencryptedPackets();
connection_.OnHandshakeComplete();
EXPECT_CALL(visitor_, GetHandshakeState())
- .WillRepeatedly(Return(HANDSHAKE_COMPLETE));
+ .WillRepeatedly(Return(HANDSHAKE_CONFIRMED));
std::string data(1200, 'a');
// Send data packets 1 - 5.
@@ -15419,7 +15467,7 @@
connection_.RemoveEncrypter(ENCRYPTION_INITIAL);
connection_.RemoveEncrypter(ENCRYPTION_HANDSHAKE);
EXPECT_CALL(visitor_, GetHandshakeState())
- .WillRepeatedly(Return(HANDSHAKE_COMPLETE));
+ .WillRepeatedly(Return(HANDSHAKE_CONFIRMED));
SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr);
ASSERT_TRUE(connection_.BlackholeDetectionInProgress());
diff --git a/quiche/quic/core/quic_flags_list.h b/quiche/quic/core/quic_flags_list.h
index 154ad0c..a38464c 100644
--- a/quiche/quic/core/quic_flags_list.h
+++ b/quiche/quic/core/quic_flags_list.h
@@ -29,6 +29,8 @@
QUIC_FLAG(quic_reloadable_flag_quic_can_send_ack_frequency, true)
// If true, allow client to enable BBRv2 on server via connection option \'B2ON\'.
QUIC_FLAG(quic_reloadable_flag_quic_allow_client_enabled_bbr_v2, true)
+// If true, an endpoint does not detect path degrading or blackholing until handshake gets confirmed.
+QUIC_FLAG(quic_reloadable_flag_quic_no_path_degrading_before_handshake_confirmed, true)
// If true, combine two WriteOrBufferData to one while writing headers.
QUIC_FLAG(quic_reloadable_flag_quic_one_write_for_headers, true)
// If true, default-enable 5RTO blachole detection.