Consult self_issued_connection_id_manager instead of default_path_ for connection ID to look up session in session map.
As a bug fix, gfe2_reloadable_flag_quic_use_active_cid_for_session_lookup is default enabled.
Protected by FLAGS_quic_reloadable_flag_quic_use_active_cid_for_session_lookup.
PiperOrigin-RevId: 389761333
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index 12bf186..0e309e2 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -47,6 +47,7 @@
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_server_stats.h"
#include "quic/platform/api/quic_socket_address.h"
+#include "common/platform/api/quiche_flag_utils.h"
#include "common/quiche_text_utils.h"
namespace quic {
@@ -6872,6 +6873,25 @@
RetirePeerIssuedConnectionIdsNoLongerOnPath();
}
+QuicConnectionId QuicConnection::GetOneActiveServerConnectionId() const {
+ if (perspective_ == Perspective::IS_CLIENT ||
+ self_issued_cid_manager_ == nullptr ||
+ !use_active_cid_for_session_lookup_) {
+ return connection_id();
+ }
+ auto active_connection_ids = GetActiveServerConnectionIds();
+ QUIC_BUG_IF(quic_bug_6944, active_connection_ids.empty());
+ if (active_connection_ids.empty() ||
+ std::find(active_connection_ids.begin(), active_connection_ids.end(),
+ connection_id()) != active_connection_ids.end()) {
+ return connection_id();
+ }
+ QUICHE_CODE_COUNT(connection_id_on_default_path_has_been_retired);
+ auto active_connection_id =
+ self_issued_cid_manager_->GetOneActiveConnectionId();
+ return active_connection_id;
+}
+
std::vector<QuicConnectionId> QuicConnection::GetActiveServerConnectionIds()
const {
if (!support_multiple_connection_ids_ ||
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h
index dea513a..6ed3f5a 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -778,9 +778,12 @@
const QuicSocketAddress& effective_peer_address() const {
return default_path_.peer_address;
}
+
+ // Returns the server connection ID used on the default path.
const QuicConnectionId& connection_id() const {
return default_path_.server_connection_id;
}
+
const QuicConnectionId& client_connection_id() const {
return default_path_.client_connection_id;
}
@@ -1225,6 +1228,12 @@
SendPingAtLevel(framer().GetEncryptionLevelToSendApplicationData());
}
+ // Returns one server connection ID that associates the current session in the
+ // session map.
+ virtual QuicConnectionId GetOneActiveServerConnectionId() const;
+
+ // Returns all server connection IDs that have not been removed from the
+ // session map.
virtual std::vector<QuicConnectionId> GetActiveServerConnectionIds() const;
bool validate_client_address() const { return validate_client_addresses_; }
@@ -1237,6 +1246,10 @@
return connection_migration_use_new_cid_;
}
+ bool use_active_cid_for_session_lookup() const {
+ return use_active_cid_for_session_lookup_;
+ }
+
bool count_bytes_on_alternative_path_separately() const {
return count_bytes_on_alternative_path_separately_;
}
@@ -2279,6 +2292,9 @@
GetQuicReloadableFlag(quic_add_missing_update_ack_timeout);
const bool ack_cid_frames_ = GetQuicReloadableFlag(quic_ack_cid_frames);
+
+ const bool use_active_cid_for_session_lookup_ =
+ GetQuicReloadableFlag(quic_use_active_cid_for_session_lookup);
};
} // namespace quic
diff --git a/quic/core/quic_connection_id_manager.cc b/quic/core/quic_connection_id_manager.cc
index f7089b7..c7e8972 100644
--- a/quic/core/quic_connection_id_manager.cc
+++ b/quic/core/quic_connection_id_manager.cc
@@ -3,12 +3,14 @@
// found in the LICENSE file.
#include "quic/core/quic_connection_id_manager.h"
+
#include <cstdio>
#include "quic/core/quic_clock.h"
#include "quic/core/quic_connection_id.h"
#include "quic/core/quic_error_codes.h"
#include "quic/core/quic_utils.h"
+#include "common/platform/api/quiche_logging.h"
namespace quic {
@@ -372,6 +374,12 @@
return unretired_ids;
}
+QuicConnectionId QuicSelfIssuedConnectionIdManager::GetOneActiveConnectionId()
+ const {
+ QUICHE_DCHECK(!active_connection_ids_.empty());
+ return active_connection_ids_.front().first;
+}
+
void QuicSelfIssuedConnectionIdManager::RetireConnectionId() {
if (to_be_retired_connection_ids_.empty()) {
QUIC_BUG(quic_bug_12420_1)
diff --git a/quic/core/quic_connection_id_manager.h b/quic/core/quic_connection_id_manager.h
index 5e7fc8c..775c016 100644
--- a/quic/core/quic_connection_id_manager.h
+++ b/quic/core/quic_connection_id_manager.h
@@ -139,6 +139,8 @@
std::vector<QuicConnectionId> GetUnretiredConnectionIds() const;
+ QuicConnectionId GetOneActiveConnectionId() const;
+
// Called when the retire_connection_id alarm_ fires. Removes the to be
// retired connection ID locally.
void RetireConnectionId();
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index 6966630..8466ab0 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -826,10 +826,8 @@
level);
}
- void ProcessFramesPacketWithAddresses(QuicFrames frames,
- QuicSocketAddress self_address,
- QuicSocketAddress peer_address,
- EncryptionLevel level) {
+ QuicReceivedPacket ConstructPacket(QuicFrames frames, EncryptionLevel level,
+ char* buffer, size_t buffer_len) {
QUICHE_DCHECK(peer_framer_.HasEncrypterOfEncryptionLevel(level));
peer_creator_.set_encryption_level(level);
QuicPacketCreatorPeer::SetSendVersionInPacket(
@@ -837,14 +835,22 @@
level < ENCRYPTION_FORWARD_SECURE &&
connection_.perspective() == Perspective::IS_SERVER);
- char buffer[kMaxOutgoingPacketSize];
SerializedPacket serialized_packet =
- QuicPacketCreatorPeer::SerializeAllFrames(
- &peer_creator_, frames, buffer, kMaxOutgoingPacketSize);
+ QuicPacketCreatorPeer::SerializeAllFrames(&peer_creator_, frames,
+ buffer, buffer_len);
+ return QuicReceivedPacket(serialized_packet.encrypted_buffer,
+ serialized_packet.encrypted_length, clock_.Now());
+ }
+
+ void ProcessFramesPacketWithAddresses(QuicFrames frames,
+ QuicSocketAddress self_address,
+ QuicSocketAddress peer_address,
+ EncryptionLevel level) {
+ char buffer[kMaxOutgoingPacketSize];
connection_.ProcessUdpPacket(
self_address, peer_address,
- QuicReceivedPacket(serialized_packet.encrypted_buffer,
- serialized_packet.encrypted_length, clock_.Now()));
+ ConstructPacket(std::move(frames), level, buffer,
+ kMaxOutgoingPacketSize));
if (connection_.GetSendAlarm()->IsSet()) {
connection_.GetSendAlarm()->Fire();
}
@@ -14793,11 +14799,13 @@
}
TEST_P(QuicConnectionTest, ServerRetireSelfIssuedConnectionId) {
- if (!version().HasIetfQuicFrames() ||
- !connection_.connection_migration_use_new_cid()) {
+ QuicConfig config;
+ config.SetConnectionOptionsToSend({kRVCM});
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ connection_.SetFromConfig(config);
+ if (!connection_.connection_migration_use_new_cid()) {
return;
}
- QuicConnectionPeer::EnableMultipleConnectionIdSupport(&connection_);
set_perspective(Perspective::IS_SERVER);
connection_.CreateConnectionIdManager();
QuicConnectionId recorded_cid;
@@ -14807,7 +14815,10 @@
QuicConnectionId cid0 = connection_id_;
QuicConnectionId cid1;
QuicConnectionId cid2;
+ EXPECT_EQ(connection_.connection_id(), cid0);
+ EXPECT_EQ(connection_.GetOneActiveServerConnectionId(), cid0);
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
EXPECT_CALL(visitor_, OnServerConnectionIdIssued(_))
.WillOnce(Invoke(cid_recorder));
EXPECT_CALL(visitor_, SendNewConnectionId(_));
@@ -14818,23 +14829,71 @@
connection_.GetRetireSelfIssuedConnectionIdAlarm();
ASSERT_FALSE(retire_self_issued_cid_alarm->IsSet());
- QuicRetireConnectionIdFrame frame;
- frame.sequence_number = 0u;
+ // Generate three packets with different connection IDs that will arrive out
+ // of order (2, 1, 3) later.
+ char buffers[3][kMaxOutgoingPacketSize];
+ // Destination connection ID of packet1 is cid0.
+ auto packet1 =
+ ConstructPacket({QuicFrame(QuicPingFrame())}, ENCRYPTION_FORWARD_SECURE,
+ buffers[0], kMaxOutgoingPacketSize);
+ peer_creator_.SetServerConnectionId(cid1);
+ auto retire_cid_frame = std::make_unique<QuicRetireConnectionIdFrame>();
+ retire_cid_frame->sequence_number = 0u;
+ // Destination connection ID of packet2 is cid1.
+ auto packet2 = ConstructPacket({QuicFrame(retire_cid_frame.release())},
+ ENCRYPTION_FORWARD_SECURE, buffers[1],
+ kMaxOutgoingPacketSize);
+ // Destination connection ID of packet3 is cid1.
+ auto packet3 =
+ ConstructPacket({QuicFrame(QuicPingFrame())}, ENCRYPTION_FORWARD_SECURE,
+ buffers[2], kMaxOutgoingPacketSize);
+
+ // Packet2 with RetireConnectionId frame trigers sending NewConnectionId
+ // immediately.
EXPECT_CALL(visitor_, OnServerConnectionIdIssued(_))
.WillOnce(Invoke(cid_recorder));
- // RetireConnectionId trigers sending NewConnectionId immediately.
EXPECT_CALL(visitor_, SendNewConnectionId(_));
- EXPECT_TRUE(connection_.OnRetireConnectionIdFrame(frame));
+ peer_creator_.SetServerConnectionId(cid1);
+ connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, packet2);
cid2 = recorded_cid;
// cid0 is not retired immediately.
EXPECT_THAT(connection_.GetActiveServerConnectionIds(),
ElementsAre(cid0, cid1, cid2));
ASSERT_TRUE(retire_self_issued_cid_alarm->IsSet());
+ EXPECT_EQ(connection_.connection_id(), cid1);
+ EXPECT_TRUE(connection_.GetOneActiveServerConnectionId() == cid0 ||
+ connection_.GetOneActiveServerConnectionId() == cid1 ||
+ connection_.GetOneActiveServerConnectionId() == cid2);
+
+ // Packet1 updates the connection ID on the default path but not the active
+ // connection ID.
+ connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, packet1);
+ EXPECT_EQ(connection_.connection_id(), cid0);
+ if (connection_.use_active_cid_for_session_lookup()) {
+ EXPECT_TRUE(connection_.GetOneActiveServerConnectionId() == cid0 ||
+ connection_.GetOneActiveServerConnectionId() == cid1 ||
+ connection_.GetOneActiveServerConnectionId() == cid2);
+ } else {
+ EXPECT_EQ(connection_.GetOneActiveServerConnectionId(), cid0);
+ }
+
// cid0 is retired when the retire CID alarm fires.
EXPECT_CALL(visitor_, OnServerConnectionIdRetired(cid0));
retire_self_issued_cid_alarm->Fire();
EXPECT_THAT(connection_.GetActiveServerConnectionIds(),
ElementsAre(cid1, cid2));
+ if (connection_.use_active_cid_for_session_lookup()) {
+ EXPECT_TRUE(connection_.GetOneActiveServerConnectionId() == cid1 ||
+ connection_.GetOneActiveServerConnectionId() == cid2);
+ } else {
+ EXPECT_EQ(connection_.GetOneActiveServerConnectionId(), cid0);
+ }
+
+ // Packet3 updates the connection ID on the default path.
+ connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, packet3);
+ EXPECT_EQ(connection_.connection_id(), cid1);
+ EXPECT_TRUE(connection_.GetOneActiveServerConnectionId() == cid1 ||
+ connection_.GetOneActiveServerConnectionId() == cid2);
}
TEST_P(QuicConnectionTest, PatchMissingClientConnectionIdOntoAlternativePath) {
diff --git a/quic/core/quic_flags_list.h b/quic/core/quic_flags_list.h
index 509b14d..b57fad2 100644
--- a/quic/core/quic_flags_list.h
+++ b/quic/core/quic_flags_list.h
@@ -77,6 +77,8 @@
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_add_stream_info_to_idle_close_detail, true)
// If true, increase the size of stream sequencer buffer block container on demand.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_allocate_stream_sequencer_buffer_blocks_on_demand, false)
+// If true, looks up session to close via connection ID managed by self_issued_connection_id_manager instead of the one on default path.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_use_active_cid_for_session_lookup, true)
// If true, pass the received PATH_RESPONSE payload to path validator to move forward the path validation.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_pass_path_response_to_validator, true)
// If true, quic connection sends/recieives NewConnectionId & RetireConnectionId frames.
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index aef3fc2..193783a 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -444,7 +444,7 @@
closed_streams_clean_up_alarm_->Cancel();
if (visitor_) {
- visitor_->OnConnectionClosed(connection_->connection_id(),
+ visitor_->OnConnectionClosed(connection_->GetOneActiveServerConnectionId(),
frame.quic_error_code, frame.error_details,
source);
}
@@ -2089,7 +2089,7 @@
void QuicSession::OnServerConnectionIdIssued(
const QuicConnectionId& server_connection_id) {
- visitor_->OnNewConnectionIdSent(connection_->connection_id(),
+ visitor_->OnNewConnectionIdSent(connection_->GetOneActiveServerConnectionId(),
server_connection_id);
}