gfe-relnote: In QUIC T049+, support sending coalesced packets.

PiperOrigin-RevId: 278634718
Change-Id: If6eadcb1a165e0cf4993f60d3a4faeb108fe8ccb
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index b6aa85e..5a2e0ef 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -514,6 +514,10 @@
     return framer_.path_response_frames();
   }
 
+  const QuicEncryptedPacket* coalesced_packet() const {
+    return framer_.coalesced_packet();
+  }
+
   size_t last_packet_size() { return last_packet_size_; }
 
   const QuicPacketHeader& last_packet_header() const {
@@ -631,6 +635,7 @@
                   HasRetransmittableData retransmittable,
                   bool has_ack,
                   bool has_pending_frames) {
+    ScopedPacketFlusher flusher(this);
     char buffer[kMaxOutgoingPacketSize];
     size_t encrypted_length =
         QuicConnectionPeer::GetFramer(this)->EncryptPayload(
@@ -641,7 +646,7 @@
         encrypted_length, has_ack, has_pending_frames);
     if (retransmittable == HAS_RETRANSMITTABLE_DATA) {
       serialized_packet.retransmittable_frames.push_back(
-          QuicFrame(QuicStreamFrame()));
+          QuicFrame(QuicPingFrame()));
     }
     OnSerializedPacket(&serialized_packet);
   }
@@ -2010,7 +2015,7 @@
   writer_->SetWritable();
   connection_.SendConnectivityProbingPacket(writer_.get(),
                                             connection_.peer_address());
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_CALL(visitor_, OnConnectionClosed(_, _)).Times(0);
     connection_.OnCanWrite();
     return;
@@ -2046,7 +2051,7 @@
   connection_.SendStreamDataWithString(/*id=*/2, "foo", 0, NO_FIN);
 
   EXPECT_FALSE(connection_.connected());
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     // No need to buffer packets.
     EXPECT_EQ(0u, connection_.NumQueuedPackets());
   } else {
@@ -3054,7 +3059,9 @@
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
     QuicConnection::ScopedPacketFlusher flusher(&connection_);
     connection_.SendStreamData3();
+    connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
     connection_.SendCryptoStreamData();
+    connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
   }
   EXPECT_EQ(0u, connection_.NumQueuedPackets());
   EXPECT_FALSE(connection_.HasQueuedData());
@@ -3352,7 +3359,7 @@
   BlockOnNextWrite();
 
   QuicStreamId stream_id = 2;
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
   } else {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
@@ -3364,7 +3371,7 @@
 
   // Unblock the connection and verify that the RST_STREAM is sent and the data
   // packet is sent.
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
         .Times(AtLeast(1));
   } else {
@@ -3569,7 +3576,7 @@
   EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _, _))
       .WillOnce(SetArgPointee<5>(lost_packets));
   EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(4), _, _))
         .Times(1);
   } else {
@@ -3584,7 +3591,7 @@
   QuicAckFrame ack_all = InitAckFrame(3);
   ProcessAckPacket(&ack_all);
 
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(4), _, _))
         .Times(0);
   } else {
@@ -3643,7 +3650,7 @@
   // Block the writer and ensure they're queued.
   BlockOnNextWrite();
   clock_.AdvanceTime(DefaultRetransmissionTime());
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
   } else {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
@@ -3655,7 +3662,7 @@
   writer_->SetWritable();
   clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(
       2 * DefaultRetransmissionTime().ToMicroseconds()));
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
   } else {
     // 2 RTOs + 1 TLP, which is buggy.
@@ -3680,13 +3687,13 @@
 TEST_P(QuicConnectionTest, WriteBlockedThenSent) {
   EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
   BlockOnNextWrite();
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
   } else {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
   }
   connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN);
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
   } else {
     EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
@@ -3696,7 +3703,7 @@
   // The second packet should also be queued, in order to ensure packets are
   // never sent out of order.
   writer_->SetWritable();
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
   } else {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
@@ -3705,7 +3712,7 @@
   EXPECT_EQ(2u, connection_.NumQueuedPackets());
 
   // Now both are sent in order when we unblock.
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
   } else {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
@@ -4230,9 +4237,12 @@
 
   // Manually mark both packets for retransmission.
   connection_.RetransmitUnackedPackets(ALL_UNACKED_RETRANSMISSION);
-
-  // Packet should have been sent with ENCRYPTION_INITIAL.
-  EXPECT_EQ(0x01010101u, writer_->final_bytes_of_previous_packet());
+  if (!connection_.version().CanSendCoalescedPackets()) {
+    // Packet should have been sent with ENCRYPTION_INITIAL.
+    // If connection can send coalesced packet, both retransmissions will be
+    // coalesced in the same UDP datagram.
+    EXPECT_EQ(0x01010101u, writer_->final_bytes_of_previous_packet());
+  }
 
   // Packet should have been sent with ENCRYPTION_ZERO_RTT.
   EXPECT_EQ(0x02020202u, writer_->final_bytes_of_last_packet());
@@ -4277,7 +4287,7 @@
   // Simulate the retransmission alarm firing and the socket blocking.
   BlockOnNextWrite();
   clock_.AdvanceTime(DefaultRetransmissionTime());
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
   } else {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
@@ -4431,13 +4441,13 @@
 
 TEST_P(QuicConnectionTest, SetRTOAfterWritingToSocket) {
   BlockOnNextWrite();
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
   } else {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
   }
   connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN);
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
   } else {
     // Make sure that RTO is not started when the packet is queued.
@@ -4446,7 +4456,7 @@
 
   // Test that RTO is started once we write to the socket.
   writer_->SetWritable();
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
   } else {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
@@ -6492,7 +6502,7 @@
   }
   // Check that ack is sent and that delayed ack alarm is reset.
   if (GetParam().no_stop_waiting) {
-    EXPECT_EQ(1u, writer_->frame_count());
+    EXPECT_EQ(writer_->padding_frames().size() + 1u, writer_->frame_count());
     EXPECT_TRUE(writer_->stop_waiting_frames().empty());
   } else {
     EXPECT_EQ(2u, writer_->frame_count());
@@ -6509,7 +6519,7 @@
                            ENCRYPTION_ZERO_RTT);
   // Check that ack is sent and that delayed ack alarm is reset.
   if (GetParam().no_stop_waiting) {
-    EXPECT_EQ(1u, writer_->frame_count());
+    EXPECT_EQ(writer_->padding_frames().size() + 1u, writer_->frame_count());
     EXPECT_TRUE(writer_->stop_waiting_frames().empty());
   } else {
     EXPECT_EQ(2u, writer_->frame_count());
@@ -6645,7 +6655,7 @@
   }
   // Check that ack is sent and that delayed ack alarm is reset.
   if (GetParam().no_stop_waiting) {
-    EXPECT_EQ(1u, writer_->frame_count());
+    EXPECT_EQ(writer_->padding_frames().size() + 1u, writer_->frame_count());
     EXPECT_TRUE(writer_->stop_waiting_frames().empty());
   } else {
     EXPECT_EQ(2u, writer_->frame_count());
@@ -6662,7 +6672,7 @@
                            ENCRYPTION_ZERO_RTT);
   // Check that ack is sent and that delayed ack alarm is reset.
   if (GetParam().no_stop_waiting) {
-    EXPECT_EQ(1u, writer_->frame_count());
+    EXPECT_EQ(writer_->padding_frames().size() + 1u, writer_->frame_count());
     EXPECT_TRUE(writer_->stop_waiting_frames().empty());
   } else {
     EXPECT_EQ(2u, writer_->frame_count());
@@ -8049,7 +8059,7 @@
   EXPECT_CALL(visitor_, WillingAndAbleToWrite()).WillRepeatedly(Return(true));
   BlockOnNextWrite();
 
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
   } else {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
@@ -8061,7 +8071,7 @@
   writer_->SetWritable();
   CongestionBlockWrites();
   EXPECT_CALL(visitor_, WillingAndAbleToWrite()).WillRepeatedly(Return(false));
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
   } else {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
@@ -8199,8 +8209,15 @@
       .WillRepeatedly(Invoke([this, &sent_count](const SerializedPacket&,
                                                  TransmissionType, QuicTime) {
         ASSERT_EQ(1u, writer_->stream_frames().size());
-        // Identify the frames by stream offset (0, 3, 6, 0, 3...).
-        EXPECT_EQ(3 * (sent_count % 3), writer_->stream_frames()[0]->offset);
+        if (connection_.version().CanSendCoalescedPackets()) {
+          // There is a delay of sending coalesced packet, so (6, 0, 3, 6,
+          // 0...).
+          EXPECT_EQ(3 * ((sent_count + 2) % 3),
+                    writer_->stream_frames()[0]->offset);
+        } else {
+          // Identify the frames by stream offset (0, 3, 6, 0, 3...).
+          EXPECT_EQ(3 * (sent_count % 3), writer_->stream_frames()[0]->offset);
+        }
         sent_count++;
       }));
   EXPECT_CALL(*send_algorithm_, ShouldSendProbingPacket())
@@ -8681,14 +8698,14 @@
 
 TEST_P(QuicConnectionTest, WriteBlockedWithInvalidAck) {
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_CALL(visitor_, OnConnectionClosed(_, _)).Times(0);
   } else {
     EXPECT_CALL(visitor_, OnConnectionClosed(_, _))
         .WillOnce(Invoke(this, &QuicConnectionTest::SaveConnectionCloseFrame));
   }
   BlockOnNextWrite();
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
   } else {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
@@ -8696,11 +8713,11 @@
   connection_.SendStreamDataWithString(5, "foo", 0, FIN);
   // This causes connection to be closed because packet 1 has not been sent yet.
   QuicAckFrame frame = InitAckFrame(1);
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _));
   }
   ProcessAckPacket(1, &frame);
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_EQ(0, connection_close_frame_count_);
   } else {
     EXPECT_EQ(1, connection_close_frame_count_);
@@ -9359,7 +9376,7 @@
   EXPECT_CALL(visitor_, OnWriteBlocked()).Times(AtLeast(1));
   SendRstStream(stream_id, QUIC_ERROR_PROCESSING_STREAM, 3);
 
-  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+  if (connection_.treat_queued_packets_as_sent()) {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
   } else {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
@@ -9731,6 +9748,44 @@
   EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
 }
 
+TEST_P(QuicConnectionTest, SendCoalescedPackets) {
+  if (!connection_.version().CanSendCoalescedPackets()) {
+    return;
+  }
+  {
+    QuicConnection::ScopedPacketFlusher flusher(&connection_);
+    use_tagging_decrypter();
+    connection_.SetEncrypter(ENCRYPTION_INITIAL,
+                             std::make_unique<TaggingEncrypter>(0x01));
+    connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
+    connection_.SendCryptoDataWithString("foo", 0);
+    // Verify this packet is on hold.
+    EXPECT_EQ(0u, writer_->packets_write_attempts());
+
+    connection_.SetEncrypter(ENCRYPTION_HANDSHAKE,
+                             std::make_unique<TaggingEncrypter>(0x02));
+    connection_.SetDefaultEncryptionLevel(ENCRYPTION_HANDSHAKE);
+    connection_.SendCryptoDataWithString("bar", 3);
+    EXPECT_EQ(0u, writer_->packets_write_attempts());
+
+    connection_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
+                             std::make_unique<TaggingEncrypter>(0x03));
+    connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+    SendStreamDataToPeer(2, "baz", 3, NO_FIN, nullptr);
+  }
+  // Verify all 3 packets are coalesced in the same UDP datagram.
+  EXPECT_EQ(1u, writer_->packets_write_attempts());
+  EXPECT_EQ(0x03030303u, writer_->final_bytes_of_last_packet());
+  // Verify the packet is padded to full.
+  EXPECT_EQ(connection_.max_packet_length(), writer_->last_packet_size());
+
+  // Verify packet process.
+  EXPECT_EQ(1u, writer_->crypto_frames().size());
+  EXPECT_EQ(0u, writer_->stream_frames().size());
+  // Verify there is coalesced packet.
+  EXPECT_NE(nullptr, writer_->coalesced_packet());
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace quic