Delay the first Initial ACK sent by the server so it can be bundled with the server's first Initial packet.

Protected by FLAGS_quic_reloadable_flag_quic_delay_initial_ack.

PiperOrigin-RevId: 338518843
Change-Id: Ib8cb7375f212ac5f028bd2c7f6a191278ac01540
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index 7f7089b..5b9ab32 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -5113,7 +5113,8 @@
                 << " supports multiple packet number spaces";
   framer_.EnableMultiplePacketNumberSpacesSupport();
   sent_packet_manager_.EnableMultiplePacketNumberSpacesSupport();
-  uber_received_packet_manager_.EnableMultiplePacketNumberSpacesSupport();
+  uber_received_packet_manager_.EnableMultiplePacketNumberSpacesSupport(
+      perspective_);
 }
 
 bool QuicConnection::SupportsMultiplePacketNumberSpaces() const {
diff --git a/quic/core/quic_received_packet_manager.cc b/quic/core/quic_received_packet_manager.cc
index 0a91709..98f450c 100644
--- a/quic/core/quic_received_packet_manager.cc
+++ b/quic/core/quic_received_packet_manager.cc
@@ -264,8 +264,11 @@
     return;
   }
 
-  MaybeUpdateAckTimeoutTo(
-      now + GetMaxAckDelay(last_received_packet_number, *rtt_stats));
+  QuicTime updated_ack_time =
+      now + GetMaxAckDelay(last_received_packet_number, *rtt_stats);
+  if (!ack_timeout_.IsInitialized() || ack_timeout_ > updated_ack_time) {
+    ack_timeout_ = updated_ack_time;
+  }
 }
 
 void QuicReceivedPacketManager::ResetAckStates() {
@@ -275,12 +278,6 @@
   last_sent_largest_acked_ = LargestAcked(ack_frame_);
 }
 
-void QuicReceivedPacketManager::MaybeUpdateAckTimeoutTo(QuicTime time) {
-  if (!ack_timeout_.IsInitialized() || ack_timeout_ > time) {
-    ack_timeout_ = time;
-  }
-}
-
 bool QuicReceivedPacketManager::HasMissingPackets() const {
   if (ack_frame_.packets.Empty()) {
     return false;
diff --git a/quic/core/uber_received_packet_manager.cc b/quic/core/uber_received_packet_manager.cc
index 7b2b32f..025da64 100644
--- a/quic/core/uber_received_packet_manager.cc
+++ b/quic/core/uber_received_packet_manager.cc
@@ -98,9 +98,15 @@
   }
   received_packet_managers_[QuicUtils::GetPacketNumberSpace(encryption_level)]
       .ResetAckStates();
+  if (encryption_level == ENCRYPTION_INITIAL) {
+    // After one Initial ACK is sent, the others should be sent 'immediately'.
+    received_packet_managers_[INITIAL_DATA].set_local_max_ack_delay(
+        kAlarmGranularity);
+  }
 }
 
-void UberReceivedPacketManager::EnableMultiplePacketNumberSpacesSupport() {
+void UberReceivedPacketManager::EnableMultiplePacketNumberSpacesSupport(
+    Perspective perspective) {
   if (supports_multiple_packet_number_spaces_) {
     QUIC_BUG << "Multiple packet number spaces has already been enabled";
     return;
@@ -112,8 +118,15 @@
   }
   // In IETF QUIC, the peer is expected to acknowledge packets in Initial and
   // Handshake packets with minimal delay.
-  received_packet_managers_[INITIAL_DATA].set_local_max_ack_delay(
-      kAlarmGranularity);
+  if (!GetQuicReloadableFlag(quic_delay_initial_ack) ||
+      perspective == Perspective::IS_CLIENT) {
+    // Delay the first server ACK, because server ACKs are padded to
+    // full size and count towards the amplification limit.
+    received_packet_managers_[INITIAL_DATA].set_local_max_ack_delay(
+        kAlarmGranularity);
+  } else {
+    QUIC_RELOADABLE_FLAG_COUNT(quic_delay_initial_ack);
+  }
   received_packet_managers_[HANDSHAKE_DATA].set_local_max_ack_delay(
       kAlarmGranularity);
 
diff --git a/quic/core/uber_received_packet_manager.h b/quic/core/uber_received_packet_manager.h
index 17b5e26..a9f1775 100644
--- a/quic/core/uber_received_packet_manager.h
+++ b/quic/core/uber_received_packet_manager.h
@@ -54,7 +54,7 @@
   void ResetAckStates(EncryptionLevel encryption_level);
 
   // Called to enable multiple packet number support.
-  void EnableMultiplePacketNumberSpacesSupport();
+  void EnableMultiplePacketNumberSpacesSupport(Perspective perspective);
 
   // Returns true if ACK frame has been updated since GetUpdatedAckFrame was
   // last called.
diff --git a/quic/core/uber_received_packet_manager_test.cc b/quic/core/uber_received_packet_manager_test.cc
index b7063d2..3a1531b 100644
--- a/quic/core/uber_received_packet_manager_test.cc
+++ b/quic/core/uber_received_packet_manager_test.cc
@@ -439,7 +439,7 @@
 
 TEST_F(UberReceivedPacketManagerTest,
        DontWaitForPacketsBeforeMultiplePacketNumberSpaces) {
-  manager_->EnableMultiplePacketNumberSpacesSupport();
+  manager_->EnableMultiplePacketNumberSpacesSupport(Perspective::IS_CLIENT);
   EXPECT_FALSE(
       manager_->GetLargestObserved(ENCRYPTION_HANDSHAKE).IsInitialized());
   EXPECT_FALSE(
@@ -469,10 +469,42 @@
 }
 
 TEST_F(UberReceivedPacketManagerTest, AckSendingDifferentPacketNumberSpaces) {
-  manager_->EnableMultiplePacketNumberSpacesSupport();
+  manager_->EnableMultiplePacketNumberSpacesSupport(Perspective::IS_SERVER);
   EXPECT_FALSE(HasPendingAck());
   EXPECT_FALSE(manager_->IsAckFrameUpdated());
 
+  RecordPacketReceipt(ENCRYPTION_INITIAL, 3);
+  EXPECT_TRUE(manager_->IsAckFrameUpdated());
+  MaybeUpdateAckTimeout(kInstigateAck, ENCRYPTION_INITIAL, 3);
+  EXPECT_TRUE(HasPendingAck());
+  // Delayed ack is scheduled.
+  if (GetQuicReloadableFlag(quic_delay_initial_ack)) {
+    CheckAckTimeout(clock_.ApproximateNow() +
+                    QuicTime::Delta::FromMilliseconds(25));
+    // Send delayed handshake data ACK.
+    clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(25));
+  } else {
+    CheckAckTimeout(clock_.ApproximateNow() +
+                    QuicTime::Delta::FromMilliseconds(1));
+    // Send delayed handshake data ACK.
+    clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
+  }
+  CheckAckTimeout(clock_.ApproximateNow());
+  EXPECT_FALSE(HasPendingAck());
+
+  // Second delayed ack should have a shorter delay.
+  RecordPacketReceipt(ENCRYPTION_INITIAL, 4);
+  EXPECT_TRUE(manager_->IsAckFrameUpdated());
+  MaybeUpdateAckTimeout(kInstigateAck, ENCRYPTION_INITIAL, 4);
+  EXPECT_TRUE(HasPendingAck());
+  // Delayed ack is scheduled.
+  CheckAckTimeout(clock_.ApproximateNow() +
+                  QuicTime::Delta::FromMilliseconds(1));
+  // Send delayed handshake data ACK.
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
+  CheckAckTimeout(clock_.ApproximateNow());
+  EXPECT_FALSE(HasPendingAck());
+
   RecordPacketReceipt(ENCRYPTION_HANDSHAKE, 3);
   EXPECT_TRUE(manager_->IsAckFrameUpdated());
   MaybeUpdateAckTimeout(kInstigateAck, ENCRYPTION_HANDSHAKE, 3);