gfe-relnote: only respect TLPR when there is pending non-crypto stream data. Flag protected by quic_ignore_tlpr_if_no_pending_stream_data and session_decides_what_to_write.
When calculating the tail loss probe delay and TLPR option is enabled, only use half tail loss probe when session has pending stream data. Otherwise, ignore TLPR.
PiperOrigin-RevId: 253286073
Change-Id: I9321c9d0608f68bb4ec0f7f4fbba1e470e4a0a3c
diff --git a/quic/test_tools/quic_test_utils.h b/quic/test_tools/quic_test_utils.h
index cb51a3b..82bdd20 100644
--- a/quic/test_tools/quic_test_utils.h
+++ b/quic/test_tools/quic_test_utils.h
@@ -1061,6 +1061,7 @@
void(const QuicFrames&, TransmissionType type));
MOCK_CONST_METHOD1(IsFrameOutstanding, bool(const QuicFrame&));
MOCK_CONST_METHOD0(HasUnackedCryptoData, bool());
+ MOCK_CONST_METHOD0(HasUnackedStreamData, bool());
};
// Creates a client session for testing.
diff --git a/quic/test_tools/simple_session_notifier.cc b/quic/test_tools/simple_session_notifier.cc
index c6e3801..624e4f7 100644
--- a/quic/test_tools/simple_session_notifier.cc
+++ b/quic/test_tools/simple_session_notifier.cc
@@ -434,6 +434,14 @@
return !bytes_to_ack.Empty();
}
+bool SimpleSessionNotifier::HasUnackedStreamData() const {
+ for (auto it : stream_map_) {
+ if (StreamIsWaitingForAcks(it.first))
+ return true;
+ }
+ return false;
+}
+
bool SimpleSessionNotifier::OnControlFrameAcked(const QuicFrame& frame) {
QuicControlFrameId id = GetControlFrameId(frame);
if (id == kInvalidControlFrameId) {
diff --git a/quic/test_tools/simple_session_notifier.h b/quic/test_tools/simple_session_notifier.h
index 25c9941..aab3769 100644
--- a/quic/test_tools/simple_session_notifier.h
+++ b/quic/test_tools/simple_session_notifier.h
@@ -73,6 +73,7 @@
TransmissionType type) override;
bool IsFrameOutstanding(const QuicFrame& frame) const override;
bool HasUnackedCryptoData() const override;
+ bool HasUnackedStreamData() const override;
private:
struct StreamState {
diff --git a/quic/test_tools/simple_session_notifier_test.cc b/quic/test_tools/simple_session_notifier_test.cc
index d9958c8..8b931fe 100644
--- a/quic/test_tools/simple_session_notifier_test.cc
+++ b/quic/test_tools/simple_session_notifier_test.cc
@@ -88,6 +88,8 @@
EXPECT_CALL(connection_, SendStreamData(5, 1024, 0, FIN))
.WillOnce(Return(QuicConsumedData(1024, true)));
notifier_.WriteOrBufferData(5, 1024, FIN);
+ EXPECT_TRUE(notifier_.StreamIsWaitingForAcks(5));
+ EXPECT_TRUE(notifier_.HasUnackedStreamData());
// Reset stream 5 with no error.
EXPECT_CALL(connection_, SendControlFrame(_))
@@ -96,10 +98,12 @@
notifier_.WriteOrBufferRstStream(5, QUIC_STREAM_NO_ERROR, 1024);
// Verify stream 5 is waiting for acks.
EXPECT_TRUE(notifier_.StreamIsWaitingForAcks(5));
+ EXPECT_TRUE(notifier_.HasUnackedStreamData());
// Reset stream 5 with error.
notifier_.WriteOrBufferRstStream(5, QUIC_ERROR_PROCESSING_STREAM, 1024);
EXPECT_FALSE(notifier_.StreamIsWaitingForAcks(5));
+ EXPECT_FALSE(notifier_.HasUnackedStreamData());
}
TEST_F(SimpleSessionNotifierTest, WriteOrBufferPing) {
@@ -158,10 +162,13 @@
QuicTime::Zero());
EXPECT_TRUE(notifier_.StreamIsWaitingForAcks(
QuicUtils::GetCryptoStreamId(connection_.transport_version())));
+ EXPECT_TRUE(notifier_.HasUnackedStreamData());
+
// Neuters unencrypted data.
notifier_.NeuterUnencryptedData();
EXPECT_FALSE(notifier_.StreamIsWaitingForAcks(
QuicUtils::GetCryptoStreamId(connection_.transport_version())));
+ EXPECT_FALSE(notifier_.HasUnackedStreamData());
}
TEST_F(SimpleSessionNotifierTest, OnCanWrite) {
@@ -178,6 +185,7 @@
notifier_.WriteOrBufferData(
QuicUtils::GetCryptoStreamId(connection_.transport_version()), 1024,
NO_FIN);
+
// Send crypto data [1024, 2048) in ENCRYPTION_ZERO_RTT.
connection_.SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
EXPECT_CALL(connection_, SendStreamData(QuicUtils::GetCryptoStreamId(
diff --git a/quic/test_tools/simulator/quic_endpoint.cc b/quic/test_tools/simulator/quic_endpoint.cc
index ba9d206..872a9b2 100644
--- a/quic/test_tools/simulator/quic_endpoint.cc
+++ b/quic/test_tools/simulator/quic_endpoint.cc
@@ -293,6 +293,13 @@
return false;
}
+bool QuicEndpoint::HasUnackedStreamData() const {
+ if (notifier_ != nullptr) {
+ return notifier_->HasUnackedStreamData();
+ }
+ return false;
+}
+
QuicEndpoint::Writer::Writer(QuicEndpoint* endpoint)
: endpoint_(endpoint), is_blocked_(false) {}
diff --git a/quic/test_tools/simulator/quic_endpoint.h b/quic/test_tools/simulator/quic_endpoint.h
index 53bff3a..c547551 100644
--- a/quic/test_tools/simulator/quic_endpoint.h
+++ b/quic/test_tools/simulator/quic_endpoint.h
@@ -130,6 +130,7 @@
TransmissionType type) override;
bool IsFrameOutstanding(const QuicFrame& frame) const override;
bool HasUnackedCryptoData() const override;
+ bool HasUnackedStreamData() const override;
// End SessionNotifierInterface implementation.
private: