Make QuicConnection generate a new flow label when flow label based
black hole avoidance is enabled, and added CODE_COUNTS for when the
flow label changes
PiperOrigin-RevId: 686993723
diff --git a/quiche/quic/core/quic_connection.cc b/quiche/quic/core/quic_connection.cc
index d6e2fa1..72bf8c9 100644
--- a/quiche/quic/core/quic_connection.cc
+++ b/quiche/quic/core/quic_connection.cc
@@ -1174,13 +1174,13 @@
last_flow_label_received_) {
if (expect_peer_flow_label_change_) {
expect_peer_flow_label_change_ = false;
+ QUIC_CODE_COUNT(quic_detected_expected_flow_label_change);
} else if (header.packet_number > GetLargestReceivedPacket() + 1) {
// This packet introduced a packet number gap and came with a new flow
// label so the peer is RTO'ing. In response, send a different flow
// label.
- uint32_t flow_label;
- random_generator_->RandBytes(&flow_label, sizeof(flow_label));
- set_outgoing_flow_label(flow_label);
+ GenerateNewOutgoingFlowLabel();
+ QUIC_CODE_COUNT(quic_generated_new_flow_label_on_flow_label_change);
}
last_flow_label_received_ = last_received_packet_info_.flow_label;
}
@@ -2926,6 +2926,12 @@
return direct_peer_address_ != last_received_packet_info_.source_address;
}
+void QuicConnection::GenerateNewOutgoingFlowLabel() {
+ uint32_t flow_label;
+ random_generator_->RandBytes(&flow_label, sizeof(flow_label));
+ set_outgoing_flow_label(flow_label);
+}
+
bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
if (perspective_ == Perspective::IS_CLIENT && version().HasIetfQuicFrames() &&
direct_peer_address_.IsInitialized() &&
@@ -4198,10 +4204,9 @@
clock_->Now());
}
if (enable_black_hole_avoidance_via_flow_label_) {
- uint32_t flow_label;
- random_generator_->RandBytes(&flow_label, sizeof(flow_label));
- set_outgoing_flow_label(flow_label);
+ GenerateNewOutgoingFlowLabel();
expect_peer_flow_label_change_ = true;
+ QUIC_CODE_COUNT(quic_generated_new_flow_label_on_pto);
}
}
if (default_enable_5rto_blackhole_detection_ &&
diff --git a/quiche/quic/core/quic_connection.h b/quiche/quic/core/quic_connection.h
index be9bcb6..693873b 100644
--- a/quiche/quic/core/quic_connection.h
+++ b/quiche/quic/core/quic_connection.h
@@ -1449,7 +1449,9 @@
}
void EnableBlackholeAvoidanceViaFlowLabel() {
+ GenerateNewOutgoingFlowLabel();
enable_black_hole_avoidance_via_flow_label_ = true;
+ QUIC_CODE_COUNT(quic_black_hole_avoidance_via_flow_label_enabled);
}
bool enable_black_hole_avoidance_via_flow_label() const {
@@ -2149,6 +2151,8 @@
bool PeerAddressChanged() const;
+ void GenerateNewOutgoingFlowLabel();
+
QuicAlarm& ack_alarm() { return alarms_.ack_alarm(); }
const QuicAlarm& ack_alarm() const { return alarms_.ack_alarm(); }
QuicAlarm& retransmission_alarm() { return alarms_.retransmission_alarm(); }
diff --git a/quiche/quic/core/quic_connection_test.cc b/quiche/quic/core/quic_connection_test.cc
index 8d36e98..6aa7ef3 100644
--- a/quiche/quic/core/quic_connection_test.cc
+++ b/quiche/quic/core/quic_connection_test.cc
@@ -9996,8 +9996,11 @@
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
connection_.SetFromConfig(config);
EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
- connection_.set_outgoing_flow_label(1);
+ EXPECT_EQ(0, connection_.outgoing_flow_label());
connection_.EnableBlackholeAvoidanceViaFlowLabel();
+ static_cast<test::MockRandom*>(helper_->GetRandomGenerator())->ChangeValue();
+ const uint32_t flow_label = connection_.outgoing_flow_label();
+ EXPECT_NE(0, flow_label);
QuicStreamId stream_id = 2;
QuicPacketNumber last_packet;
@@ -10009,7 +10012,7 @@
// Fire PTO and verify the flow label has changed.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
connection_.GetRetransmissionAlarm()->Fire();
- EXPECT_NE(1, connection_.outgoing_flow_label());
+ EXPECT_NE(flow_label, connection_.outgoing_flow_label());
}
TEST_P(QuicConnectionTest, NewReceiveNewFlowLabelWithGapChangesFlowLabel) {
@@ -10020,21 +10023,24 @@
config.SetConnectionOptionsToSend(connection_options);
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
connection_.SetFromConfig(config);
+ EXPECT_EQ(0, connection_.outgoing_flow_label());
connection_.EnableBlackholeAvoidanceViaFlowLabel();
- const uint32_t flow_label = 1;
- connection_.set_outgoing_flow_label(flow_label);
+ static_cast<test::MockRandom*>(helper_->GetRandomGenerator())->ChangeValue();
+ const uint32_t flow_label = connection_.outgoing_flow_label();
+ EXPECT_NE(0, flow_label);
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
// Receive the first packet to initialize the flow label.
ProcessDataPacketAtLevel(1, !kHasStopWaiting, ENCRYPTION_INITIAL, 0);
- EXPECT_EQ(1, connection_.outgoing_flow_label());
+ EXPECT_EQ(flow_label, connection_.outgoing_flow_label());
// Receive the second packet with the same flow label
ProcessDataPacketAtLevel(2, !kHasStopWaiting, ENCRYPTION_INITIAL, flow_label);
- EXPECT_EQ(1, connection_.outgoing_flow_label());
+ EXPECT_EQ(flow_label, connection_.outgoing_flow_label());
// Receive a packet with gap and a new flow label and verify the outgoing
// flow label has changed.
+ static_cast<test::MockRandom*>(helper_->GetRandomGenerator())->ChangeValue();
ProcessDataPacketAtLevel(4, !kHasStopWaiting, ENCRYPTION_INITIAL,
flow_label + 1);
EXPECT_NE(flow_label, connection_.outgoing_flow_label());
@@ -10049,18 +10055,20 @@
config.SetConnectionOptionsToSend(connection_options);
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
connection_.SetFromConfig(config);
+ EXPECT_EQ(0, connection_.outgoing_flow_label());
connection_.EnableBlackholeAvoidanceViaFlowLabel();
- const uint32_t flow_label = 1;
- connection_.set_outgoing_flow_label(flow_label);
+ static_cast<test::MockRandom*>(helper_->GetRandomGenerator())->ChangeValue();
+ const uint32_t flow_label = connection_.outgoing_flow_label();
+ EXPECT_NE(0, flow_label);
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
// Receive the first packet to initialize the flow label.
ProcessDataPacketAtLevel(1, !kHasStopWaiting, ENCRYPTION_INITIAL, 0);
- EXPECT_EQ(1, connection_.outgoing_flow_label());
+ EXPECT_EQ(flow_label, connection_.outgoing_flow_label());
// Receive the second packet with the same flow label
ProcessDataPacketAtLevel(2, !kHasStopWaiting, ENCRYPTION_INITIAL, flow_label);
- EXPECT_EQ(1, connection_.outgoing_flow_label());
+ EXPECT_EQ(flow_label, connection_.outgoing_flow_label());
// Receive a packet with no gap and a new flow label and verify the outgoing
// flow label has not changed.