gfe-relnote: In QUIC, consider packets (which cannot be sent because of write blocked) as sent from unacked_packet_map and congestion control's perspectives. Protected by gfe2_reloadable_flag_quic_treat_queued_packets_as_sent.

PiperOrigin-RevId: 272424245
Change-Id: I83d54860464e3d6b6169475de90fa74904cc5438
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index 1828a63..ce1e6c4 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -326,7 +326,9 @@
       bytes_received_before_address_validation_(0),
       bytes_sent_before_address_validation_(0),
       address_validated_(false),
-      skip_packet_number_for_pto_(false) {
+      skip_packet_number_for_pto_(false),
+      treat_queued_packets_as_sent_(
+          GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
   QUIC_DLOG(INFO) << ENDPOINT << "Created connection with server connection ID "
                   << server_connection_id
                   << " and version: " << ParsedQuicVersionToString(version());
@@ -389,10 +391,13 @@
   for (auto it = queued_packets_.begin(); it != queued_packets_.end(); ++it) {
     // Delete the buffer before calling ClearSerializedPacket, which sets
     // encrypted_buffer to nullptr.
+    DCHECK(!treat_queued_packets_as_sent_);
     delete[] it->encrypted_buffer;
     ClearSerializedPacket(&(*it));
   }
   queued_packets_.clear();
+
+  buffered_packets_.clear();
 }
 
 void QuicConnection::SetFromConfig(const QuicConfig& config) {
@@ -2019,6 +2024,7 @@
   QUIC_CLIENT_HISTOGRAM_COUNTS("QuicSession.NumQueuedPacketsBeforeWrite",
                                queued_packets_.size(), 1, 1000, 50, "");
   while (!queued_packets_.empty()) {
+    DCHECK(!treat_queued_packets_as_sent_);
     // WritePacket() can potentially clear all queued packets, so we need to
     // save the first queued packet to a local variable before calling it.
     SerializedPacket packet(std::move(queued_packets_.front()));
@@ -2043,6 +2049,30 @@
 
     // Continue to send the next packet in queue.
   }
+
+  while (!buffered_packets_.empty()) {
+    DCHECK(treat_queued_packets_as_sent_);
+    if (HandleWriteBlocked()) {
+      break;
+    }
+    const BufferedPacket& packet = buffered_packets_.front();
+    WriteResult result = writer_->WritePacket(
+        packet.encrypted_buffer.data(), packet.encrypted_buffer.length(),
+        packet.self_address.host(), packet.peer_address, per_packet_options_);
+    QUIC_DVLOG(1) << ENDPOINT << "Sending buffered packet, result: " << result;
+    if (IsWriteError(result.status)) {
+      OnWriteError(result.error_code);
+      break;
+    }
+    if (result.status == WRITE_STATUS_OK ||
+        result.status == WRITE_STATUS_BLOCKED_DATA_BUFFERED) {
+      buffered_packets_.pop_front();
+    }
+    if (IsWriteBlockedStatus(result.status)) {
+      visitor_->OnWriteBlocked();
+      break;
+    }
+  }
 }
 
 void QuicConnection::WritePendingRetransmissions() {
@@ -2210,9 +2240,11 @@
                     ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
     return true;
   }
+  SerializedPacketFate fate = DeterminePacketFate();
   // Termination packets are encrypted and saved, so don't exit early.
   const bool is_termination_packet = IsTerminationPacket(*packet);
-  if (HandleWriteBlocked() && !is_termination_packet) {
+  if (!treat_queued_packets_as_sent_ && HandleWriteBlocked() &&
+      !is_termination_packet) {
     return false;
   }
 
@@ -2232,7 +2264,7 @@
         new QuicEncryptedPacket(buffer_copy, encrypted_length, true));
     // This assures we won't try to write *forced* packets when blocked.
     // Return true to stop processing.
-    if (HandleWriteBlocked()) {
+    if (!treat_queued_packets_as_sent_ && HandleWriteBlocked()) {
       return true;
     }
   }
@@ -2265,9 +2297,26 @@
     }
     per_packet_options_->release_time_delay = release_time_delay;
   }
-  WriteResult result = writer_->WritePacket(
-      packet->encrypted_buffer, encrypted_length, self_address().host(),
-      peer_address(), per_packet_options_);
+  WriteResult result(WRITE_STATUS_OK, encrypted_length);
+  switch (fate) {
+    case COALESCE:
+      DCHECK(false);
+      break;
+    case BUFFER:
+      DCHECK(treat_queued_packets_as_sent_);
+      QUIC_DVLOG(1) << ENDPOINT << "Adding packet: " << packet->packet_number
+                    << " to buffered packets";
+      buffered_packets_.emplace_back(*packet, self_address(), peer_address());
+      break;
+    case SEND_TO_WRITER:
+      result = writer_->WritePacket(packet->encrypted_buffer, encrypted_length,
+                                    self_address().host(), peer_address(),
+                                    per_packet_options_);
+      break;
+    default:
+      DCHECK(false);
+      break;
+  }
 
   QUIC_HISTOGRAM_ENUM(
       "QuicConnection.WritePacketStatus", result.status,
@@ -2284,7 +2333,13 @@
     // duplicate packet being sent.  The helper must call OnCanWrite
     // when the write completes, and OnWriteError if an error occurs.
     if (result.status != WRITE_STATUS_BLOCKED_DATA_BUFFERED) {
-      return false;
+      if (treat_queued_packets_as_sent_) {
+        QUIC_DVLOG(1) << ENDPOINT << "Adding packet: " << packet->packet_number
+                      << " to buffered packets";
+        buffered_packets_.emplace_back(*packet, self_address(), peer_address());
+      } else {
+        return false;
+      }
     }
   }
 
@@ -2535,10 +2590,12 @@
   // If there are already queued packets, queue this one immediately to ensure
   // it's written in sequence number order.
   if (!queued_packets_.empty() || !WritePacket(packet)) {
-    // Take ownership of the underlying encrypted packet.
-    packet->encrypted_buffer = CopyBuffer(*packet);
-    queued_packets_.push_back(*packet);
-    packet->retransmittable_frames.clear();
+    if (!treat_queued_packets_as_sent_) {
+      // Take ownership of the underlying encrypted packet.
+      packet->encrypted_buffer = CopyBuffer(*packet);
+      queued_packets_.push_back(*packet);
+      packet->retransmittable_frames.clear();
+    }
   }
 
   ClearSerializedPacket(packet);
@@ -2955,13 +3012,14 @@
 
 bool QuicConnection::HasQueuedData() const {
   return pending_version_negotiation_packet_ || !queued_packets_.empty() ||
-         packet_generator_.HasPendingFrames();
+         packet_generator_.HasPendingFrames() || !buffered_packets_.empty();
 }
 
 bool QuicConnection::CanWriteStreamData() {
   // Don't write stream data if there are negotiation or queued data packets
   // to send. Otherwise, continue and bundle as many frames as possible.
-  if (pending_version_negotiation_packet_ || !queued_packets_.empty()) {
+  if (pending_version_negotiation_packet_ || !queued_packets_.empty() ||
+      !buffered_packets_.empty()) {
     return false;
   }
 
@@ -3225,6 +3283,18 @@
             !connection_->packet_generator_.PacketFlusherAttached());
 }
 
+QuicConnection::BufferedPacket::BufferedPacket(
+    const SerializedPacket& packet,
+    const QuicSocketAddress& self_address,
+    const QuicSocketAddress& peer_address)
+    : encrypted_buffer(CopyBuffer(packet), packet.encrypted_length),
+      self_address(self_address),
+      peer_address(peer_address) {}
+
+QuicConnection::BufferedPacket::~BufferedPacket() {
+  delete[] encrypted_buffer.data();
+}
+
 HasRetransmittableData QuicConnection::IsRetransmittable(
     const SerializedPacket& packet) {
   // Retransmitted packets retransmittable frames are owned by the unacked
@@ -3543,7 +3613,7 @@
   }
 
   bool application_limited =
-      queued_packets_.empty() &&
+      queued_packets_.empty() && buffered_packets_.empty() &&
       !sent_packet_manager_.HasPendingRetransmissions() &&
       !visitor_->WillingAndAbleToWrite();
 
@@ -3885,6 +3955,14 @@
                  bytes_received_before_address_validation_;
 }
 
+QuicConnection::SerializedPacketFate QuicConnection::DeterminePacketFate() {
+  if (treat_queued_packets_as_sent_ &&
+      (!buffered_packets_.empty() || HandleWriteBlocked())) {
+    return BUFFER;
+  }
+  return SEND_TO_WRITER;
+}
+
 size_t QuicConnection::min_received_before_ack_decimation() const {
   return uber_received_packet_manager_.min_received_before_ack_decimation();
 }
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h
index 399ba13..bb4464b 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -623,7 +623,12 @@
   }
 
   // Testing only.
-  size_t NumQueuedPackets() const { return queued_packets_.size(); }
+  size_t NumQueuedPackets() const {
+    if (treat_queued_packets_as_sent_) {
+      return buffered_packets_.size();
+    }
+    return queued_packets_.size();
+  }
 
   // Returns true if the underlying UDP socket is writable, there is
   // no queued data and the connection is not congestion-control
@@ -994,6 +999,33 @@
 
   typedef std::list<SerializedPacket> QueuedPacketList;
 
+  // Indicates the fate of a serialized packet in WritePacket().
+  enum SerializedPacketFate : uint8_t {
+    COALESCE,        // Try to coalesce packet.
+    BUFFER,          // Buffer packet in buffered_packets_.
+    SEND_TO_WRITER,  // Send packet to writer.
+  };
+
+  // BufferedPacket stores necessary information (encrypted buffer and self/peer
+  // addresses) of those packets which are serialized but failed to send because
+  // socket is blocked. From unacked packet map and send algorithm's
+  // perspective, buffered packets are treated as sent.
+  struct BufferedPacket {
+    BufferedPacket(const SerializedPacket& packet,
+                   const QuicSocketAddress& self_address,
+                   const QuicSocketAddress& peer_address);
+    BufferedPacket(const BufferedPacket& other) = delete;
+    BufferedPacket(const BufferedPacket&& other) = delete;
+
+    ~BufferedPacket();
+
+    // encrypted_buffer is owned by buffered packet.
+    QuicStringPiece encrypted_buffer;
+    // Self and peer addresses when the packet is serialized.
+    const QuicSocketAddress self_address;
+    const QuicSocketAddress peer_address;
+  };
+
   // Notifies the visitor of the close and marks the connection as disconnected.
   // Does not send a connection close frame to the peer. It should only be
   // called by CloseConnection or OnConnectionCloseFrame, OnPublicResetPacket,
@@ -1142,6 +1174,9 @@
   // and flags.
   void MaybeEnableMultiplePacketNumberSpacesSupport();
 
+  // Returns packet fate when trying to write a packet.
+  SerializedPacketFate DeterminePacketFate();
+
   // Returns the encryption level the connection close packet should be sent at,
   // which is the highest encryption level that peer can guarantee to process.
   EncryptionLevel GetConnectionCloseEncryptionLevel() const;
@@ -1272,6 +1307,8 @@
   // unacked_packets_ if they are to be retransmitted.  Packets encrypted_buffer
   // fields are owned by the QueuedPacketList, in order to ensure they outlast
   // the original scope of the SerializedPacket.
+  // TODO(fayang): Remove this when deprecating
+  // quic_treat_queued_packets_as_sent.
   QueuedPacketList queued_packets_;
 
   // Contains the connection close packets if the connection has been closed.
@@ -1494,6 +1531,16 @@
 
   // If true, skip packet number before sending the last PTO retransmission.
   bool skip_packet_number_for_pto_;
+
+  // Used to store content of packets which cannot be sent because of write
+  // blocked. Packets' encrypted buffers are copied and owned by
+  // buffered_packets_. From unacked_packet_map (and congestion control)'s
+  // perspective, those packets are considered sent. This is only used when
+  // treat_queued_packets_as_sent_ is true.
+  std::list<BufferedPacket> buffered_packets_;
+
+  // Latched value of quic_treat_queued_packets_as_sent.
+  const bool treat_queued_packets_as_sent_;
 };
 
 }  // namespace quic
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index f65f0cd..9e11494 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -721,7 +721,19 @@
   QuicConsumedData SendCryptoStreamData() {
     QuicStreamOffset offset = 0;
     QuicStringPiece data("chlo");
-    return SendCryptoDataWithString(data, offset);
+    if (!QuicVersionUsesCryptoFrames(transport_version())) {
+      return SendCryptoDataWithString(data, offset);
+    }
+    producer_.SaveCryptoData(ENCRYPTION_INITIAL, offset, data);
+    size_t bytes_written;
+    if (notifier_) {
+      bytes_written =
+          notifier_->WriteCryptoData(ENCRYPTION_INITIAL, data.length(), offset);
+    } else {
+      bytes_written = QuicConnection::SendCryptoData(ENCRYPTION_INITIAL,
+                                                     data.length(), offset);
+    }
+    return QuicConsumedData(bytes_written, /*fin_consumed*/ false);
   }
 
   QuicConsumedData SendCryptoDataWithString(QuicStringPiece data,
@@ -2015,7 +2027,11 @@
   writer_->SetWritable();
   connection_.SendConnectivityProbingPacket(writer_.get(),
                                             connection_.peer_address());
-
+  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+    EXPECT_CALL(visitor_, OnConnectionClosed(_, _)).Times(0);
+    connection_.OnCanWrite();
+    return;
+  }
   EXPECT_CALL(visitor_,
               OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
   EXPECT_QUIC_BUG(connection_.OnCanWrite(),
@@ -2046,7 +2062,12 @@
   connection_.SendStreamDataWithString(/*id=*/2, "foo", 0, NO_FIN);
 
   EXPECT_FALSE(connection_.connected());
-  EXPECT_EQ(1u, connection_.NumQueuedPackets());
+  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+    // No need to buffer packets.
+    EXPECT_EQ(0u, connection_.NumQueuedPackets());
+  } else {
+    EXPECT_EQ(1u, connection_.NumQueuedPackets());
+  }
 
   EXPECT_EQ(0u, connection_.GetStats().packets_discarded);
   connection_.OnCanWrite();
@@ -3355,6 +3376,11 @@
   BlockOnNextWrite();
 
   QuicStreamId stream_id = 2;
+  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+  } else {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
+  }
   connection_.SendStreamDataWithString(stream_id, "foo", 0, NO_FIN);
 
   // Now that there is a queued packet, reset the stream.
@@ -3362,7 +3388,13 @@
 
   // Unblock the connection and verify that the RST_STREAM is sent and the data
   // packet is sent.
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(2));
+  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+        .Times(AtLeast(1));
+  } else {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+        .Times(AtLeast(2));
+  }
   writer_->SetWritable();
   connection_.OnCanWrite();
   if (!connection_.session_decides_what_to_write()) {
@@ -3576,6 +3608,12 @@
   EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _, _))
       .WillOnce(SetArgPointee<5>(lost_packets));
   EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
+  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(4), _, _))
+        .Times(1);
+  } else {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
+  }
   ProcessAckPacket(&nack_two);
   EXPECT_EQ(1u, connection_.NumQueuedPackets());
 
@@ -3585,10 +3623,15 @@
   QuicAckFrame ack_all = InitAckFrame(3);
   ProcessAckPacket(&ack_all);
 
-  // Unblock the socket and attempt to send the queued packets. We will always
-  // send the retransmission.
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(4), _, _))
-      .Times(1);
+  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(4), _, _))
+        .Times(0);
+  } else {
+    // Unblock the socket and attempt to send the queued packets. We will always
+    // send the retransmission.
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(4), _, _))
+        .Times(1);
+  }
 
   writer_->SetWritable();
   connection_.OnCanWrite();
@@ -3640,6 +3683,19 @@
   BlockOnNextWrite();
   clock_.AdvanceTime(DefaultRetransmissionTime());
   // Only one packet should be retransmitted.
+  if (connection_.session_decides_what_to_write()) {
+    if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+      EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
+    } else {
+      EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
+    }
+  } else {
+    if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+      EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+    } else {
+      EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
+    }
+  }
   connection_.GetRetransmissionAlarm()->Fire();
   EXPECT_TRUE(connection_.HasQueuedData());
 
@@ -3650,10 +3706,18 @@
   // Retransmit already retransmitted packets event though the packet number
   // greater than the largest observed.
   if (connection_.session_decides_what_to_write()) {
-    // 2 RTOs + 1 TLP.
-    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(3);
+    if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+      EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
+    } else {
+      // 2 RTOs + 1 TLP.
+      EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(3);
+    }
   } else {
-    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
+    if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+      EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+    } else {
+      EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
+    }
   }
   connection_.GetRetransmissionAlarm()->Fire();
   connection_.OnCanWrite();
@@ -3674,20 +3738,39 @@
 TEST_P(QuicConnectionTest, WriteBlockedThenSent) {
   EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
   BlockOnNextWrite();
+  if (GetQuicReloadableFlag(quic_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);
-  EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
+  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+    EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
+  } else {
+    EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
+  }
   EXPECT_EQ(1u, connection_.NumQueuedPackets());
 
   // 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)) {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+  } else {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
+  }
   connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN);
   EXPECT_EQ(2u, connection_.NumQueuedPackets());
 
   // Now both are sent in order when we unblock.
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
+  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
+  } else {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
+  }
   connection_.OnCanWrite();
   EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
+  EXPECT_EQ(0u, connection_.NumQueuedPackets());
 }
 
 TEST_P(QuicConnectionTest, RetransmitWriteBlockedAckedOriginalThenSent) {
@@ -4282,7 +4365,13 @@
   // Simulate the retransmission alarm firing and the socket blocking.
   BlockOnNextWrite();
   clock_.AdvanceTime(DefaultRetransmissionTime());
+  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+  } else {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
+  }
   connection_.GetRetransmissionAlarm()->Fire();
+  EXPECT_EQ(1u, connection_.NumQueuedPackets());
 
   // Go forward secure.
   connection_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
@@ -4290,6 +4379,7 @@
   connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
   notifier_.NeuterUnencryptedData();
   connection_.NeuterUnencryptedPackets();
+  connection_.OnHandshakeComplete();
 
   EXPECT_EQ(QuicTime::Zero(), connection_.GetRetransmissionAlarm()->deadline());
   // Unblock the socket and ensure that no packets are sent.
@@ -4429,12 +4519,26 @@
 
 TEST_P(QuicConnectionTest, SetRTOAfterWritingToSocket) {
   BlockOnNextWrite();
+  if (GetQuicReloadableFlag(quic_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);
-  // Make sure that RTO is not started when the packet is queued.
-  EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
+  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+    EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
+  } else {
+    // Make sure that RTO is not started when the packet is queued.
+    EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
+  }
 
   // Test that RTO is started once we write to the socket.
   writer_->SetWritable();
+  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
+  } else {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+  }
   connection_.OnCanWrite();
   EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
 }
@@ -7803,6 +7907,11 @@
   EXPECT_CALL(visitor_, WillingAndAbleToWrite()).WillRepeatedly(Return(true));
   BlockOnNextWrite();
 
+  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+  } else {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
+  }
   connection_.SendStreamData3();
 
   // Now unblock the writer, become congestion control blocked,
@@ -7810,11 +7919,12 @@
   writer_->SetWritable();
   CongestionBlockWrites();
   EXPECT_CALL(visitor_, WillingAndAbleToWrite()).WillRepeatedly(Return(false));
-  {
-    InSequence seq;
-    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
-    EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(1);
+  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
+  } else {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
   }
+  EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(1);
   connection_.OnCanWrite();
 }
 
@@ -8216,16 +8326,32 @@
 
 TEST_P(QuicConnectionTest, WriteBlockedWithInvalidAck) {
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-  EXPECT_CALL(visitor_, OnConnectionClosed(_, _))
-      .WillOnce(Invoke(this, &QuicConnectionTest::SaveConnectionCloseFrame));
+  if (GetQuicReloadableFlag(quic_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)) {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+  } else {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
+  }
   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)) {
+    EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _));
+  }
   ProcessAckPacket(1, &frame);
-  EXPECT_EQ(1, connection_close_frame_count_);
-  EXPECT_EQ(QUIC_INVALID_ACK_DATA,
-            saved_connection_close_frame_.quic_error_code);
+  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+    EXPECT_EQ(0, connection_close_frame_count_);
+  } else {
+    EXPECT_EQ(1, connection_close_frame_count_);
+    EXPECT_EQ(QUIC_INVALID_ACK_DATA,
+              saved_connection_close_frame_.quic_error_code);
+  }
 }
 
 TEST_P(QuicConnectionTest, SendMessage) {
@@ -8884,6 +9010,11 @@
   EXPECT_CALL(visitor_, OnWriteBlocked()).Times(AtLeast(1));
   SendRstStream(stream_id, QUIC_ERROR_PROCESSING_STREAM, 3);
 
+  if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+  } else {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
+  }
   // Retransmission timer fires in TLP mode.
   connection_.GetRetransmissionAlarm()->Fire();
   // Verify one packets is forced flushed when writer is blocked.