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/core/quic_stream_test.cc b/quic/core/quic_stream_test.cc
index f13d867..d11a7a4 100644
--- a/quic/core/quic_stream_test.cc
+++ b/quic/core/quic_stream_test.cc
@@ -314,6 +314,9 @@
NO_FIN);
}));
stream_->WriteOrBufferData(QuicStringPiece(kData1, 2), false, nullptr);
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams());
EXPECT_EQ(1u, stream_->BufferedDataBytes());
}
@@ -331,6 +334,9 @@
NO_FIN);
}));
stream_->WriteOrBufferData(QuicStringPiece(kData1, 2), true, nullptr);
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams());
}
@@ -376,6 +382,10 @@
kDataLen - 1, 0u, NO_FIN);
}));
stream_->WriteOrBufferData(kData1, false, nullptr);
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
+
EXPECT_EQ(1u, stream_->BufferedDataBytes());
EXPECT_TRUE(HasWriteBlockedStreams());
@@ -390,6 +400,9 @@
kDataLen - 1, kDataLen - 1, NO_FIN);
}));
stream_->OnCanWrite();
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
// And finally the end of the bytes_consumed.
EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
@@ -398,6 +411,9 @@
2 * kDataLen - 2, NO_FIN);
}));
stream_->OnCanWrite();
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
}
TEST_P(QuicStreamTest, WriteOrBufferDataReachStreamLimit) {
@@ -408,6 +424,9 @@
EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.WillOnce(Invoke(&(MockQuicSession::ConsumeData)));
stream_->WriteOrBufferData(data, false, nullptr);
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
EXPECT_CALL(*connection_, CloseConnection(QUIC_STREAM_LENGTH_OVERFLOW, _, _));
EXPECT_QUIC_BUG(stream_->WriteOrBufferData("a", false, nullptr),
"Write too many data via stream");
@@ -442,12 +461,18 @@
NO_FIN);
}));
stream_->WriteOrBufferData(QuicStringPiece(kData1, 1), false, nullptr);
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
EXPECT_FALSE(fin_sent());
EXPECT_FALSE(rst_sent());
// Now close the stream, and expect that we send a RST.
EXPECT_CALL(*session_, SendRstStream(_, _, _));
stream_->OnClose();
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_FALSE(session_->HasUnackedStreamData());
+ }
EXPECT_FALSE(fin_sent());
EXPECT_TRUE(rst_sent());
}
@@ -818,9 +843,15 @@
// Stream is not waiting for acks initially.
EXPECT_FALSE(stream_->IsWaitingForAcks());
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_FALSE(session_->HasUnackedStreamData());
+ }
// Send kData1.
stream_->WriteOrBufferData(kData1, false, nullptr);
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_TRUE(stream_->IsWaitingForAcks());
QuicByteCount newly_acked_length = 0;
@@ -829,11 +860,17 @@
EXPECT_EQ(9u, newly_acked_length);
// Stream is not waiting for acks as all sent data is acked.
EXPECT_FALSE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_FALSE(session_->HasUnackedStreamData());
+ }
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
// Send kData2.
stream_->WriteOrBufferData(kData2, false, nullptr);
EXPECT_TRUE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
// Send FIN.
stream_->WriteOrBufferData("", true, nullptr);
@@ -849,6 +886,9 @@
EXPECT_EQ(9u, newly_acked_length);
// Stream is waiting for acks as FIN is not acked.
EXPECT_TRUE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
// FIN is acked.
@@ -856,6 +896,9 @@
&newly_acked_length));
EXPECT_EQ(0u, newly_acked_length);
EXPECT_FALSE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_FALSE(session_->HasUnackedStreamData());
+ }
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
}
@@ -870,26 +913,43 @@
stream_->WriteOrBufferData("", true, nullptr);
EXPECT_EQ(3u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_TRUE(stream_->IsWaitingForAcks());
-
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
QuicByteCount newly_acked_length = 0;
EXPECT_TRUE(stream_->OnStreamFrameAcked(9, 9, false, QuicTime::Delta::Zero(),
&newly_acked_length));
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
EXPECT_EQ(9u, newly_acked_length);
EXPECT_EQ(3u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_TRUE(stream_->OnStreamFrameAcked(18, 9, false, QuicTime::Delta::Zero(),
&newly_acked_length));
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
EXPECT_EQ(9u, newly_acked_length);
EXPECT_EQ(3u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_TRUE(stream_->OnStreamFrameAcked(0, 9, false, QuicTime::Delta::Zero(),
&newly_acked_length));
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
EXPECT_EQ(9u, newly_acked_length);
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
// FIN is not acked yet.
EXPECT_TRUE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
EXPECT_TRUE(stream_->OnStreamFrameAcked(27, 0, true, QuicTime::Delta::Zero(),
&newly_acked_length));
EXPECT_EQ(0u, newly_acked_length);
EXPECT_FALSE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_FALSE(session_->HasUnackedStreamData());
+ }
}
TEST_P(QuicStreamTest, CancelStream) {
@@ -897,22 +957,43 @@
EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
EXPECT_FALSE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_FALSE(session_->HasUnackedStreamData());
+ }
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
stream_->WriteOrBufferData(kData1, false, nullptr);
EXPECT_TRUE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
// Cancel stream.
stream_->Reset(QUIC_STREAM_NO_ERROR);
// stream still waits for acks as the error code is QUIC_STREAM_NO_ERROR, and
// data is going to be retransmitted.
EXPECT_TRUE(stream_->IsWaitingForAcks());
- EXPECT_CALL(*session_,
- SendRstStream(stream_->id(), QUIC_STREAM_CANCELLED, 9));
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
+ EXPECT_CALL(*connection_,
+ OnStreamReset(stream_->id(), QUIC_STREAM_CANCELLED));
+ EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
+ EXPECT_CALL(*session_, SendRstStream(stream_->id(), QUIC_STREAM_CANCELLED, 9))
+ .WillOnce(InvokeWithoutArgs([this]() {
+ return QuicSessionPeer::SendRstStreamInner(
+ session_.get(), stream_->id(), QUIC_STREAM_CANCELLED,
+ stream_->stream_bytes_written(),
+ /*close_write_side_only=*/false);
+ }));
+
stream_->Reset(QUIC_STREAM_CANCELLED);
EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
// Stream stops waiting for acks as data is not going to be retransmitted.
EXPECT_FALSE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_FALSE(session_->HasUnackedStreamData());
+ }
}
TEST_P(QuicStreamTest, RstFrameReceivedStreamNotFinishSending) {
@@ -920,10 +1001,16 @@
EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
EXPECT_FALSE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_FALSE(session_->HasUnackedStreamData());
+ }
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
stream_->WriteOrBufferData(kData1, false, nullptr);
EXPECT_TRUE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
// RST_STREAM received.
@@ -936,6 +1023,9 @@
// Stream stops waiting for acks as it does not finish sending and rst is
// sent.
EXPECT_FALSE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_FALSE(session_->HasUnackedStreamData());
+ }
}
TEST_P(QuicStreamTest, RstFrameReceivedStreamFinishSending) {
@@ -943,10 +1033,16 @@
EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
EXPECT_FALSE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_FALSE(session_->HasUnackedStreamData());
+ }
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
stream_->WriteOrBufferData(kData1, true, nullptr);
EXPECT_TRUE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
// RST_STREAM received.
EXPECT_CALL(*session_, SendRstStream(_, _, _)).Times(0);
@@ -955,6 +1051,9 @@
stream_->OnStreamReset(rst_frame);
// Stream still waits for acks as it finishes sending and has unacked data.
EXPECT_TRUE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
}
@@ -963,11 +1062,16 @@
EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
EXPECT_FALSE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_FALSE(session_->HasUnackedStreamData());
+ }
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
stream_->WriteOrBufferData(kData1, false, nullptr);
EXPECT_TRUE(stream_->IsWaitingForAcks());
-
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
EXPECT_CALL(*session_,
SendRstStream(stream_->id(), QUIC_RST_ACKNOWLEDGEMENT, 9));
stream_->OnConnectionClosed(QUIC_INTERNAL_ERROR,
@@ -975,6 +1079,9 @@
EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
// Stream stops waiting for acks as connection is going to close.
EXPECT_FALSE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_FALSE(session_->HasUnackedStreamData());
+ }
}
TEST_P(QuicStreamTest, CanWriteNewDataAfterData) {
@@ -1003,6 +1110,8 @@
stream_->WriteOrBufferData(data, false, nullptr);
stream_->WriteOrBufferData(data, false, nullptr);
stream_->WriteOrBufferData(data, false, nullptr);
+ EXPECT_TRUE(stream_->IsWaitingForAcks());
+
// Verify all data is saved.
EXPECT_EQ(3 * data.length() - 100, stream_->BufferedDataBytes());
@@ -1215,12 +1324,20 @@
Initialize();
EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_FALSE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_FALSE(session_->HasUnackedStreamData());
+ }
+
// Send [0, 27) and fin.
stream_->WriteOrBufferData(kData1, false, nullptr);
stream_->WriteOrBufferData(kData1, false, nullptr);
stream_->WriteOrBufferData(kData1, true, nullptr);
EXPECT_EQ(3u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_TRUE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
// Ack [0, 9), [5, 22) and [18, 26)
// Verify [0, 9) 9 bytes are acked.
@@ -1240,6 +1357,9 @@
EXPECT_EQ(4u, newly_acked_length);
EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_TRUE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
// Ack [0, 27). Verify [26, 27) 1 byte is acked.
EXPECT_TRUE(stream_->OnStreamFrameAcked(26, 1, false, QuicTime::Delta::Zero(),
@@ -1247,6 +1367,9 @@
EXPECT_EQ(1u, newly_acked_length);
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_TRUE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_TRUE(session_->HasUnackedStreamData());
+ }
// Ack Fin.
EXPECT_TRUE(stream_->OnStreamFrameAcked(27, 0, true, QuicTime::Delta::Zero(),
@@ -1254,6 +1377,9 @@
EXPECT_EQ(0u, newly_acked_length);
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_FALSE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_FALSE(session_->HasUnackedStreamData());
+ }
// Ack [10, 27) and fin. No new data is acked.
EXPECT_FALSE(stream_->OnStreamFrameAcked(
@@ -1261,6 +1387,9 @@
EXPECT_EQ(0u, newly_acked_length);
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_FALSE(stream_->IsWaitingForAcks());
+ if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+ EXPECT_FALSE(session_->HasUnackedStreamData());
+ }
}
TEST_P(QuicStreamTest, OnStreamFrameLost) {