diff --git a/api/envoy/config/core/v3/protocol.proto b/api/envoy/config/core/v3/protocol.proto index ca94d04e5f4a1..e3e1feef0f9e3 100644 --- a/api/envoy/config/core/v3/protocol.proto +++ b/api/envoy/config/core/v3/protocol.proto @@ -57,7 +57,7 @@ message QuicKeepAliveSettings { } // QUIC protocol options which apply to both downstream and upstream connections. -// [#next-free-field: 12] +// [#next-free-field: 13] message QuicProtocolOptions { // Config for QUIC connection migration across network interfaces, i.e. cellular to WIFI, upon // network change events from the platform, i.e. the current network gets @@ -173,6 +173,12 @@ message QuicProtocolOptions { // If absent, the feature will be disabled. // [#not-implemented-hide:] ConnectionMigrationSettings connection_migration = 11; + + // Timeout for a QUIC connection to schedule memory reduction callback when the network has been idle for a while. + // This value should be smaller than the idle timeout to take effect. + // If not specified, memory reduction is set to infinite by QUIC connection (disabled). + google.protobuf.Duration memory_reduction_timeout = 12 + [(validate.rules).duration = {gte {seconds: 1}}]; } message UpstreamHttpProtocolOptions { diff --git a/source/common/quic/envoy_quic_server_session.cc b/source/common/quic/envoy_quic_server_session.cc index 81c432769ced2..09f6b1630a5d8 100644 --- a/source/common/quic/envoy_quic_server_session.cc +++ b/source/common/quic/envoy_quic_server_session.cc @@ -214,6 +214,14 @@ void EnvoyQuicServerSession::setHttp3Options( } } } + if (http3_options.has_quic_protocol_options()) { + const uint64_t memory_reduction_timeout_ms = PROTOBUF_GET_MS_OR_DEFAULT( + http3_options.quic_protocol_options(), memory_reduction_timeout, 0); + if (memory_reduction_timeout_ms > 0) { + connection()->SetMemoryReductionTimeout( + quic::QuicTime::Delta::FromMilliseconds(memory_reduction_timeout_ms)); + } + } set_allow_extended_connect(http3_options_->allow_extended_connect()); if (http3_options_->disable_qpack()) { DisableHuffmanEncoding(); diff --git a/test/common/quic/envoy_quic_server_session_test.cc b/test/common/quic/envoy_quic_server_session_test.cc index 0046ceeb057f9..788a31ff9e48f 100644 --- a/test/common/quic/envoy_quic_server_session_test.cc +++ b/test/common/quic/envoy_quic_server_session_test.cc @@ -1346,6 +1346,32 @@ TEST_F(EnvoyQuicServerSessionTest, SessionIdleCallbacksIdempotency) { EXPECT_CALL(session_idle_list_, RemoveSession(_)); } +TEST_F(EnvoyQuicServerSessionTest, MemoryReductionTimeoutTest) { + envoy::config::core::v3::Http3ProtocolOptions http3_options; + auto* quic_options = http3_options.mutable_quic_protocol_options(); + quic_options->mutable_memory_reduction_timeout()->set_seconds(300); + + // Mark handshake complete and set connection idle timeout to a large duration. + quic::test::QuicConnectionPeer::GetIdleNetworkDetector(quic_connection_) + .SetTimeouts(quic::QuicTime::Delta::Infinite(), quic::QuicTime::Delta::FromSeconds(600)); + + envoy_quic_session_.setHttp3Options(http3_options); + + // Trigger SetAlarm. + quic::test::QuicConnectionPeer::GetIdleNetworkDetector(quic_connection_) + .OnPacketReceived(connection_helper_.GetClock()->Now()); + + // Check the alarm deadline. + quic::QuicAlarmProxy idle_detector_alarm = + quic::test::QuicConnectionPeer::GetIdleNetworkDetectorAlarm(quic_connection_); + + EXPECT_TRUE(idle_detector_alarm.IsSet()); + EXPECT_EQ(connection_helper_.GetClock()->Now() + quic::QuicTime::Delta::FromSeconds(300), + idle_detector_alarm.deadline()); + + installReadFilter(); +} + class EnvoyQuicServerSessionTestWillNotInitialize : public EnvoyQuicServerSessionTest { void SetUp() override {} void TearDown() override {