Maybe copy datagram frames in QuicUnackedPacketMap. Protected by FLAGS_quic_reloadable_flag_quic_maybe_copy_datagram_frames. PiperOrigin-RevId: 914318383
diff --git a/quiche/common/quiche_feature_flags_list.h b/quiche/common/quiche_feature_flags_list.h index dfed18a..069549d 100755 --- a/quiche/common/quiche_feature_flags_list.h +++ b/quiche/common/quiche_feature_flags_list.h
@@ -44,6 +44,7 @@ QUICHE_FLAG(bool, quiche_reloadable_flag_quic_fix_gap_filling_ack_logic, true, true, "If true, fix the gap filling ack logic in QuicAckFrame.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_fix_timeouts, true, true, "If true, postpone setting handshake timeout to infinite to handshake complete.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_include_datagrams_in_willing_to_write, false, false, "If true, checks for queued datagrams when determining if a connection is willing to write.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_maybe_copy_datagram_frames, false, true, "If true, maybe copy datagram frames in QuicUnackedPacketMap.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_move_clock_now, false, false, "If true, move the call to clock.Now() in QuicPacketReader::ReadAndDispatchPackets to after socket_api_.ReadMultiplePackets().") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_neuter_packets_on_migration, false, true, "If ture, QuicSentPacketManager::OnConnectionMigration will call old_send_algorithm->OnPacketNeutered on all inflight packets.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_no_write_control_frame_upon_connection_close, false, true, "If trrue, early return before write control frame in OnCanWrite() if the connection is already closed.")
diff --git a/quiche/quic/core/frames/quic_frame.cc b/quiche/quic/core/frames/quic_frame.cc index 8451bb9..dac978e 100644 --- a/quiche/quic/core/frames/quic_frame.cc +++ b/quiche/quic/core/frames/quic_frame.cc
@@ -192,6 +192,15 @@ return false; } +bool HasOnlyDatagramFrame(const QuicFrames& frames) { + for (const QuicFrame& frame : frames) { + if (frame.type != DATAGRAM_FRAME) { + return false; + } + } + return !frames.empty(); +} + bool IsControlFrame(QuicFrameType type) { switch (type) { case RST_STREAM_FRAME:
diff --git a/quiche/quic/core/frames/quic_frame.h b/quiche/quic/core/frames/quic_frame.h index a9eb9d7..37c6bb3 100644 --- a/quiche/quic/core/frames/quic_frame.h +++ b/quiche/quic/core/frames/quic_frame.h
@@ -149,9 +149,12 @@ QUICHE_EXPORT void RemoveFramesForStream(QuicFrames* frames, QuicStreamId stream_id); -// Returns true if |frames| contains at least one message frame. +// Returns true if |frames| contains at least one data frame. QUICHE_EXPORT bool HasDatagramFrame(const QuicFrames& frames); +// Returns true if |frames| contains only data frames. +QUICHE_EXPORT bool HasOnlyDatagramFrame(const QuicFrames& frames); + // Returns true if |type| is a retransmittable control frame. QUICHE_EXPORT bool IsControlFrame(QuicFrameType type);
diff --git a/quiche/quic/core/frames/quic_frames_test.cc b/quiche/quic/core/frames/quic_frames_test.cc index 5f99eff..e85166a 100644 --- a/quiche/quic/core/frames/quic_frames_test.cc +++ b/quiche/quic/core/frames/quic_frames_test.cc
@@ -8,8 +8,10 @@ #include "quiche/quic/core/frames/quic_ack_frame.h" #include "quiche/quic/core/frames/quic_blocked_frame.h" #include "quiche/quic/core/frames/quic_connection_close_frame.h" +#include "quiche/quic/core/frames/quic_datagram_frame.h" #include "quiche/quic/core/frames/quic_frame.h" #include "quiche/quic/core/frames/quic_goaway_frame.h" +#include "quiche/quic/core/frames/quic_handshake_done_frame.h" #include "quiche/quic/core/frames/quic_immediate_ack_frame.h" #include "quiche/quic/core/frames/quic_mtu_discovery_frame.h" #include "quiche/quic/core/frames/quic_new_connection_id_frame.h" @@ -917,6 +919,21 @@ DeleteFrames(&frames); } +TEST_F(QuicFramesTest, HasOnlyDatagramFrame) { + QuicFrames frames; + + EXPECT_FALSE(HasOnlyDatagramFrame(frames)); + + frames.push_back(QuicFrame( + new QuicDatagramFrame(1, quiche::QuicheMemSlice::Copy("datagram")))); + EXPECT_TRUE(HasOnlyDatagramFrame(frames)); + + frames.push_back(QuicFrame(QuicHandshakeDoneFrame())); + EXPECT_FALSE(HasOnlyDatagramFrame(frames)); + + DeleteFrames(&frames); +} + } // namespace } // namespace test } // namespace quic
diff --git a/quiche/quic/core/quic_unacked_packet_map.cc b/quiche/quic/core/quic_unacked_packet_map.cc index 80401dd..12c2837 100644 --- a/quiche/quic/core/quic_unacked_packet_map.cc +++ b/quiche/quic/core/quic_unacked_packet_map.cc
@@ -507,7 +507,17 @@ quiche::SimpleBufferAllocator allocator; std::optional<QuicFrames> frames_copy; const bool use_copied_frames = - !HasDatagramFrame(info->retransmittable_frames); + maybe_copy_datagram_frames_ + ? !HasOnlyDatagramFrame(info->retransmittable_frames) + : !HasDatagramFrame(info->retransmittable_frames); + + if (maybe_copy_datagram_frames_) { + if (use_copied_frames) { + QUIC_RELOADABLE_FLAG_COUNT_N(quic_maybe_copy_datagram_frames, 1, 4); + } else { + QUIC_RELOADABLE_FLAG_COUNT_N(quic_maybe_copy_datagram_frames, 2, 4); + } + } if (use_copied_frames) { frames = &frames_copy.emplace( @@ -552,7 +562,16 @@ quiche::SimpleBufferAllocator allocator; std::optional<QuicFrames> frames_copy; const bool use_copied_frames = - !HasDatagramFrame(info->retransmittable_frames); + maybe_copy_datagram_frames_ + ? !HasOnlyDatagramFrame(info->retransmittable_frames) + : !HasDatagramFrame(info->retransmittable_frames); + if (maybe_copy_datagram_frames_) { + if (use_copied_frames) { + QUIC_RELOADABLE_FLAG_COUNT_N(quic_maybe_copy_datagram_frames, 3, 4); + } else { + QUIC_RELOADABLE_FLAG_COUNT_N(quic_maybe_copy_datagram_frames, 4, 4); + } + } if (use_copied_frames) { frames = &frames_copy.emplace(
diff --git a/quiche/quic/core/quic_unacked_packet_map.h b/quiche/quic/core/quic_unacked_packet_map.h index e37ac3c..9377b6e 100644 --- a/quiche/quic/core/quic_unacked_packet_map.h +++ b/quiche/quic/core/quic_unacked_packet_map.h
@@ -10,11 +10,13 @@ #include "absl/container/inlined_vector.h" #include "absl/strings/str_cat.h" +#include "quiche/quic/core/frames/quic_frame.h" #include "quiche/quic/core/quic_packets.h" #include "quiche/quic/core/quic_transmission_info.h" #include "quiche/quic/core/session_notifier_interface.h" #include "quiche/quic/platform/api/quic_export.h" #include "quiche/quic/platform/api/quic_flags.h" +#include "quiche/common/platform/api/quiche_flags.h" #include "quiche/common/quiche_circular_deque.h" namespace quic { @@ -344,6 +346,9 @@ // Latched value of the quic_simple_inflight_time flag. bool simple_inflight_time_; + + bool maybe_copy_datagram_frames_ = + GetQuicReloadableFlag(quic_maybe_copy_datagram_frames); }; } // namespace quic