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_sent_packet_manager_test.cc b/quic/core/quic_sent_packet_manager_test.cc
index a0746fe..1e8302f 100644
--- a/quic/core/quic_sent_packet_manager_test.cc
+++ b/quic/core/quic_sent_packet_manager_test.cc
@@ -267,6 +267,14 @@
     return packet;
   }
 
+  SerializedPacket CreatePingPacket(uint64_t packet_number) {
+    SerializedPacket packet(QuicPacketNumber(packet_number),
+                            PACKET_4BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
+                            false, false);
+    packet.retransmittable_frames.push_back(QuicFrame(QuicPingFrame()));
+    return packet;
+  }
+
   void SendDataPacket(uint64_t packet_number) {
     SendDataPacket(packet_number, ENCRYPTION_INITIAL);
   }
@@ -282,6 +290,17 @@
                           NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
   }
 
+  void SendPingPacket(uint64_t packet_number,
+                      EncryptionLevel encryption_level) {
+    EXPECT_CALL(*send_algorithm_,
+                OnPacketSent(_, BytesInFlight(),
+                             QuicPacketNumber(packet_number), _, _));
+    SerializedPacket packet(CreatePingPacket(packet_number));
+    packet.encryption_level = encryption_level;
+    manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(),
+                          NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+  }
+
   void SendCryptoPacket(uint64_t packet_number) {
     EXPECT_CALL(
         *send_algorithm_,
@@ -1761,6 +1780,118 @@
   EXPECT_EQ(expected_time, manager_.GetRetransmissionTime());
 }
 
+TEST_P(QuicSentPacketManagerTest, TLPRWithPendingStreamData) {
+  if (!manager_.session_decides_what_to_write()) {
+    return;
+  }
+
+  QuicConfig config;
+  QuicTagVector options;
+
+  options.push_back(kTLPR);
+  QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+  EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+  EXPECT_CALL(*send_algorithm_, PacingRate(_))
+      .WillRepeatedly(Return(QuicBandwidth::Zero()));
+  EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
+      .WillOnce(Return(10 * kDefaultTCPMSS));
+  manager_.SetFromConfig(config);
+  EXPECT_TRUE(
+      QuicSentPacketManagerPeer::GetEnableHalfRttTailLossProbe(&manager_));
+
+  QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2);
+
+  SendDataPacket(1);
+  SendDataPacket(2);
+
+  // Test with a standard smoothed RTT.
+  RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
+  rtt_stats->set_initial_rtt(QuicTime::Delta::FromMilliseconds(100));
+  QuicTime::Delta srtt = rtt_stats->initial_rtt();
+  // With pending stream data, TLPR is used.
+  QuicTime::Delta expected_tlp_delay = 0.5 * srtt;
+  EXPECT_CALL(notifier_, HasUnackedStreamData()).WillRepeatedly(Return(true));
+
+  EXPECT_EQ(expected_tlp_delay,
+            manager_.GetRetransmissionTime() - clock_.Now());
+
+  // Retransmit the packet by invoking the retransmission timeout.
+  clock_.AdvanceTime(expected_tlp_delay);
+  manager_.OnRetransmissionTimeout();
+  EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
+  EXPECT_FALSE(manager_.HasPendingRetransmissions());
+  EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+      .WillOnce(WithArgs<1>(Invoke(
+          [this](TransmissionType type) { RetransmitDataPacket(3, type); })));
+  EXPECT_TRUE(manager_.MaybeRetransmitTailLossProbe());
+
+  EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false));
+  EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now()));
+  EXPECT_FALSE(manager_.HasPendingRetransmissions());
+
+  // 2nd TLP.
+  expected_tlp_delay = 2 * srtt;
+  EXPECT_EQ(expected_tlp_delay,
+            manager_.GetRetransmissionTime() - clock_.Now());
+}
+
+TEST_P(QuicSentPacketManagerTest, TLPRWithoutPendingStreamData) {
+  if (!manager_.session_decides_what_to_write()) {
+    return;
+  }
+
+  QuicConfig config;
+  QuicTagVector options;
+
+  options.push_back(kTLPR);
+  QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+  EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+  EXPECT_CALL(*send_algorithm_, PacingRate(_))
+      .WillRepeatedly(Return(QuicBandwidth::Zero()));
+  EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
+      .WillOnce(Return(10 * kDefaultTCPMSS));
+  manager_.SetFromConfig(config);
+  EXPECT_TRUE(
+      QuicSentPacketManagerPeer::GetEnableHalfRttTailLossProbe(&manager_));
+  QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2);
+
+  SendPingPacket(1, ENCRYPTION_INITIAL);
+  SendPingPacket(2, ENCRYPTION_INITIAL);
+
+  // Test with a standard smoothed RTT.
+  RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
+  rtt_stats->set_initial_rtt(QuicTime::Delta::FromMilliseconds(100));
+  QuicTime::Delta srtt = rtt_stats->initial_rtt();
+  QuicTime::Delta expected_tlp_delay = 0.5 * srtt;
+  if (GetQuicReloadableFlag(quic_ignore_tlpr_if_no_pending_stream_data)) {
+    // With no pending stream data, TLPR is ignored.
+    expected_tlp_delay = 2 * srtt;
+  }
+  EXPECT_CALL(notifier_, HasUnackedStreamData()).WillRepeatedly(Return(false));
+  EXPECT_EQ(expected_tlp_delay,
+            manager_.GetRetransmissionTime() - clock_.Now());
+
+  // Retransmit the packet by invoking the retransmission timeout.
+  clock_.AdvanceTime(expected_tlp_delay);
+  manager_.OnRetransmissionTimeout();
+  EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
+  EXPECT_FALSE(manager_.HasPendingRetransmissions());
+  EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+      .WillOnce(WithArgs<1>(Invoke(
+          [this](TransmissionType type) { RetransmitDataPacket(3, type); })));
+  EXPECT_TRUE(manager_.MaybeRetransmitTailLossProbe());
+  EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false));
+  EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now()));
+  EXPECT_FALSE(manager_.HasPendingRetransmissions());
+
+  // 2nd TLP.
+  expected_tlp_delay = 2 * srtt;
+  EXPECT_EQ(expected_tlp_delay,
+            manager_.GetRetransmissionTime() - clock_.Now());
+}
+
 TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeSpuriousRTO) {
   RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
   rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100),