gfe-relnote: Close QUIC connection is there are too many (> 1000) buffered control frames in control frame manager. Protected by gfe2_reloadable_flag_quic_add_upper_limit_of_buffered_control_frames.
PiperOrigin-RevId: 261002263
Change-Id: I4dd92d5c1ea159d05cf35719f1a7ccc36f7b3fd3
diff --git a/quic/core/quic_control_frame_manager.cc b/quic/core/quic_control_frame_manager.cc
index 511ef2b..ac4488b 100644
--- a/quic/core/quic_control_frame_manager.cc
+++ b/quic/core/quic_control_frame_manager.cc
@@ -14,11 +14,25 @@
namespace quic {
+namespace {
+
+// The maximum number of buffered control frames which are waiting to be ACKed
+// or sent for the first time.
+const size_t kMaxNumControlFrames = 1000;
+
+} // namespace
+
QuicControlFrameManager::QuicControlFrameManager(QuicSession* session)
: last_control_frame_id_(kInvalidControlFrameId),
least_unacked_(1),
least_unsent_(1),
- session_(session) {}
+ session_(session),
+ add_upper_limit_(GetQuicReloadableFlag(
+ quic_add_upper_limit_of_buffered_control_frames)) {
+ if (add_upper_limit_) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_add_upper_limit_of_buffered_control_frames);
+ }
+}
QuicControlFrameManager::~QuicControlFrameManager() {
while (!control_frames_.empty()) {
@@ -30,6 +44,15 @@
void QuicControlFrameManager::WriteOrBufferQuicFrame(QuicFrame frame) {
const bool had_buffered_frames = HasBufferedFrames();
control_frames_.emplace_back(frame);
+ if (add_upper_limit_ && control_frames_.size() > kMaxNumControlFrames) {
+ session_->connection()->CloseConnection(
+ QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES,
+ QuicStrCat("More than ", kMaxNumControlFrames,
+ "buffered control frames, least_unacked: ", least_unacked_,
+ ", least_unsent_: ", least_unsent_),
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
+ }
if (had_buffered_frames) {
return;
}
@@ -101,6 +124,15 @@
}
control_frames_.emplace_back(
QuicFrame(QuicPingFrame(++last_control_frame_id_)));
+ if (add_upper_limit_ && control_frames_.size() > kMaxNumControlFrames) {
+ session_->connection()->CloseConnection(
+ QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES,
+ QuicStrCat("More than ", kMaxNumControlFrames,
+ "buffered control frames, least_unacked: ", least_unacked_,
+ ", least_unsent_: ", least_unsent_),
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
+ }
WriteBufferedFrames();
}
@@ -172,6 +204,9 @@
}
if (!QuicContainsKey(pending_retransmissions_, id)) {
pending_retransmissions_[id] = true;
+ QUIC_BUG_IF(pending_retransmissions_.size() > control_frames_.size())
+ << "least_unacked_: " << least_unacked_
+ << ", least_unsent_: " << least_unsent_;
}
}