Set client CID in the packets sent by QuicBufferedPacketStore.
Protected by quic_reloadable_flag_quic_buffered_store_set_client_cid.
PiperOrigin-RevId: 700077952
diff --git a/quiche/common/quiche_feature_flags_list.h b/quiche/common/quiche_feature_flags_list.h
index 11b419d..ec1183e 100755
--- a/quiche/common/quiche_feature_flags_list.h
+++ b/quiche/common/quiche_feature_flags_list.h
@@ -17,6 +17,7 @@
QUICHE_FLAG(bool, quiche_reloadable_flag_quic_bbr2_probe_two_rounds, true, true, "When true, the BB2U copt causes BBR2 to wait two rounds with out draining the queue before exiting PROBE_UP and BB2S has the same effect in STARTUP.")
QUICHE_FLAG(bool, quiche_reloadable_flag_quic_bbr2_simplify_inflight_hi, true, true, "When true, the BBHI copt causes QUIC BBRv2 to use a simpler algorithm for raising inflight_hi in PROBE_UP.")
QUICHE_FLAG(bool, quiche_reloadable_flag_quic_block_until_settings_received_copt, true, true, "If enabled and a BSUS connection is received, blocks server connections until SETTINGS frame is received.")
+QUICHE_FLAG(bool, quiche_reloadable_flag_quic_buffered_store_set_client_cid, false, false, "If true, QuicBufferedPacketStore will set client CID in packets it generates.")
QUICHE_FLAG(bool, quiche_reloadable_flag_quic_can_send_ack_frequency, true, true, "If true, ack frequency frame can be sent from server to client.")
QUICHE_FLAG(bool, quiche_reloadable_flag_quic_conservative_bursts, false, false, "If true, set burst token to 2 in cwnd bootstrapping experiment.")
QUICHE_FLAG(bool, quiche_reloadable_flag_quic_conservative_cwnd_and_pacing_gains, false, false, "If true, uses conservative cwnd gain and pacing gain when cwnd gets bootstrapped.")
diff --git a/quiche/quic/core/quic_buffered_packet_store.cc b/quiche/quic/core/quic_buffered_packet_store.cc
index 4421b66..42d00ff 100644
--- a/quiche/quic/core/quic_buffered_packet_store.cc
+++ b/quiche/quic/core/quic_buffered_packet_store.cc
@@ -313,6 +313,11 @@
PacketCollector collector(&send_buffer_allocator);
QuicPacketCreator creator(server_connection_id, &framer, &collector);
+ if (GetQuicReloadableFlag(quic_buffered_store_set_client_cid)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_buffered_store_set_client_cid);
+ creator.SetClientConnectionId(packet_info.source_connection_id);
+ }
+
if (!dispatcher_sent_packets.empty()) {
// Sets the *last sent* packet number, creator will derive the next sending
// packet number accordingly.
diff --git a/quiche/quic/core/quic_buffered_packet_store_test.cc b/quiche/quic/core/quic_buffered_packet_store_test.cc
index 60495dc..d3400f0 100644
--- a/quiche/quic/core/quic_buffered_packet_store_test.cc
+++ b/quiche/quic/core/quic_buffered_packet_store_test.cc
@@ -14,6 +14,9 @@
#include <utility>
#include <vector>
+#include "absl/status/status.h"
+#include "absl/status/statusor.h"
+#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "quiche/quic/core/connection_id_generator.h"
#include "quiche/quic/core/crypto/transport_parameters.h"
@@ -117,13 +120,31 @@
packet_time_(QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(42)),
packet_(packet_content_.data(), packet_content_.size(), packet_time_),
invalid_version_(UnsupportedQuicVersion()),
- valid_version_(CurrentSupportedVersions().front()) {}
+ valid_version_(CurrentSupportedVersions().front()) {
+ store_.set_writer(&mock_packet_writer_);
+
+ EXPECT_CALL(mock_packet_writer_, IsWriteBlocked())
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(mock_packet_writer_, WritePacket(_, _, _, _, _, _))
+ .WillRepeatedly(testing::Invoke(
+ [&](const char* buffer, size_t buf_len, const QuicIpAddress&,
+ const QuicSocketAddress&, PerPacketOptions*,
+ const QuicPacketWriterParams&) {
+ // This packet is sent by the store and "received" by the client.
+ client_received_packets_.push_back(
+ std::make_unique<ClientReceivedPacket>(
+ buffer, buf_len, peer_address_, self_address_));
+ return WriteResult(WRITE_STATUS_OK, buf_len);
+ }));
+ }
protected:
QuicDispatcherStats stats_;
QuicBufferedPacketStoreVisitor visitor_;
MockClock clock_;
MockAlarmFactory alarm_factory_;
+ // Mock the sending of the INITIAL ACK packets.
+ MockPacketWriter mock_packet_writer_;
QuicBufferedPacketStore store_;
QuicSocketAddress self_address_;
QuicSocketAddress peer_address_;
@@ -133,6 +154,35 @@
const ParsedQuicVersion invalid_version_;
const ParsedQuicVersion valid_version_;
MockConnectionIdGenerator connection_id_generator_;
+
+ // A packet that is sent by the store and "received" by the client.
+ struct ClientReceivedPacket {
+ ClientReceivedPacket(const char* buffer, size_t buf_len,
+ const QuicSocketAddress& client_address,
+ const QuicSocketAddress& server_address)
+ : self_address(client_address),
+ peer_address(server_address),
+ packet(QuicReceivedPacket(buffer, buf_len, QuicTime::Zero()).Clone()),
+ packet_info(self_address, peer_address, *packet) {
+ std::string detailed_error;
+ MockConnectionIdGenerator unused_generator;
+ if (QuicFramer::ParsePublicHeaderDispatcherShortHeaderLengthUnknown(
+ *packet, &packet_info.form, &packet_info.long_packet_type,
+ &packet_info.version_flag, &packet_info.use_length_prefix,
+ &packet_info.version_label, &packet_info.version,
+ &packet_info.destination_connection_id,
+ &packet_info.source_connection_id, &packet_info.retry_token,
+ &detailed_error, unused_generator) != QUIC_NO_ERROR) {
+ ADD_FAILURE() << "Failed to parse packet header: " << detailed_error;
+ }
+ }
+
+ const QuicSocketAddress self_address;
+ const QuicSocketAddress peer_address;
+ std::unique_ptr<QuicReceivedPacket> packet;
+ ReceivedPacketInfo packet_info;
+ };
+ std::vector<std::unique_ptr<ClientReceivedPacket>> client_received_packets_;
};
TEST_F(QuicBufferedPacketStoreTest, SimpleEnqueueAndDeliverPacket) {
@@ -837,6 +887,49 @@
}
}
+TEST_F(QuicBufferedPacketStoreTest, InitialAckHasClientConnectionId) {
+ const QuicConnectionId kDCID = TestConnectionId(1);
+ const QuicConnectionId kSCID = TestConnectionId(42);
+ const std::string crypto_data = "crypto_data";
+ ParsedQuicVersionVector versions = {ParsedQuicVersion::RFCv1()};
+ std::unique_ptr<QuicEncryptedPacket> client_initial_packet(
+ ConstructEncryptedPacket(
+ kDCID, kSCID, /*version_flag=*/true, /*reset_flag=*/false,
+ /*packet_number=*/1, crypto_data, /*full_padding=*/true,
+ CONNECTION_ID_PRESENT, CONNECTION_ID_PRESENT,
+ PACKET_4BYTE_PACKET_NUMBER, &versions, Perspective::IS_CLIENT));
+
+ QuicReceivedPacket received_client_initial(client_initial_packet->data(),
+ client_initial_packet->length(),
+ QuicTime::Zero());
+ ReceivedPacketInfo packet_info(self_address_, peer_address_,
+ received_client_initial);
+ std::string detailed_error;
+ ASSERT_EQ(QuicFramer::ParsePublicHeaderDispatcherShortHeaderLengthUnknown(
+ received_client_initial, &packet_info.form,
+ &packet_info.long_packet_type, &packet_info.version_flag,
+ &packet_info.use_length_prefix, &packet_info.version_label,
+ &packet_info.version, &packet_info.destination_connection_id,
+ &packet_info.source_connection_id, &packet_info.retry_token,
+ &detailed_error, connection_id_generator_),
+ QUIC_NO_ERROR)
+ << detailed_error;
+ store_.EnqueuePacket(packet_info, kNoParsedChlo, connection_id_generator_);
+ ASSERT_EQ(client_received_packets_.size(), 1u);
+
+ const ReceivedPacketInfo& client_received_packet_info =
+ client_received_packets_[0]->packet_info;
+ // From the client's perspective, the destination connection ID is kSCID and
+ // the source connection ID is kDCID.
+ if (GetQuicReloadableFlag(quic_buffered_store_set_client_cid)) {
+ EXPECT_EQ(client_received_packet_info.destination_connection_id, kSCID);
+ } else {
+ EXPECT_EQ(client_received_packet_info.destination_connection_id,
+ EmptyQuicConnectionId());
+ }
+ EXPECT_EQ(client_received_packet_info.source_connection_id, kDCID);
+}
+
TEST_F(QuicBufferedPacketStoreTest, EmptyBufferedPacketList) {
BufferedPacketList packet_list;
EXPECT_TRUE(packet_list.buffered_packets.empty());