Add a callback to notify QuicSession whenever a new RTT sample is available. PiperOrigin-RevId: 933690522
diff --git a/quiche/quic/core/quic_connection.cc b/quiche/quic/core/quic_connection.cc index 26e3eb4..36c2ca0 100644 --- a/quiche/quic/core/quic_connection.cc +++ b/quiche/quic/core/quic_connection.cc
@@ -4212,6 +4212,10 @@ packet_writer_params_.ecn_codepoint = ECN_NOT_ECT; } +void QuicConnection::OnRttSampleAvailable(const QuicRttSample& rtt_sample) { + visitor_->OnRttSampleAvailable(rtt_sample); +} + std::unique_ptr<QuicSelfIssuedConnectionIdManager> QuicConnection::MakeSelfIssuedConnectionIdManager() { QUICHE_DCHECK((perspective_ == Perspective::IS_CLIENT &&
diff --git a/quiche/quic/core/quic_connection.h b/quiche/quic/core/quic_connection.h index c0b27ad..b1816fc 100644 --- a/quiche/quic/core/quic_connection.h +++ b/quiche/quic/core/quic_connection.h
@@ -186,6 +186,9 @@ // Called when the connection receives a packet from a migrated client. virtual void OnConnectionMigration(AddressChangeType type) = 0; + // Called when a new RTT sample is available. + virtual void OnRttSampleAvailable(const QuicRttSample& rtt_sample) = 0; + // Called when the peer seems unreachable over the current path. virtual void OnPathDegrading() = 0; @@ -835,6 +838,7 @@ void OnPathMtuIncreased(QuicPacketLength packet_size) override; void OnInFlightEcnPacketAcked() override; void OnInvalidEcnFeedback() override; + void OnRttSampleAvailable(const QuicRttSample& rtt_sample) override; // QuicNetworkBlackholeDetector::Delegate void OnPathDegradingDetected() override;
diff --git a/quiche/quic/core/quic_connection_test.cc b/quiche/quic/core/quic_connection_test.cc index 0d66c4f..1f28529 100644 --- a/quiche/quic/core/quic_connection_test.cc +++ b/quiche/quic/core/quic_connection_test.cc
@@ -697,6 +697,7 @@ EXPECT_CALL(visitor_, ShouldKeepConnectionAlive()) .WillRepeatedly(Return(false)); EXPECT_CALL(visitor_, OnCongestionWindowChange(_)).Times(AnyNumber()); + EXPECT_CALL(visitor_, OnRttSampleAvailable).Times(AnyNumber()); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)).Times(AnyNumber()); EXPECT_CALL(visitor_, MaybeBundleOpportunistically()).Times(AnyNumber()); EXPECT_CALL(visitor_, GetFlowControlSendWindowSize(_)).Times(AnyNumber());
diff --git a/quiche/quic/core/quic_sent_packet_manager.cc b/quiche/quic/core/quic_sent_packet_manager.cc index 6b731f0..41ad223 100644 --- a/quiche/quic/core/quic_sent_packet_manager.cc +++ b/quiche/quic/core/quic_sent_packet_manager.cc
@@ -1065,7 +1065,12 @@ QuicTime::Delta send_delta = ack_receive_time - transmission_info.sent_time; const bool min_rtt_available = !rtt_stats_.min_rtt().IsZero(); - rtt_stats_.UpdateRtt(send_delta, ack_delay_time, ack_receive_time); + const bool rtt_updated = + rtt_stats_.UpdateRtt(send_delta, ack_delay_time, ack_receive_time); + if (rtt_updated && network_change_visitor_ != nullptr) { + network_change_visitor_->OnRttSampleAvailable( + QuicRttSample{.latest_rtt = rtt_stats_.latest_rtt()}); + } if (!min_rtt_available && !rtt_stats_.min_rtt().IsZero()) { loss_algorithm_->OnMinRttAvailable();
diff --git a/quiche/quic/core/quic_sent_packet_manager.h b/quiche/quic/core/quic_sent_packet_manager.h index 42d9e32..a007eba 100644 --- a/quiche/quic/core/quic_sent_packet_manager.h +++ b/quiche/quic/core/quic_sent_packet_manager.h
@@ -119,6 +119,9 @@ // Called when an ACK frame with ECN counts has invalid values, or an ACK // acknowledges packets with ECN marks and there are no ECN counts. virtual void OnInvalidEcnFeedback() = 0; + + // Called when a new RTT sample is available. + virtual void OnRttSampleAvailable(const QuicRttSample& rtt_sample) = 0; }; // The retransmission timer is a single timer which switches modes depending
diff --git a/quiche/quic/core/quic_sent_packet_manager_test.cc b/quiche/quic/core/quic_sent_packet_manager_test.cc index d0d3c22..1d04fc3 100644 --- a/quiche/quic/core/quic_sent_packet_manager_test.cc +++ b/quiche/quic/core/quic_sent_packet_manager_test.cc
@@ -146,6 +146,8 @@ EXPECT_CALL(*send_algorithm_, OnPacketNeutered(_)).Times(AnyNumber()); EXPECT_CALL(*network_change_visitor_, OnPathMtuIncreased(1000)) .Times(AnyNumber()); + EXPECT_CALL(*network_change_visitor_, OnRttSampleAvailable) + .Times(AnyNumber()); EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(true)); EXPECT_CALL(notifier_, HasUnackedCryptoData()) .WillRepeatedly(Return(false)); @@ -775,6 +777,22 @@ EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt()); } +TEST_F(QuicSentPacketManagerTest, OnRttSampleAvailable) { + const QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(20); + SendDataPacket(1); + clock_.AdvanceTime(expected_rtt); + const QuicTime::Delta ack_delay = QuicTime::Delta::FromMilliseconds(5); + + ExpectAck(1); + EXPECT_CALL(*network_change_visitor_, + OnRttSampleAvailable(QuicRttSample{expected_rtt})); + manager_.OnAckFrameStart(QuicPacketNumber(1), ack_delay, clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); + EXPECT_EQ(PACKETS_NEWLY_ACKED, + manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1), + ENCRYPTION_INITIAL, kEmptyCounts)); +} + TEST_F(QuicSentPacketManagerTest, RttWithInvalidDelta) { // Expect that the RTT is equal to the local time elapsed, since the // ack_delay_time is larger than the local time elapsed
diff --git a/quiche/quic/core/quic_session.h b/quiche/quic/core/quic_session.h index 56ac2b0..593bd2d 100644 --- a/quiche/quic/core/quic_session.h +++ b/quiche/quic/core/quic_session.h
@@ -307,6 +307,7 @@ void OnCanWrite() override; void OnCongestionWindowChange(QuicTime /*now*/) override {} void OnConnectionMigration(AddressChangeType /*type*/) override {} + void OnRttSampleAvailable(const QuicRttSample& /*rtt_sample*/) override {} // Adds a connection level WINDOW_UPDATE frame. void OnAckNeedsRetransmittableFrame() override; void SendAckFrequency(const QuicAckFrequencyFrame& frame) override;
diff --git a/quiche/quic/core/quic_types.h b/quiche/quic/core/quic_types.h index 7feba26..1ad2b56 100644 --- a/quiche/quic/core/quic_types.h +++ b/quiche/quic/core/quic_types.h
@@ -1016,6 +1016,16 @@ QUICHE_EXPORT std::string QuicPriorityTypeToString(QuicPriorityType type); QUICHE_EXPORT std::ostream& operator<<(std::ostream& os, QuicPriorityType type); +// Individual QUIC RTT sample as it is reported to by the application. +struct QUICHE_EXPORT QuicRttSample { + // The time delta between the time that the packet was received, and the time + // that the packet was acknowledged, adjusted for the ACK delay (see RFC 9000, + // Section 13.2.5). + QuicTimeDelta latest_rtt; + + bool operator==(const QuicRttSample& other) const = default; +}; + } // namespace quic #endif // QUICHE_QUIC_CORE_QUIC_TYPES_H_
diff --git a/quiche/quic/test_tools/quic_test_utils.h b/quiche/quic/test_tools/quic_test_utils.h index 78cfe1f..fd8cbf1 100644 --- a/quiche/quic/test_tools/quic_test_utils.h +++ b/quiche/quic/test_tools/quic_test_utils.h
@@ -487,6 +487,8 @@ MOCK_METHOD(void, OnCongestionWindowChange, (QuicTime now), (override)); MOCK_METHOD(void, OnConnectionMigration, (AddressChangeType type), (override)); + MOCK_METHOD(void, OnRttSampleAvailable, (const QuicRttSample& rtt_sample), + (override)); MOCK_METHOD(void, OnPathDegrading, (), (override)); MOCK_METHOD(void, OnForwardProgressMadeAfterPathDegrading, (), (override)); MOCK_METHOD(void, OnForwardProgressMadeAfterFlowLabelChange, (), (override)); @@ -1328,6 +1330,8 @@ MOCK_METHOD(void, OnPathMtuIncreased, (QuicPacketLength), (override)); MOCK_METHOD(void, OnInFlightEcnPacketAcked, (), (override)); MOCK_METHOD(void, OnInvalidEcnFeedback, (), (override)); + MOCK_METHOD(void, OnRttSampleAvailable, (const QuicRttSample& rtt_sample), + (override)); }; class MockQuicConnectionDebugVisitor : public QuicConnectionDebugVisitor {
diff --git a/quiche/quic/test_tools/simulator/quic_endpoint.h b/quiche/quic/test_tools/simulator/quic_endpoint.h index fe72ebc..c47a156 100644 --- a/quiche/quic/test_tools/simulator/quic_endpoint.h +++ b/quiche/quic/test_tools/simulator/quic_endpoint.h
@@ -61,6 +61,7 @@ const ParsedQuicVersion& /*version*/) override {} void OnCongestionWindowChange(QuicTime /*now*/) override {} void OnConnectionMigration(AddressChangeType /*type*/) override {} + void OnRttSampleAvailable(const QuicRttSample& /*rtt_sample*/) override {} void OnPathDegrading() override {} void OnForwardProgressMadeAfterPathDegrading() override {} void OnForwardProgressMadeAfterFlowLabelChange() override {}