In quic, determine a serialized packet fate before it gets serialized, and use the fate to determine whether add full padding later. protected by gfe2_reloadable_flag_quic_determine_serialized_packet_fate_early.

PiperOrigin-RevId: 319272370
Change-Id: I43b3b823d50cd5f9c1b8c7d946eb1319706ee41e
diff --git a/quic/core/quic_packet_creator.cc b/quic/core/quic_packet_creator.cc
index e6f01ea..cf5540e 100644
--- a/quic/core/quic_packet_creator.cc
+++ b/quic/core/quic_packet_creator.cc
@@ -496,6 +496,7 @@
   packet_.transmission_type = NOT_RETRANSMISSION;
   packet_.encrypted_buffer = nullptr;
   packet_.encrypted_length = 0;
+  packet_.fate = SEND_TO_WRITER;
   if (avoid_leak_writer_buffer_) {
     QUIC_RELOADABLE_FLAG_COUNT_N(quic_avoid_leak_writer_buffer, 2, 3);
     QUIC_BUG_IF(packet_.release_encrypted_buffer != nullptr)
@@ -568,6 +569,14 @@
   // Write out the packet header
   QuicPacketHeader header;
   FillPacketHeader(&header);
+  if (determine_serialized_packet_fate_early_) {
+    packet_.fate = delegate_->GetSerializedPacketFate(
+        /*is_mtu_discovery=*/false, packet_.encryption_level);
+    QUIC_DVLOG(1) << ENDPOINT << "fate of packet " << packet_.packet_number
+                  << ": " << SerializedPacketFateToString(packet_.fate)
+                  << " of "
+                  << EncryptionLevelToString(packet_.encryption_level);
+  }
 
   QUIC_CACHELINE_ALIGNED char stack_buffer[kMaxOutgoingPacketSize];
   QuicOwnedPacketBuffer packet_buffer(delegate_->GetPacketBuffer());
@@ -758,6 +767,17 @@
   QuicPacketHeader header;
   // FillPacketHeader increments packet_number_.
   FillPacketHeader(&header);
+  if (determine_serialized_packet_fate_early_ && delegate_ != nullptr) {
+    QUIC_RELOADABLE_FLAG_COUNT(quic_determine_serialized_packet_fate_early);
+    packet_.fate = delegate_->GetSerializedPacketFate(
+        /*is_mtu_discovery=*/QuicUtils::ContainsFrameType(queued_frames_,
+                                                          MTU_DISCOVERY_FRAME),
+        packet_.encryption_level);
+    QUIC_DVLOG(1) << ENDPOINT << "fate of packet " << packet_.packet_number
+                  << ": " << SerializedPacketFateToString(packet_.fate)
+                  << " of "
+                  << EncryptionLevelToString(packet_.encryption_level);
+  }
 
   MaybeAddPadding();
 
@@ -1758,27 +1778,36 @@
     needs_full_padding_ = true;
   }
 
-  // Packet coalescer pads INITIAL packets, so the creator should not.
-  if (framer_->version().CanSendCoalescedPackets() &&
-      (packet_.encryption_level == ENCRYPTION_INITIAL ||
-       packet_.encryption_level == ENCRYPTION_HANDSHAKE)) {
-    // TODO(fayang): MTU discovery packets should not ever be sent as
-    // ENCRYPTION_INITIAL or ENCRYPTION_HANDSHAKE.
-    bool is_mtu_discovery = false;
-    for (const auto& frame : packet_.nonretransmittable_frames) {
-      if (frame.type == MTU_DISCOVERY_FRAME) {
-        is_mtu_discovery = true;
-        break;
-      }
-    }
-    if (!is_mtu_discovery) {
-      // Do not add full padding if connection tries to coalesce packet.
+  if (determine_serialized_packet_fate_early_) {
+    if (packet_.fate == COALESCE ||
+        packet_.fate == LEGACY_VERSION_ENCAPSULATE) {
+      // Do not add full padding if the packet is going to be coalesced or
+      // encapsulated.
       needs_full_padding_ = false;
     }
-  }
+  } else {
+    // Packet coalescer pads INITIAL packets, so the creator should not.
+    if (framer_->version().CanSendCoalescedPackets() &&
+        (packet_.encryption_level == ENCRYPTION_INITIAL ||
+         packet_.encryption_level == ENCRYPTION_HANDSHAKE)) {
+      // TODO(fayang): MTU discovery packets should not ever be sent as
+      // ENCRYPTION_INITIAL or ENCRYPTION_HANDSHAKE.
+      bool is_mtu_discovery = false;
+      for (const auto& frame : packet_.nonretransmittable_frames) {
+        if (frame.type == MTU_DISCOVERY_FRAME) {
+          is_mtu_discovery = true;
+          break;
+        }
+      }
+      if (!is_mtu_discovery) {
+        // Do not add full padding if connection tries to coalesce packet.
+        needs_full_padding_ = false;
+      }
+    }
 
-  if (disable_padding_override_) {
-    needs_full_padding_ = false;
+    if (disable_padding_override_) {
+      needs_full_padding_ = false;
+    }
   }
 
   // Header protection requires a minimum plaintext packet size.