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.