Move the increments of retransmittable-on-wire counters to when the alarm fires in retransmittable-on-wire mode.

Protected by FLAGS_quic_reloadable_flag_quic_use_ping_manager2.

PiperOrigin-RevId: 447876160
diff --git a/quiche/quic/core/quic_connection.cc b/quiche/quic/core/quic_connection.cc
index 3913635..1e458c6 100644
--- a/quiche/quic/core/quic_connection.cc
+++ b/quiche/quic/core/quic_connection.cc
@@ -128,7 +128,7 @@
 
   void OnAlarm() override {
     QUICHE_DCHECK(connection_->connected());
-    QUICHE_DCHECK(!GetQuicReloadableFlag(quic_use_ping_manager));
+    QUICHE_DCHECK(!GetQuicReloadableFlag(quic_use_ping_manager2));
     connection_->OnPingTimeout();
   }
 };
@@ -4702,7 +4702,7 @@
     return;
   }
   if (use_ping_manager_) {
-    QUIC_RELOADABLE_FLAG_COUNT(quic_use_ping_manager);
+    QUIC_RELOADABLE_FLAG_COUNT(quic_use_ping_manager2);
     ping_manager_.SetAlarm(clock_->ApproximateNow(),
                            visitor_->ShouldKeepConnectionAlive(),
                            sent_packet_manager_.HasInFlightPackets());
diff --git a/quiche/quic/core/quic_connection.h b/quiche/quic/core/quic_connection.h
index b214361..09cef3d 100644
--- a/quiche/quic/core/quic_connection.h
+++ b/quiche/quic/core/quic_connection.h
@@ -1995,7 +1995,7 @@
   bool defer_send_in_response_to_packets_;
 
   // TODO(fayang): remove PING related fields below when deprecating
-  // quic_use_ping_manager.
+  // quic_use_ping_manager2.
   // The timeout for keep-alive PING.
   QuicTime::Delta keep_alive_ping_timeout_;
 
@@ -2019,7 +2019,7 @@
   // An alarm that is scheduled when the SentPacketManager requires a delay
   // before sending packets and fires when the packet may be sent.
   QuicArenaScopedPtr<QuicAlarm> send_alarm_;
-  // TODO(fayang): remove ping_alarm_ when deprecating quic_use_ping_manager.
+  // TODO(fayang): remove ping_alarm_ when deprecating quic_use_ping_manager2.
   // An alarm that fires when a ping should be sent.
   QuicArenaScopedPtr<QuicAlarm> ping_alarm_;
   // An alarm that fires when an MTU probe should be sent.
@@ -2256,7 +2256,7 @@
   // If true, send connection close packet on INVALID_VERSION.
   bool send_connection_close_for_invalid_version_ = false;
 
-  const bool use_ping_manager_ = GetQuicReloadableFlag(quic_use_ping_manager);
+  const bool use_ping_manager_ = GetQuicReloadableFlag(quic_use_ping_manager2);
 
   QuicPingManager ping_manager_;
 
diff --git a/quiche/quic/core/quic_connection_test.cc b/quiche/quic/core/quic_connection_test.cc
index 0da0673..692e3ef 100644
--- a/quiche/quic/core/quic_connection_test.cc
+++ b/quiche/quic/core/quic_connection_test.cc
@@ -7185,7 +7185,7 @@
 }
 
 TEST_P(QuicConnectionTest, RetransmittableOnWireSendFirstPacket) {
-  if (!GetQuicReloadableFlag(quic_use_ping_manager) ||
+  if (!GetQuicReloadableFlag(quic_use_ping_manager2) ||
       !VersionHasIetfQuicFrames(connection_.version().transport_version)) {
     return;
   }
@@ -7231,7 +7231,7 @@
 }
 
 TEST_P(QuicConnectionTest, RetransmittableOnWireSendRandomBytes) {
-  if (!GetQuicReloadableFlag(quic_use_ping_manager) ||
+  if (!GetQuicReloadableFlag(quic_use_ping_manager2) ||
       !VersionHasIetfQuicFrames(connection_.version().transport_version)) {
     return;
   }
@@ -7280,7 +7280,7 @@
 
 TEST_P(QuicConnectionTest,
        RetransmittableOnWireSendRandomBytesWithWriterBlocked) {
-  if (!GetQuicReloadableFlag(quic_use_ping_manager) ||
+  if (!GetQuicReloadableFlag(quic_use_ping_manager2) ||
       !VersionHasIetfQuicFrames(connection_.version().transport_version)) {
     return;
   }
@@ -8250,6 +8250,8 @@
                                          peer_creator_.packet_number() + 1);
   EXPECT_EQ(initial_retransmittable_on_wire_timeout,
             connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+  clock_.AdvanceTime(initial_retransmittable_on_wire_timeout);
+  connection_.GetPingAlarm()->Fire();
 
   // Verify the count of consecutive aggressive pings is reset.
   for (int i = 0; i < max_aggressive_retransmittable_on_wire_ping_count; i++) {
diff --git a/quiche/quic/core/quic_flags_list.h b/quiche/quic/core/quic_flags_list.h
index 75c3687..73b41a3 100644
--- a/quiche/quic/core/quic_flags_list.h
+++ b/quiche/quic/core/quic_flags_list.h
@@ -86,7 +86,7 @@
 // If true, use BBRv2 as the default congestion controller. Takes precedence over --quic_default_to_bbr.
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_to_bbr_v2, false)
 // If true, use PING manager to manage the PING alarm.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_use_ping_manager, true)
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_use_ping_manager2, true)
 // If true, use new connection ID in connection migration.
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_connection_migration_use_new_cid_v2, true)
 // If true, uses conservative cwnd gain and pacing gain when cwnd gets bootstrapped.
diff --git a/quiche/quic/core/quic_ping_manager.cc b/quiche/quic/core/quic_ping_manager.cc
index e3947e5..e2ef9c2 100644
--- a/quiche/quic/core/quic_ping_manager.cc
+++ b/quiche/quic/core/quic_ping_manager.cc
@@ -8,6 +8,11 @@
 
 namespace {
 
+// Maximum shift used to calculate retransmittable on wire timeout. For 200ms
+// initial retransmittable on wire delay, this would get a maximum of 200ms * (1
+// << 10) = 204.8s
+const int kMaxRetransmittableOnWireDelayShift = 10;
+
 class AlarmDelegate : public QuicAlarm::DelegateWithContext {
  public:
   explicit AlarmDelegate(QuicPingManager* manager,
@@ -47,11 +52,6 @@
     return;
   }
   alarm_->Update(earliest_deadline, kAlarmGranularity);
-  if (GetQuicFlag(
-          FLAGS_quic_max_aggressive_retransmittable_on_wire_ping_count) != 0) {
-    ++consecutive_retransmittable_on_wire_count_;
-  }
-  ++retransmittable_on_wire_count_;
 }
 
 void QuicPingManager::OnAlarm() {
@@ -65,6 +65,12 @@
   // to SetAlarm later.
   if (earliest_deadline == retransmittable_on_wire_deadline_) {
     retransmittable_on_wire_deadline_ = QuicTime::Zero();
+    if (GetQuicFlag(
+            FLAGS_quic_max_aggressive_retransmittable_on_wire_ping_count) !=
+        0) {
+      ++consecutive_retransmittable_on_wire_count_;
+    }
+    ++retransmittable_on_wire_count_;
     delegate_->OnRetransmittableOnWireTimeout();
     return;
   }
@@ -125,8 +131,9 @@
       max_aggressive_retransmittable_on_wire_count) {
     // Exponentially back off the timeout if the number of consecutive
     // retransmittable on wire pings has exceeds the allowance.
-    int shift = consecutive_retransmittable_on_wire_count_ -
-                max_aggressive_retransmittable_on_wire_count;
+    int shift = std::min(consecutive_retransmittable_on_wire_count_ -
+                             max_aggressive_retransmittable_on_wire_count,
+                         kMaxRetransmittableOnWireDelayShift);
     retransmittable_on_wire_timeout =
         initial_retransmittable_on_wire_timeout_ * (1 << shift);
   }
diff --git a/quiche/quic/core/quic_ping_manager_test.cc b/quiche/quic/core/quic_ping_manager_test.cc
index e7b4b78..509022b 100644
--- a/quiche/quic/core/quic_ping_manager_test.cc
+++ b/quiche/quic/core/quic_ping_manager_test.cc
@@ -16,6 +16,11 @@
   static QuicAlarm* GetAlarm(QuicPingManager* manager) {
     return manager->alarm_.get();
   }
+
+  static void SetPerspective(QuicPingManager* manager,
+                             Perspective perspective) {
+    manager->perspective_ = perspective;
+  }
 };
 
 namespace {
@@ -292,6 +297,9 @@
                     !kHasInflightPackets);
   EXPECT_EQ(initial_retransmittable_on_wire_timeout,
             alarm_->deadline() - clock_.ApproximateNow());
+  EXPECT_CALL(delegate_, OnRetransmittableOnWireTimeout());
+  clock_.AdvanceTime(initial_retransmittable_on_wire_timeout);
+  alarm_->Fire();
 
   for (int i = 0; i < kMaxAggressiveRetransmittableOnWireCount; i++) {
     manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive,
@@ -375,6 +383,46 @@
   EXPECT_FALSE(alarm_->IsSet());
 }
 
+TEST_F(QuicPingManagerTest, MaxRetransmittableOnWireDelayShift) {
+  QuicPingManagerPeer::SetPerspective(&manager_, Perspective::IS_SERVER);
+  const int kMaxAggressiveRetransmittableOnWireCount = 3;
+  SetQuicFlag(FLAGS_quic_max_aggressive_retransmittable_on_wire_ping_count,
+              kMaxAggressiveRetransmittableOnWireCount);
+  const QuicTime::Delta initial_retransmittable_on_wire_timeout =
+      QuicTime::Delta::FromMilliseconds(200);
+  manager_.set_initial_retransmittable_on_wire_timeout(
+      initial_retransmittable_on_wire_timeout);
+
+  for (int i = 0; i <= kMaxAggressiveRetransmittableOnWireCount; i++) {
+    manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive,
+                      !kHasInflightPackets);
+    EXPECT_TRUE(alarm_->IsSet());
+    EXPECT_EQ(initial_retransmittable_on_wire_timeout,
+              alarm_->deadline() - clock_.ApproximateNow());
+    clock_.AdvanceTime(initial_retransmittable_on_wire_timeout);
+    EXPECT_CALL(delegate_, OnRetransmittableOnWireTimeout());
+    alarm_->Fire();
+    manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive,
+                      kHasInflightPackets);
+  }
+  for (int i = 1; i <= 20; ++i) {
+    manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive,
+                      !kHasInflightPackets);
+    EXPECT_TRUE(alarm_->IsSet());
+    if (i <= 10) {
+      EXPECT_EQ(initial_retransmittable_on_wire_timeout * (1 << i),
+                alarm_->deadline() - clock_.ApproximateNow());
+    } else {
+      // Verify shift is capped.
+      EXPECT_EQ(initial_retransmittable_on_wire_timeout * (1 << 10),
+                alarm_->deadline() - clock_.ApproximateNow());
+    }
+    clock_.AdvanceTime(alarm_->deadline() - clock_.ApproximateNow());
+    EXPECT_CALL(delegate_, OnRetransmittableOnWireTimeout());
+    alarm_->Fire();
+  }
+}
+
 }  // namespace
 
 }  // namespace test