gfe-relnote: Let GFE be able to use FIFO write scheduler in QUIC and enable it via a connection option FIFO. Protected by gfe2_reloadable_flag_quic_use_fifo_write_scheduler.
PiperOrigin-RevId: 261676376
Change-Id: I74a4d92ad6d612c565eaa1e38186738988d02fe5
diff --git a/quic/core/crypto/crypto_protocol.h b/quic/core/crypto/crypto_protocol.h
index 81f9730..0facf00 100644
--- a/quic/core/crypto/crypto_protocol.h
+++ b/quic/core/crypto/crypto_protocol.h
@@ -199,6 +199,8 @@
// Enable Priority scheme experiment.
const QuicTag kH2PR = TAG('H', '2', 'P', 'R'); // HTTP2 priorities.
+const QuicTag kFIFO = TAG('F', 'I', 'F', 'O'); // Stream with the smallest ID
+ // has the highest priority.
// Proof types (i.e. certificate types)
// NOTE: although it would be silly to do so, specifying both kX509 and kX59R
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc
index c61c347..2e79f78 100644
--- a/quic/core/http/end_to_end_test.cc
+++ b/quic/core/http/end_to_end_test.cc
@@ -85,11 +85,13 @@
TestParams(const ParsedQuicVersionVector& client_supported_versions,
const ParsedQuicVersionVector& server_supported_versions,
ParsedQuicVersion negotiated_version,
- QuicTag congestion_control_tag)
+ QuicTag congestion_control_tag,
+ QuicTag priority_tag)
: client_supported_versions(client_supported_versions),
server_supported_versions(server_supported_versions),
negotiated_version(negotiated_version),
- congestion_control_tag(congestion_control_tag) {}
+ congestion_control_tag(congestion_control_tag),
+ priority_tag(priority_tag) {}
friend std::ostream& operator<<(std::ostream& os, const TestParams& p) {
os << "{ server_supported_versions: "
@@ -99,7 +101,8 @@
os << " negotiated_version: "
<< ParsedQuicVersionToString(p.negotiated_version);
os << " congestion_control_tag: "
- << QuicTagToString(p.congestion_control_tag) << " }";
+ << QuicTagToString(p.congestion_control_tag);
+ os << " priority_tag: " << QuicTagToString(p.priority_tag) << " }";
return os;
}
@@ -107,6 +110,7 @@
ParsedQuicVersionVector server_supported_versions;
ParsedQuicVersion negotiated_version;
QuicTag congestion_control_tag;
+ QuicTag priority_tag;
};
// Constructs various test permutations.
@@ -153,28 +157,32 @@
if (FilterSupportedVersions(client_versions).empty()) {
continue;
}
- // Add an entry for server and client supporting all versions.
- params.push_back(TestParams(client_versions, all_supported_versions,
- client_versions.front(),
- congestion_control_tag));
+ for (const QuicTag priority_tag :
+ {/*no tag*/ static_cast<QuicTag>(0), kH2PR, kFIFO}) {
+ // Add an entry for server and client supporting all versions.
+ params.push_back(TestParams(client_versions, all_supported_versions,
+ client_versions.front(),
+ congestion_control_tag, priority_tag));
- // Test client supporting all versions and server supporting
- // 1 version. Simulate an old server and exercise version
- // downgrade in the client. Protocol negotiation should
- // occur. Skip the i = 0 case because it is essentially the
- // same as the default case.
- for (size_t i = 1; i < client_versions.size(); ++i) {
- ParsedQuicVersionVector server_supported_versions;
- server_supported_versions.push_back(client_versions[i]);
- if (FilterSupportedVersions(server_supported_versions).empty()) {
- continue;
- }
- params.push_back(TestParams(client_versions, server_supported_versions,
- server_supported_versions.front(),
- congestion_control_tag));
- } // End of inner version loop.
- } // End of outer version loop.
- } // End of congestion_control_tag loop.
+ // Test client supporting all versions and server supporting
+ // 1 version. Simulate an old server and exercise version
+ // downgrade in the client. Protocol negotiation should
+ // occur. Skip the i = 0 case because it is essentially the
+ // same as the default case.
+ for (size_t i = 1; i < client_versions.size(); ++i) {
+ ParsedQuicVersionVector server_supported_versions;
+ server_supported_versions.push_back(client_versions[i]);
+ if (FilterSupportedVersions(server_supported_versions).empty()) {
+ continue;
+ }
+ params.push_back(TestParams(client_versions,
+ server_supported_versions,
+ server_supported_versions.front(),
+ congestion_control_tag, priority_tag));
+ } // End of inner version loop.
+ } // End of priority_tag loop.
+ } // End of outer version loop.
+ } // End of congestion_control_tag loop.
return params;
}
@@ -343,9 +351,7 @@
GetQuicReloadableFlag(quic_enable_pcc3)) {
copt.push_back(kTPCC);
}
- // TODO(fayang): Move this to GetTestParams when other priority connection
- // opts are supported.
- copt.push_back(kH2PR);
+ copt.push_back(GetParam().priority_tag);
client_config_.SetConnectionOptionsToSend(copt);
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index ba53d5e..e39fd41 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -998,12 +998,22 @@
if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFWA)) {
AdjustInitialFlowControlWindows(1024 * 1024);
}
- // Enable HTTP2 (tree-style) priority write scheduler.
if (GetQuicReloadableFlag(quic_use_http2_priority_write_scheduler) &&
ContainsQuicTag(config_.ReceivedConnectionOptions(), kH2PR) &&
!VersionHasIetfQuicFrames(connection_->transport_version())) {
+ // Enable HTTP2 (tree-style) priority write scheduler.
use_http2_priority_write_scheduler_ =
- write_blocked_streams_.UseHttp2PriorityScheduler();
+ write_blocked_streams_.SwitchWriteScheduler(
+ spdy::WriteSchedulerType::HTTP2,
+ connection_->transport_version());
+ } else if (GetQuicReloadableFlag(quic_enable_fifo_write_scheduler) &&
+ ContainsQuicTag(config_.ReceivedConnectionOptions(), kFIFO)) {
+ // Enable FIFO write scheduler.
+ if (write_blocked_streams_.SwitchWriteScheduler(
+ spdy::WriteSchedulerType::FIFO,
+ connection_->transport_version())) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_enable_fifo_write_scheduler);
+ }
}
}
diff --git a/quic/core/quic_write_blocked_list.cc b/quic/core/quic_write_blocked_list.cc
index c9b9c22..8e4bcf1 100644
--- a/quic/core/quic_write_blocked_list.cc
+++ b/quic/core/quic_write_blocked_list.cc
@@ -6,7 +6,6 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
-#include "net/third_party/quiche/src/spdy/core/priority_write_scheduler.h"
namespace quic {
diff --git a/quic/core/quic_write_blocked_list.h b/quic/core/quic_write_blocked_list.h
index 17bc695..dd9ddb4 100644
--- a/quic/core/quic_write_blocked_list.h
+++ b/quic/core/quic_write_blocked_list.h
@@ -14,7 +14,9 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
+#include "net/third_party/quiche/src/spdy/core/fifo_write_scheduler.h"
#include "net/third_party/quiche/src/spdy/core/http2_priority_write_scheduler.h"
+#include "net/third_party/quiche/src/spdy/core/priority_write_scheduler.h"
namespace quic {
@@ -63,20 +65,41 @@
return priority_write_scheduler_->ShouldYield(id);
}
- // Uses HTTP2 (tree-style) priority scheduler. This can only be called before
- // any stream is registered.
- bool UseHttp2PriorityScheduler() {
- if (scheduler_type_ == spdy::WriteSchedulerType::HTTP2) {
+ // Switches write scheduler. This can only be called before any stream is
+ // registered.
+ bool SwitchWriteScheduler(spdy::WriteSchedulerType type,
+ QuicTransportVersion version) {
+ if (scheduler_type_ == type) {
return true;
}
if (priority_write_scheduler_->NumRegisteredStreams() != 0) {
QUIC_BUG << "Cannot switch scheduler with registered streams";
return false;
}
- QUIC_DVLOG(1) << "Using HTTP2 Priority Scheduler";
- priority_write_scheduler_ =
- QuicMakeUnique<spdy::Http2PriorityWriteScheduler<QuicStreamId>>();
- scheduler_type_ = spdy::WriteSchedulerType::HTTP2;
+ QUIC_DVLOG(1) << "Switching to scheduler type: "
+ << spdy::WriteSchedulerTypeToString(type);
+ switch (type) {
+ case spdy::WriteSchedulerType::SPDY:
+ priority_write_scheduler_ =
+ QuicMakeUnique<spdy::PriorityWriteScheduler<QuicStreamId>>(
+ QuicVersionUsesCryptoFrames(version)
+ ? std::numeric_limits<QuicStreamId>::max()
+ : 0);
+ break;
+ case spdy::WriteSchedulerType::HTTP2:
+ priority_write_scheduler_ =
+ QuicMakeUnique<spdy::Http2PriorityWriteScheduler<QuicStreamId>>();
+ break;
+ case spdy::WriteSchedulerType::FIFO:
+ priority_write_scheduler_ =
+ QuicMakeUnique<spdy::FifoWriteScheduler<QuicStreamId>>();
+ break;
+ default:
+ QUIC_BUG << "Scheduler is not supported for type: "
+ << spdy::WriteSchedulerTypeToString(type);
+ return false;
+ }
+ scheduler_type_ = type;
return true;
}
@@ -92,8 +115,8 @@
const auto id_and_precedence =
priority_write_scheduler_->PopNextReadyStreamAndPrecedence();
const QuicStreamId id = std::get<0>(id_and_precedence);
- if (scheduler_type_ == spdy::WriteSchedulerType::HTTP2) {
- // No batch writing logic when using HTTP2 priorities.
+ if (scheduler_type_ != spdy::WriteSchedulerType::SPDY) {
+ // No batch writing logic for non-SPDY priority write scheduler.
return id;
}
const spdy::SpdyPriority priority =
@@ -144,7 +167,7 @@
}
void UpdateBytesForStream(QuicStreamId stream_id, size_t bytes) {
- if (scheduler_type_ == spdy::WriteSchedulerType::HTTP2) {
+ if (scheduler_type_ != spdy::WriteSchedulerType::SPDY) {
return;
}
if (batch_write_stream_id_[last_priority_popped_] == stream_id) {
@@ -185,10 +208,18 @@
private:
bool PrecedenceMatchesSchedulerType(
const spdy::SpdyStreamPrecedence& precedence) {
- if (precedence.is_spdy3_priority()) {
- return scheduler_type_ == spdy::WriteSchedulerType::SPDY;
+ switch (scheduler_type_) {
+ case spdy::WriteSchedulerType::SPDY:
+ return precedence.is_spdy3_priority();
+ case spdy::WriteSchedulerType::HTTP2:
+ return !precedence.is_spdy3_priority();
+ case spdy::WriteSchedulerType::FIFO:
+ break;
+ default:
+ DCHECK(false);
+ return false;
}
- return scheduler_type_ == spdy::WriteSchedulerType::HTTP2;
+ return true;
}
std::unique_ptr<QuicPriorityWriteScheduler> priority_write_scheduler_;
diff --git a/quic/core/quic_write_blocked_list_test.cc b/quic/core/quic_write_blocked_list_test.cc
index ca3433b..5d4b639 100644
--- a/quic/core/quic_write_blocked_list_test.cc
+++ b/quic/core/quic_write_blocked_list_test.cc
@@ -22,7 +22,9 @@
QuicWriteBlockedListTest()
: write_blocked_list_(AllSupportedVersions()[0].transport_version) {
if (GetParam()) {
- write_blocked_list_.UseHttp2PriorityScheduler();
+ write_blocked_list_.SwitchWriteScheduler(
+ spdy::WriteSchedulerType::HTTP2,
+ AllSupportedVersions()[0].transport_version);
}
}