For loss detection tuning, if user agent is available, save it into quicsession. protected by --gfe2_reloadable_flag_quic_save_user_agent_in_quic_session.
PiperOrigin-RevId: 316688269
Change-Id: I2a25beeb081b38ae204a62c14459427341efa5e0
diff --git a/quic/core/congestion_control/general_loss_algorithm.h b/quic/core/congestion_control/general_loss_algorithm.h
index ee8ba64..950831e 100644
--- a/quic/core/congestion_control/general_loss_algorithm.h
+++ b/quic/core/congestion_control/general_loss_algorithm.h
@@ -58,6 +58,11 @@
<< "Unexpected call to GeneralLossAlgorithm::OnMinRttAvailable";
}
+ void OnUserAgentIdKnown() override {
+ DCHECK(false)
+ << "Unexpected call to GeneralLossAlgorithm::OnUserAgentIdKnown";
+ }
+
void OnConnectionClosed() override {
DCHECK(false)
<< "Unexpected call to GeneralLossAlgorithm::OnConnectionClosed";
diff --git a/quic/core/congestion_control/loss_detection_interface.h b/quic/core/congestion_control/loss_detection_interface.h
index cd2bd72..d5e0190 100644
--- a/quic/core/congestion_control/loss_detection_interface.h
+++ b/quic/core/congestion_control/loss_detection_interface.h
@@ -57,6 +57,8 @@
virtual void OnMinRttAvailable() = 0;
+ virtual void OnUserAgentIdKnown() = 0;
+
virtual void OnConnectionClosed() = 0;
};
diff --git a/quic/core/congestion_control/uber_loss_algorithm.cc b/quic/core/congestion_control/uber_loss_algorithm.cc
index 28463cb..243f563 100644
--- a/quic/core/congestion_control/uber_loss_algorithm.cc
+++ b/quic/core/congestion_control/uber_loss_algorithm.cc
@@ -98,7 +98,8 @@
}
void UberLossAlgorithm::MaybeStartTuning() {
- if (tuner_started_ || !tuning_enabled_ || !min_rtt_available_) {
+ if (tuner_started_ || !tuning_enabled_ || !min_rtt_available_ ||
+ !user_agent_known_) {
return;
}
@@ -127,6 +128,11 @@
MaybeStartTuning();
}
+void UberLossAlgorithm::OnUserAgentIdKnown() {
+ user_agent_known_ = true;
+ MaybeStartTuning();
+}
+
void UberLossAlgorithm::OnConnectionClosed() {
if (tuner_ != nullptr && tuner_started_) {
tuner_->Finish(tuned_parameters_);
diff --git a/quic/core/congestion_control/uber_loss_algorithm.h b/quic/core/congestion_control/uber_loss_algorithm.h
index 7dacb66..0d1453c 100644
--- a/quic/core/congestion_control/uber_loss_algorithm.h
+++ b/quic/core/congestion_control/uber_loss_algorithm.h
@@ -7,6 +7,7 @@
#include "net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h"
namespace quic {
@@ -72,6 +73,7 @@
std::unique_ptr<LossDetectionTunerInterface> tuner);
void OnConfigNegotiated() override;
void OnMinRttAvailable() override;
+ void OnUserAgentIdKnown() override;
void OnConnectionClosed() override;
// Sets reordering_shift for all packet number spaces.
@@ -125,6 +127,10 @@
LossDetectionParameters tuned_parameters_;
bool tuner_started_ = false;
bool min_rtt_available_ = false;
+ // If flag is false, set |user_agent_known_| to true, so loss detection tuner
+ // will start once SetFromConfig is called and min rtt is available.
+ bool user_agent_known_ =
+ !GetQuicReloadableFlag(quic_save_user_agent_in_quic_session);
bool tuning_enabled_ = false; // Whether tuning is enabled by config.
};
diff --git a/quic/core/congestion_control/uber_loss_algorithm_test.cc b/quic/core/congestion_control/uber_loss_algorithm_test.cc
index 318e730..e663540 100644
--- a/quic/core/congestion_control/uber_loss_algorithm_test.cc
+++ b/quic/core/congestion_control/uber_loss_algorithm_test.cc
@@ -239,6 +239,8 @@
const QuicPacketCount old_reordering_threshold =
loss_algorithm_.GetPacketReorderingThreshold();
+ loss_algorithm_.OnUserAgentIdKnown();
+
// Not owned.
TestLossTuner* test_tuner = new TestLossTuner(
/*forced_start_result=*/true,
@@ -275,6 +277,8 @@
const QuicPacketCount old_reordering_threshold =
loss_algorithm_.GetPacketReorderingThreshold();
+ loss_algorithm_.OnUserAgentIdKnown();
+
// Not owned.
TestLossTuner* test_tuner = new TestLossTuner(
/*forced_start_result=*/true,
@@ -309,6 +313,8 @@
const QuicPacketCount old_reordering_threshold =
loss_algorithm_.GetPacketReorderingThreshold();
+ loss_algorithm_.OnUserAgentIdKnown();
+
// Not owned.
TestLossTuner* test_tuner = new TestLossTuner(
/*forced_start_result=*/false,
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc
index abe9399..1be5ad6 100644
--- a/quic/core/http/end_to_end_test.cc
+++ b/quic/core/http/end_to_end_test.cc
@@ -83,6 +83,7 @@
const char kFooResponseBody[] = "Artichoke hearts make me happy.";
const char kBarResponseBody[] = "Palm hearts are pretty delicious, also.";
+const char kTestUserAgentId[] = "quic/core/http/end_to_end_test.cc";
const float kSessionToStreamRatio = 1.5;
// Run all tests with the cross products of all versions.
@@ -217,6 +218,7 @@
client_supported_versions_,
crypto_test_utils::ProofVerifierForTesting(),
std::make_unique<SimpleSessionCache>());
+ client->SetUserAgentID(kTestUserAgentId);
client->UseWriter(writer);
if (!pre_shared_key_client_.empty()) {
client->client()->SetPreSharedKey(pre_shared_key_client_);
@@ -454,6 +456,13 @@
EXPECT_EQ(0u, server_stats.packets_lost);
}
EXPECT_EQ(0u, server_stats.packets_discarded);
+ if (GetQuicReloadableFlag(quic_save_user_agent_in_quic_session)) {
+ EXPECT_EQ(
+ GetServerSession()->user_agent_id().value_or("MissingUserAgent"),
+ kTestUserAgentId);
+ } else {
+ EXPECT_FALSE(GetServerSession()->user_agent_id().has_value());
+ }
// TODO(ianswett): Restore the check for packets_dropped equals 0.
// The expect for packets received is equal to packets processed fails
// due to version negotiation packets.
@@ -4283,6 +4292,12 @@
server_thread_->Pause();
QuicConfig server_config = *GetServerSession()->config();
+ if (GetQuicReloadableFlag(quic_save_user_agent_in_quic_session)) {
+ EXPECT_EQ(GetServerSession()->user_agent_id().value_or("MissingUserAgent"),
+ kTestUserAgentId);
+ } else {
+ EXPECT_FALSE(GetServerSession()->user_agent_id().has_value());
+ }
server_thread_->Resume();
ASSERT_NE(server_config.received_custom_transport_parameters().find(
kCustomParameter),
diff --git a/quic/core/http/http_constants.h b/quic/core/http/http_constants.h
index 17afe1b..285d379 100644
--- a/quic/core/http/http_constants.h
+++ b/quic/core/http/http_constants.h
@@ -42,6 +42,7 @@
// SETTINGS_QPACK_BLOCKED_STREAMS.
const uint64_t kDefaultMaximumBlockedStreams = 100;
+const char kUserAgentHeaderName[] = "user-agent";
} // namespace quic
#endif // QUICHE_QUIC_CORE_HTTP_HTTP_CONSTANTS_H_
diff --git a/quic/core/http/quic_spdy_stream.cc b/quic/core/http/quic_spdy_stream.cc
index 51f7c5c..4c979c1 100644
--- a/quic/core/http/quic_spdy_stream.cc
+++ b/quic/core/http/quic_spdy_stream.cc
@@ -529,6 +529,21 @@
void QuicSpdyStream::OnStreamHeaderList(bool fin,
size_t frame_len,
const QuicHeaderList& header_list) {
+ if (GetQuicReloadableFlag(quic_save_user_agent_in_quic_session)) {
+ if (!spdy_session()->user_agent_id().has_value()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_save_user_agent_in_quic_session, 3, 3);
+ std::string uaid;
+ for (const auto& kv : header_list) {
+ if (quiche::QuicheTextUtils::ToLower(kv.first) ==
+ kUserAgentHeaderName) {
+ uaid = kv.second;
+ break;
+ }
+ }
+ spdy_session()->SetUserAgentId(std::move(uaid));
+ }
+ }
+
// TODO(b/134706391): remove |fin| argument.
// When using Google QUIC, an empty header list indicates that the size limit
// has been exceeded.
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h
index 7339b57..5cc257d 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -980,6 +980,8 @@
return anti_amplification_factor_;
}
+ void OnUserAgentIdKnown() { sent_packet_manager_.OnUserAgentIdKnown(); }
+
protected:
// Calls cancel() on all the alarms owned by this connection.
void CancelAllAlarms();
diff --git a/quic/core/quic_crypto_server_stream.cc b/quic/core/quic_crypto_server_stream.cc
index b21745c..6c84067 100644
--- a/quic/core/quic_crypto_server_stream.cc
+++ b/quic/core/quic_crypto_server_stream.cc
@@ -8,6 +8,7 @@
#include <string>
#include "third_party/boringssl/src/include/openssl/sha.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
@@ -400,6 +401,17 @@
nullptr);
return;
}
+
+ if (GetQuicReloadableFlag(quic_save_user_agent_in_quic_session)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_save_user_agent_in_quic_session, 1, 3);
+ quiche::QuicheStringPiece user_agent_id;
+ message.GetStringPiece(quic::kUAID, &user_agent_id);
+ if (!session()->user_agent_id().has_value()) {
+ std::string uaid = user_agent_id.empty() ? "" : user_agent_id.data();
+ session()->SetUserAgentId(std::move(uaid));
+ }
+ }
+
if (!result->info.server_nonce.empty()) {
++num_handshake_messages_with_server_nonces_;
}
diff --git a/quic/core/quic_sent_packet_manager.h b/quic/core/quic_sent_packet_manager.h
index ce8353d..b0a8352 100644
--- a/quic/core/quic_sent_packet_manager.h
+++ b/quic/core/quic_sent_packet_manager.h
@@ -408,6 +408,8 @@
bool one_rtt_packet_acked() const { return one_rtt_packet_acked_; }
+ void OnUserAgentIdKnown() { loss_algorithm_->OnUserAgentIdKnown(); }
+
private:
friend class test::QuicConnectionPeer;
friend class test::QuicSentPacketManagerPeer;
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h
index 81ba099..8328782 100644
--- a/quic/core/quic_session.h
+++ b/quic/core/quic_session.h
@@ -33,6 +33,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -473,6 +474,15 @@
return true;
}
+ const quiche::QuicheOptional<std::string> user_agent_id() const {
+ return user_agent_id_;
+ }
+
+ void SetUserAgentId(std::string user_agent_id) {
+ user_agent_id_ = std::move(user_agent_id);
+ connection()->OnUserAgentIdKnown();
+ }
+
protected:
using StreamMap = QuicSmallMap<QuicStreamId, std::unique_ptr<QuicStream>, 10>;
@@ -791,6 +801,8 @@
// list may be a superset of the connection framer's supported versions.
ParsedQuicVersionVector supported_versions_;
+ quiche::QuicheOptional<std::string> user_agent_id_;
+
// If true, write_blocked_streams_ uses HTTP2 (tree-style) priority write
// scheduler.
bool use_http2_priority_write_scheduler_;
diff --git a/quic/core/tls_server_handshaker.cc b/quic/core/tls_server_handshaker.cc
index 057e86d..84ad6e1 100644
--- a/quic/core/tls_server_handshaker.cc
+++ b/quic/core/tls_server_handshaker.cc
@@ -299,6 +299,20 @@
return false;
}
ProcessAdditionalTransportParameters(client_params);
+ if (GetQuicReloadableFlag(quic_save_user_agent_in_quic_session) &&
+ !session()->user_agent_id().has_value()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_save_user_agent_in_quic_session, 2, 3);
+
+ if (client_params.user_agent_id.has_value()) {
+ session()->SetUserAgentId(client_params.user_agent_id.value());
+ } else if (client_params.google_quic_params) {
+ quiche::QuicheStringPiece user_agent_id;
+ client_params.google_quic_params->GetStringPiece(kUAID, &user_agent_id);
+ if (!user_agent_id.empty()) {
+ session()->SetUserAgentId(user_agent_id.data());
+ }
+ }
+ }
return true;
}
diff --git a/quic/test_tools/quic_test_utils.h b/quic/test_tools/quic_test_utils.h
index 839bb56..686ea3a 100644
--- a/quic/test_tools/quic_test_utils.h
+++ b/quic/test_tools/quic_test_utils.h
@@ -1292,6 +1292,7 @@
MOCK_METHOD(void, OnConfigNegotiated, (), (override));
MOCK_METHOD(void, OnMinRttAvailable, (), (override));
+ MOCK_METHOD(void, OnUserAgentIdKnown, (), (override));
MOCK_METHOD(void, OnConnectionClosed, (), (override));
};