Pass path validation start time to QuicPathValidator::ResultDelegate::OnPathValidationSuccess.
The start time can be used by multi ports to calculate RTTs on alternate path.
PiperOrigin-RevId: 464625591
diff --git a/quiche/quic/core/quic_connection.cc b/quiche/quic/core/quic_connection.cc
index 8dfa5a2..fc83845 100644
--- a/quiche/quic/core/quic_connection.cc
+++ b/quiche/quic/core/quic_connection.cc
@@ -37,6 +37,7 @@
#include "quiche/quic/core/quic_packet_writer.h"
#include "quiche/quic/core/quic_packets.h"
#include "quiche/quic/core/quic_path_validator.h"
+#include "quiche/quic/core/quic_time.h"
#include "quiche/quic/core/quic_types.h"
#include "quiche/quic/core/quic_utils.h"
#include "quiche/quic/platform/api/quic_bug_tracker.h"
@@ -325,7 +326,7 @@
blackhole_detector_(this, &arena_, alarm_factory_, &context_),
idle_network_detector_(this, clock_->ApproximateNow(), &arena_,
alarm_factory_, &context_),
- path_validator_(alarm_factory_, &arena_, this, random_generator_,
+ path_validator_(alarm_factory_, &arena_, this, random_generator_, clock_,
&context_),
ping_manager_(perspective, this, &arena_, alarm_factory_, &context_) {
QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT ||
@@ -7113,9 +7114,10 @@
connection_->active_effective_peer_migration_type_) {}
void QuicConnection::ReversePathValidationResultDelegate::
- OnPathValidationSuccess(
- std::unique_ptr<QuicPathValidationContext> context) {
- QUIC_DLOG(INFO) << "Successfully validated new path " << *context;
+ OnPathValidationSuccess(std::unique_ptr<QuicPathValidationContext> context,
+ QuicTime start_time) {
+ QUIC_DLOG(INFO) << "Successfully validated new path " << *context
+ << ", validation started at " << start_time;
if (connection_->IsDefaultPath(context->self_address(),
context->peer_address())) {
QUIC_CODE_COUNT_N(quic_kick_off_client_address_validation, 3, 6);
diff --git a/quiche/quic/core/quic_connection.h b/quiche/quic/core/quic_connection.h
index cd187e3..5daf2bf 100644
--- a/quiche/quic/core/quic_connection.h
+++ b/quiche/quic/core/quic_connection.h
@@ -1467,7 +1467,8 @@
const QuicSocketAddress& direct_peer_address);
void OnPathValidationSuccess(
- std::unique_ptr<QuicPathValidationContext> context) override;
+ std::unique_ptr<QuicPathValidationContext> context,
+ QuicTime start_time) override;
void OnPathValidationFailure(
std::unique_ptr<QuicPathValidationContext> context) override;
diff --git a/quiche/quic/core/quic_connection_test.cc b/quiche/quic/core/quic_connection_test.cc
index b07eb49..9274962 100644
--- a/quiche/quic/core/quic_connection_test.cc
+++ b/quiche/quic/core/quic_connection_test.cc
@@ -2428,7 +2428,8 @@
expected_peer_address_(expected_peer_address),
success_(success) {}
void OnPathValidationSuccess(
- std::unique_ptr<QuicPathValidationContext> context) override {
+ std::unique_ptr<QuicPathValidationContext> context,
+ QuicTime /*start_time*/) override {
EXPECT_EQ(expected_self_address_, context->self_address());
EXPECT_EQ(expected_peer_address_, context->peer_address());
*success_ = true;
diff --git a/quiche/quic/core/quic_path_validator.cc b/quiche/quic/core/quic_path_validator.cc
index 279ac0f..61e3dad 100644
--- a/quiche/quic/core/quic_path_validator.cc
+++ b/quiche/quic/core/quic_path_validator.cc
@@ -34,10 +34,11 @@
QuicPathValidator::QuicPathValidator(QuicAlarmFactory* alarm_factory,
QuicConnectionArena* arena,
SendDelegate* send_delegate,
- QuicRandom* random,
+ QuicRandom* random, const QuicClock* clock,
QuicConnectionContext* context)
: send_delegate_(send_delegate),
random_(random),
+ clock_(clock),
retry_timer_(alarm_factory->CreateAlarm(
arena->New<RetryAlarmDelegate>(this, context), arena)),
retry_count_(0u) {}
@@ -57,14 +58,16 @@
return;
}
// This iterates at most 3 times.
- if (std::find(probing_data_.begin(), probing_data_.end(), probing_data) !=
- probing_data_.end()) {
- result_delegate_->OnPathValidationSuccess(std::move(path_context_));
- ResetPathValidation();
- } else {
- QUIC_DVLOG(1) << "PATH_RESPONSE with payload " << probing_data.data()
- << " doesn't match the probing data.";
+ for (auto it = probing_data_.begin(); it != probing_data_.end(); ++it) {
+ if (it->frame_buffer == probing_data) {
+ result_delegate_->OnPathValidationSuccess(std::move(path_context_),
+ it->send_time);
+ ResetPathValidation();
+ return;
+ }
}
+ QUIC_DVLOG(1) << "PATH_RESPONSE with payload " << probing_data.data()
+ << " doesn't match the probing data.";
}
void QuicPathValidator::StartPathValidation(
@@ -109,9 +112,10 @@
}
const QuicPathFrameBuffer& QuicPathValidator::GeneratePathChallengePayload() {
- probing_data_.push_back(QuicPathFrameBuffer());
- random_->RandBytes(probing_data_.back().data(), sizeof(QuicPathFrameBuffer));
- return probing_data_.back();
+ probing_data_.emplace_back(clock_->Now());
+ random_->RandBytes(probing_data_.back().frame_buffer.data(),
+ sizeof(QuicPathFrameBuffer));
+ return probing_data_.back().frame_buffer;
}
void QuicPathValidator::OnRetryTimeout() {
diff --git a/quiche/quic/core/quic_path_validator.h b/quiche/quic/core/quic_path_validator.h
index 32758a9..4389ce5 100644
--- a/quiche/quic/core/quic_path_validator.h
+++ b/quiche/quic/core/quic_path_validator.h
@@ -16,6 +16,7 @@
#include "quiche/quic/core/quic_connection_context.h"
#include "quiche/quic/core/quic_one_block_arena.h"
#include "quiche/quic/core/quic_packet_writer.h"
+#include "quiche/quic/core/quic_time.h"
#include "quiche/quic/core/quic_types.h"
#include "quiche/quic/platform/api/quic_export.h"
#include "quiche/quic/platform/api/quic_socket_address.h"
@@ -100,8 +101,11 @@
public:
virtual ~ResultDelegate() = default;
+ // Called when a PATH_RESPONSE is received with a matching PATH_CHALLANGE.
+ // |start_time| is the time when the matching PATH_CHALLANGE was sent.
virtual void OnPathValidationSuccess(
- std::unique_ptr<QuicPathValidationContext> context) = 0;
+ std::unique_ptr<QuicPathValidationContext> context,
+ QuicTime start_time) = 0;
virtual void OnPathValidationFailure(
std::unique_ptr<QuicPathValidationContext> context) = 0;
@@ -109,7 +113,7 @@
QuicPathValidator(QuicAlarmFactory* alarm_factory, QuicConnectionArena* arena,
SendDelegate* delegate, QuicRandom* random,
- QuicConnectionContext* context);
+ const QuicClock* clock, QuicConnectionContext* context);
// Send PATH_CHALLENGE and start the retry timer.
void StartPathValidation(std::unique_ptr<QuicPathValidationContext> context,
@@ -144,10 +148,17 @@
void ResetPathValidation();
+ struct QUIC_NO_EXPORT ProbingData {
+ explicit ProbingData(QuicTime send_time) : send_time(send_time) {}
+ QuicPathFrameBuffer frame_buffer;
+ QuicTime send_time;
+ };
+
// Has at most 3 entries due to validation timeout.
- absl::InlinedVector<QuicPathFrameBuffer, 3> probing_data_;
+ absl::InlinedVector<ProbingData, 3> probing_data_;
SendDelegate* send_delegate_;
QuicRandom* random_;
+ const QuicClock* clock_;
std::unique_ptr<QuicPathValidationContext> path_context_;
std::unique_ptr<ResultDelegate> result_delegate_;
QuicArenaScopedPtr<QuicAlarm> retry_timer_;
diff --git a/quiche/quic/core/quic_path_validator_test.cc b/quiche/quic/core/quic_path_validator_test.cc
index 7640b86..f45cd26 100644
--- a/quiche/quic/core/quic_path_validator_test.cc
+++ b/quiche/quic/core/quic_path_validator_test.cc
@@ -43,6 +43,7 @@
public:
QuicPathValidatorTest()
: path_validator_(&alarm_factory_, &arena_, &send_delegate_, &random_,
+ &clock_,
/*context=*/nullptr),
context_(new MockQuicPathValidationContext(
self_address_, peer_address_, effective_peer_address_, &writer_)),
@@ -82,15 +83,19 @@
return true;
}));
EXPECT_CALL(send_delegate_, GetRetryTimeout(peer_address_, &writer_));
+ const QuicTime expected_start_time = clock_.Now();
path_validator_.StartPathValidation(
std::unique_ptr<QuicPathValidationContext>(context_),
std::unique_ptr<MockQuicPathValidationResultDelegate>(result_delegate_));
EXPECT_TRUE(path_validator_.HasPendingPathValidation());
EXPECT_TRUE(path_validator_.IsValidatingPeerAddress(effective_peer_address_));
- EXPECT_CALL(*result_delegate_, OnPathValidationSuccess(_))
- .WillOnce(Invoke([=](std::unique_ptr<QuicPathValidationContext> context) {
+ EXPECT_CALL(*result_delegate_, OnPathValidationSuccess(_, _))
+ .WillOnce(Invoke([=](std::unique_ptr<QuicPathValidationContext> context,
+ QuicTime start_time) {
EXPECT_EQ(context.get(), context_);
+ EXPECT_EQ(start_time, expected_start_time);
}));
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(kInitialRttMs));
path_validator_.OnPathResponse(challenge_data, self_address_);
EXPECT_FALSE(path_validator_.HasPendingPathValidation());
}
@@ -107,6 +112,7 @@
return true;
}));
EXPECT_CALL(send_delegate_, GetRetryTimeout(peer_address_, &writer_));
+ const QuicTime expected_start_time = clock_.Now();
path_validator_.StartPathValidation(
std::unique_ptr<QuicPathValidationContext>(context_),
std::unique_ptr<MockQuicPathValidationResultDelegate>(result_delegate_));
@@ -114,12 +120,16 @@
// Reception of a PATH_RESPONSE on a different self address should be ignored.
const QuicSocketAddress kAlternativeSelfAddress(QuicIpAddress::Any6(), 54321);
EXPECT_NE(kAlternativeSelfAddress, self_address_);
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(kInitialRttMs));
path_validator_.OnPathResponse(challenge_data, kAlternativeSelfAddress);
- EXPECT_CALL(*result_delegate_, OnPathValidationSuccess(_))
- .WillOnce(Invoke([=](std::unique_ptr<QuicPathValidationContext> context) {
+ EXPECT_CALL(*result_delegate_, OnPathValidationSuccess(_, _))
+ .WillOnce(Invoke([=](std::unique_ptr<QuicPathValidationContext> context,
+ QuicTime start_time) {
EXPECT_EQ(context->self_address(), self_address_);
+ EXPECT_EQ(start_time, expected_start_time);
}));
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(kInitialRttMs));
path_validator_.OnPathResponse(challenge_data, self_address_);
}
@@ -143,6 +153,7 @@
}));
EXPECT_CALL(send_delegate_, GetRetryTimeout(peer_address_, &writer_))
.Times(2u);
+ const QuicTime start_time = clock_.Now();
path_validator_.StartPathValidation(
std::unique_ptr<QuicPathValidationContext>(context_),
std::unique_ptr<MockQuicPathValidationResultDelegate>(result_delegate_));
@@ -152,7 +163,7 @@
alarm_factory_.FireAlarm(
QuicPathValidatorPeer::retry_timer(&path_validator_));
- EXPECT_CALL(*result_delegate_, OnPathValidationSuccess(_));
+ EXPECT_CALL(*result_delegate_, OnPathValidationSuccess(_, start_time));
// Respond to the 1st PATH_CHALLENGE should complete the validation.
path_validator_.OnPathResponse(challenge_data, self_address_);
EXPECT_FALSE(path_validator_.HasPendingPathValidation());
@@ -183,12 +194,13 @@
std::unique_ptr<MockQuicPathValidationResultDelegate>(result_delegate_));
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(3 * kInitialRttMs));
+ const QuicTime start_time = clock_.Now();
random_.ChangeValue();
alarm_factory_.FireAlarm(
QuicPathValidatorPeer::retry_timer(&path_validator_));
// Respond to the 2nd PATH_CHALLENGE should complete the validation.
- EXPECT_CALL(*result_delegate_, OnPathValidationSuccess(_));
+ EXPECT_CALL(*result_delegate_, OnPathValidationSuccess(_, start_time));
path_validator_.OnPathResponse(challenge_data, self_address_);
EXPECT_FALSE(path_validator_.HasPendingPathValidation());
}
diff --git a/quiche/quic/test_tools/quic_test_utils.h b/quiche/quic/test_tools/quic_test_utils.h
index 7340e7e..66f2c60 100644
--- a/quiche/quic/test_tools/quic_test_utils.h
+++ b/quiche/quic/test_tools/quic_test_utils.h
@@ -1434,7 +1434,8 @@
: public QuicPathValidator::ResultDelegate {
public:
MOCK_METHOD(void, OnPathValidationSuccess,
- (std::unique_ptr<QuicPathValidationContext>), (override));
+ (std::unique_ptr<QuicPathValidationContext>, QuicTime),
+ (override));
MOCK_METHOD(void, OnPathValidationFailure,
(std::unique_ptr<QuicPathValidationContext>), (override));
diff --git a/quiche/quic/tools/quic_client_base.cc b/quiche/quic/tools/quic_client_base.cc
index 826ade8..4a300c2 100644
--- a/quiche/quic/tools/quic_client_base.cc
+++ b/quiche/quic/tools/quic_client_base.cc
@@ -49,7 +49,8 @@
// Overridden to start migration and takes the ownership of the writer in the
// context.
void OnPathValidationSuccess(
- std::unique_ptr<QuicPathValidationContext> context) override {
+ std::unique_ptr<QuicPathValidationContext> context,
+ QuicTime /*start_time*/) override {
QUIC_DLOG(INFO) << "Successfully validated path from " << *context
<< ". Migrate to it now.";
auto migration_context = std::unique_ptr<PathMigrationContext>(
@@ -467,8 +468,10 @@
: QuicPathValidator::ResultDelegate(), client_(client) {}
void OnPathValidationSuccess(
- std::unique_ptr<QuicPathValidationContext> context) override {
- QUIC_DLOG(INFO) << "Successfully validated path from " << *context;
+ std::unique_ptr<QuicPathValidationContext> context,
+ QuicTime start_time) override {
+ QUIC_DLOG(INFO) << "Successfully validated path from " << *context
+ << ", validation started at " << start_time;
client_->AddValidatedPath(std::move(context));
}
void OnPathValidationFailure(