Enable QUIC spin bit configuration via QuicConfig: Only enable spin bit if both config requests it and ShouldEnableSpinBit() allows it (GFE flag is true and coin flip success). Protected by FLAGS_quic_reloadable_flag_quic_enable_spin_bit. PiperOrigin-RevId: 952064277
diff --git a/quiche/quic/core/quic_config.cc b/quiche/quic/core/quic_config.cc index 4b9c404..abb5913 100644 --- a/quiche/quic/core/quic_config.cc +++ b/quiche/quic/core/quic_config.cc
@@ -1059,6 +1059,7 @@ SetReliableStreamReset(false); scone_packet_interval_ = QuicTimeDelta::Zero(); parse_scone_packets_ = false; + enable_spin_bit_ = false; } void QuicConfig::ToHandshakeMessage( @@ -1537,4 +1538,8 @@ return reliable_stream_reset_; } +void QuicConfig::set_enable_spin_bit(bool enable) { enable_spin_bit_ = enable; } + +bool QuicConfig::enable_spin_bit() const { return enable_spin_bit_; } + } // namespace quic
diff --git a/quiche/quic/core/quic_config.h b/quiche/quic/core/quic_config.h index 79487d2..691a166 100644 --- a/quiche/quic/core/quic_config.h +++ b/quiche/quic/core/quic_config.h
@@ -475,6 +475,10 @@ void SetReliableStreamReset(bool reliable_stream_reset); bool SupportsReliableStreamReset() const; + // Whether the spin bit is enabled. + void set_enable_spin_bit(bool enable); + bool enable_spin_bit() const; + // Original destination connection ID. void SetOriginalConnectionIdToSend( const QuicConnectionId& original_destination_connection_id); @@ -777,6 +781,9 @@ // Support for RESET_STREAM_AT frame. bool reliable_stream_reset_; + + // Whether the spin bit is enabled. + bool enable_spin_bit_; }; } // namespace quic
diff --git a/quiche/quic/core/quic_connection.cc b/quiche/quic/core/quic_connection.cc index c7df04f..eedbef6 100644 --- a/quiche/quic/core/quic_connection.cc +++ b/quiche/quic/core/quic_connection.cc
@@ -447,6 +447,10 @@ config.max_idle_time_before_crypto_handshake()); } + if (config.enable_spin_bit()) { + spin_bit_enabled_ = ShouldEnableSpinBit(); + } + if (version().IsIetfQuic() && config.HasReceivedPreferredAddressConnectionIdAndToken()) { QuicNewConnectionIdFrame frame;
diff --git a/quiche/quic/core/quic_connection.h b/quiche/quic/core/quic_connection.h index e8db6f5..80f4104 100644 --- a/quiche/quic/core/quic_connection.h +++ b/quiche/quic/core/quic_connection.h
@@ -2596,7 +2596,7 @@ bool quic_close_on_idle_timeout_ : 1 = GetQuicReloadableFlag(quic_close_on_idle_timeout); // True if spin bit is enabled for this connection. - bool spin_bit_enabled_ : 1 = ShouldEnableSpinBit(); + bool spin_bit_enabled_ : 1 = false; bool fix_mtu_discovery_ : 1 = GetQuicReloadableFlag(quic_fix_mtu_discovery); };
diff --git a/quiche/quic/core/quic_connection_test.cc b/quiche/quic/core/quic_connection_test.cc index f0b0b3c..2639ded 100644 --- a/quiche/quic/core/quic_connection_test.cc +++ b/quiche/quic/core/quic_connection_test.cc
@@ -18890,6 +18890,7 @@ SetQuicReloadableFlag(quic_enable_spin_bit, false); + EXPECT_CALL(random_generator_, RandBytes(_, _)).Times(0); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); EXPECT_CALL(*send_algorithm_, EnableECT1()).WillRepeatedly(Return(false)); EXPECT_CALL(*send_algorithm_, EnableECT0()).WillRepeatedly(Return(false)); @@ -18905,8 +18906,35 @@ TEST_P(QuicConnectionTest, EnabledSpinBit) { SetQuicReloadableFlag(quic_enable_spin_bit, true); - ON_CALL(random_generator_, RandBytes(_, 1)) - .WillByDefault([](void* data, size_t len) { + + EXPECT_CALL(random_generator_, RandBytes(_, _)).Times(0); + EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); + EXPECT_CALL(*send_algorithm_, EnableECT1()).WillRepeatedly(Return(false)); + EXPECT_CALL(*send_algorithm_, EnableECT0()).WillRepeatedly(Return(false)); + + QuicConfig config; + connection_.SetFromConfig(config); + EXPECT_FALSE(QuicConnectionPeer::GetSpinBitEnabled(&connection_)); +} + +TEST_P(QuicConnectionTest, ConfigCannotEnableSpinBitIfFlagIsFalse) { + SetQuicReloadableFlag(quic_enable_spin_bit, false); + + EXPECT_CALL(random_generator_, RandBytes(_, _)).Times(0); + EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); + EXPECT_CALL(*send_algorithm_, EnableECT1()).WillRepeatedly(Return(false)); + EXPECT_CALL(*send_algorithm_, EnableECT0()).WillRepeatedly(Return(false)); + + QuicConfig config; + config.set_enable_spin_bit(true); + connection_.SetFromConfig(config); + EXPECT_FALSE(QuicConnectionPeer::GetSpinBitEnabled(&connection_)); +} + +TEST_P(QuicConnectionTest, ConfigEnablesSpinBitIfFlagIsTrueAndCoinFlipSuccess) { + SetQuicReloadableFlag(quic_enable_spin_bit, true); + EXPECT_CALL(random_generator_, RandBytes(_, 1)) + .WillOnce([](void* data, size_t len) { ASSERT_EQ(1u, len); *static_cast<uint8_t*>(data) = 0x00; }); @@ -18916,6 +18944,34 @@ EXPECT_CALL(*send_algorithm_, EnableECT0()).WillRepeatedly(Return(false)); QuicConfig config; + config.set_enable_spin_bit(true); + connection_.SetFromConfig(config); + EXPECT_TRUE(QuicConnectionPeer::GetSpinBitEnabled(&connection_)); +} + +TEST_P(QuicConnectionTest, ConfigDisablesSpinBit) { + SetQuicReloadableFlag(quic_enable_spin_bit, true); + + EXPECT_CALL(random_generator_, RandBytes(_, _)).Times(0); + EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); + EXPECT_CALL(*send_algorithm_, EnableECT1()).WillRepeatedly(Return(false)); + EXPECT_CALL(*send_algorithm_, EnableECT0()).WillRepeatedly(Return(false)); + + QuicConfig config; + config.set_enable_spin_bit(false); + connection_.SetFromConfig(config); + EXPECT_FALSE(QuicConnectionPeer::GetSpinBitEnabled(&connection_)); +} + +TEST_P(QuicConnectionTest, ConfigWithoutSpinBitDisablesSpinBit) { + SetQuicReloadableFlag(quic_enable_spin_bit, true); + + EXPECT_CALL(random_generator_, RandBytes(_, _)).Times(0); + EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); + EXPECT_CALL(*send_algorithm_, EnableECT1()).WillRepeatedly(Return(false)); + EXPECT_CALL(*send_algorithm_, EnableECT0()).WillRepeatedly(Return(false)); + + QuicConfig config; connection_.SetFromConfig(config); EXPECT_FALSE(QuicConnectionPeer::GetSpinBitEnabled(&connection_)); }