Commit e29d97d9 authored by Zhongyi Shi's avatar Zhongyi Shi Committed by Commit Bot

Attempt port migration if path degrading is detected.

Session will migrate to the new port after probing succeeds.

BUG: 999285
Change-Id: I115a6a7eede4c027bb666288c1a838a6b1323549
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1775744
Commit-Queue: Zhongyi Shi <zhongyi@chromium.org>
Reviewed-by: default avatarRyan Hamilton <rch@chromium.org>
Cr-Commit-Position: refs/heads/master@{#692966}
parent dcf25ed5
......@@ -1957,20 +1957,10 @@ void QuicChromiumClientSession::OnProbeSucceeded(
/*is_success=*/true);
});
if (network != NetworkChangeNotifier::kInvalidNetworkHandle) {
OnProbeNetworkSucceeded(network, peer_address, self_address,
std::move(socket), std::move(writer),
std::move(reader));
}
}
if (!allow_port_migration_ &&
network == NetworkChangeNotifier::kInvalidNetworkHandle)
return;
void QuicChromiumClientSession::OnProbeNetworkSucceeded(
NetworkChangeNotifier::NetworkHandle network,
const quic::QuicSocketAddress& peer_address,
const quic::QuicSocketAddress& self_address,
std::unique_ptr<DatagramClientSocket> socket,
std::unique_ptr<QuicChromiumPacketWriter> writer,
std::unique_ptr<QuicChromiumPacketReader> reader) {
LogProbeResultToHistogram(current_connection_migration_cause_, true);
// Remove |this| as the old packet writer's delegate. Write error on old
......@@ -2011,7 +2001,8 @@ void QuicChromiumClientSession::OnProbeNetworkSucceeded(
NetLogEventType::QUIC_CONNECTION_MIGRATION_SUCCESS_AFTER_PROBING,
"migrate_to_network", network);
if (network == default_network_) {
DVLOG(1) << "Client successfully migrated to default network.";
DVLOG(1) << "Client successfully migrated to default network: "
<< default_network_;
CancelMigrateBackToDefaultNetworkTimer();
return;
}
......@@ -2037,21 +2028,17 @@ void QuicChromiumClientSession::OnProbeFailed(
/*is_success=*/false);
});
if (network != NetworkChangeNotifier::kInvalidNetworkHandle)
OnProbeNetworkFailed(network, peer_address);
}
void QuicChromiumClientSession::OnProbeNetworkFailed(
NetworkChangeNotifier::NetworkHandle network,
const quic::QuicSocketAddress& peer_address) {
LogProbeResultToHistogram(current_connection_migration_cause_, false);
// Probing failure can be ignored.
DVLOG(1) << "Connectivity probing failed on <network: " << network
<< ", peer_address: " << peer_address.ToString() << ">.";
DVLOG_IF(1, network == default_network_ &&
GetDefaultSocket()->GetBoundNetwork() != default_network_)
<< "Client probing failed on the default network, still using "
"non-default network.";
if (network != NetworkChangeNotifier::kInvalidNetworkHandle) {
// Probing failure can be ignored.
DVLOG(1) << "Connectivity probing failed on <network: " << network
<< ", peer_address: " << peer_address.ToString() << ">.";
DVLOG_IF(1, network == default_network_ &&
GetDefaultSocket()->GetBoundNetwork() != default_network_)
<< "Client probing failed on the default network, still using "
"non-default network.";
}
}
bool QuicChromiumClientSession::OnSendConnectivityProbingPacket(
......@@ -2293,52 +2280,17 @@ void QuicChromiumClientSession::OnPathDegrading() {
current_connection_migration_cause_ = ON_PATH_DEGRADING;
if (!migrate_session_early_v2_) {
HistogramAndLogMigrationFailure(
net_log_, MIGRATION_STATUS_PATH_DEGRADING_NOT_ENABLED, connection_id(),
"Migration on path degrading not enabled");
return;
}
if (GetDefaultSocket()->GetBoundNetwork() == default_network_ &&
current_migrations_to_non_default_network_on_path_degrading_ >=
max_migrations_to_non_default_network_on_path_degrading_) {
HistogramAndLogMigrationFailure(
net_log_, MIGRATION_STATUS_ON_PATH_DEGRADING_DISABLED, connection_id(),
"Exceeds maximum number of migrations on path degrading");
return;
}
NetworkChangeNotifier::NetworkHandle alternate_network =
stream_factory_->FindAlternateNetwork(
GetDefaultSocket()->GetBoundNetwork());
if (alternate_network == NetworkChangeNotifier::kInvalidNetworkHandle) {
HistogramAndLogMigrationFailure(
net_log_, MIGRATION_STATUS_NO_ALTERNATE_NETWORK, connection_id(),
"No alternative network on path degrading");
if (migrate_session_early_v2_) {
MaybeMigrateToAlternateNetworkOnPathDegrading();
return;
}
LogHandshakeStatusOnConnectionMigrationSignal();
if (!IsCryptoHandshakeConfirmed()) {
HistogramAndLogMigrationFailure(
net_log_, MIGRATION_STATUS_PATH_DEGRADING_BEFORE_HANDSHAKE_CONFIRMED,
connection_id(), "Path degrading before handshake confirmed");
return;
}
HistogramAndLogMigrationFailure(
net_log_, MIGRATION_STATUS_PATH_DEGRADING_NOT_ENABLED, connection_id(),
"Migration on path degrading not enabled");
const NetLogWithSource migration_net_log = NetLogWithSource::Make(
net_log_.net_log(), NetLogSourceType::QUIC_CONNECTION_MIGRATION);
migration_net_log.BeginEventWithStringParams(
NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED, "trigger",
"PathDegrading");
// Probe the alternative network, session will migrate to the probed
// network and decide whether it wants to migrate back to the default
// network on success.
StartProbeNetwork(alternate_network, peer_address(), migration_net_log);
migration_net_log.EndEvent(
NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED);
if (allow_port_migration_)
MaybeMigrateToDifferentPortOnPathDegrading();
}
bool QuicChromiumClientSession::ShouldKeepConnectionAlive() const {
......@@ -2476,7 +2428,78 @@ void QuicChromiumClientSession::NotifyRequestsOfConfirmation(int net_error) {
waiting_for_confirmation_callbacks_.clear();
}
ProbingResult QuicChromiumClientSession::StartProbeNetwork(
void QuicChromiumClientSession::MaybeMigrateToDifferentPortOnPathDegrading() {
DCHECK(allow_port_migration_ && !migrate_session_early_v2_);
// Migration before handshake is not allowed.
if (!IsCryptoHandshakeConfirmed()) {
// TODO(zhongyi): add histogram and net log entries.
return;
}
// TODO(zhongyi): replace with port migration net log.
const NetLogWithSource migration_net_log = NetLogWithSource::Make(
net_log_.net_log(), NetLogSourceType::QUIC_CONNECTION_MIGRATION);
migration_net_log.BeginEventWithStringParams(
NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED, "trigger",
"port migration on PathDegrading");
if (!stream_factory_)
return;
// Probe a different port, session will migrate to the probed port on success.
// TODO(zhongyi): maybe pass in the network handle current socket is on?
StartProbing(default_network_, peer_address(), migration_net_log);
migration_net_log.EndEvent(
NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED);
}
void QuicChromiumClientSession::
MaybeMigrateToAlternateNetworkOnPathDegrading() {
DCHECK(migrate_session_early_v2_);
if (GetDefaultSocket()->GetBoundNetwork() == default_network_ &&
current_migrations_to_non_default_network_on_path_degrading_ >=
max_migrations_to_non_default_network_on_path_degrading_) {
HistogramAndLogMigrationFailure(
net_log_, MIGRATION_STATUS_ON_PATH_DEGRADING_DISABLED, connection_id(),
"Exceeds maximum number of migrations on path degrading");
return;
}
NetworkChangeNotifier::NetworkHandle alternate_network =
stream_factory_->FindAlternateNetwork(
GetDefaultSocket()->GetBoundNetwork());
if (alternate_network == NetworkChangeNotifier::kInvalidNetworkHandle) {
HistogramAndLogMigrationFailure(
net_log_, MIGRATION_STATUS_NO_ALTERNATE_NETWORK, connection_id(),
"No alternative network on path degrading");
return;
}
LogHandshakeStatusOnConnectionMigrationSignal();
if (!IsCryptoHandshakeConfirmed()) {
HistogramAndLogMigrationFailure(
net_log_, MIGRATION_STATUS_PATH_DEGRADING_BEFORE_HANDSHAKE_CONFIRMED,
connection_id(), "Path degrading before handshake confirmed");
return;
}
const NetLogWithSource migration_net_log = NetLogWithSource::Make(
net_log_.net_log(), NetLogSourceType::QUIC_CONNECTION_MIGRATION);
migration_net_log.BeginEventWithStringParams(
NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED, "trigger",
"PathDegrading");
// Probe the alternative network, session will migrate to the probed
// network and decide whether it wants to migrate back to the default
// network on success.
MaybeStartProbing(alternate_network, peer_address(), migration_net_log);
migration_net_log.EndEvent(
NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED);
}
ProbingResult QuicChromiumClientSession::MaybeStartProbing(
NetworkChangeNotifier::NetworkHandle network,
const quic::QuicSocketAddress& peer_address,
const NetLogWithSource& migration_net_log) {
......@@ -2510,6 +2533,13 @@ ProbingResult QuicChromiumClientSession::StartProbeNetwork(
return ProbingResult::DISABLED_BY_CONFIG;
}
return StartProbing(network, peer_address, migration_net_log);
}
ProbingResult QuicChromiumClientSession::StartProbing(
NetworkChangeNotifier::NetworkHandle network,
const quic::QuicSocketAddress& peer_address,
const NetLogWithSource& migration_net_log) {
// Check if probing manager is probing the same path.
if (probing_manager_.IsUnderProbing(network, peer_address))
return ProbingResult::PENDING;
......@@ -2584,7 +2614,7 @@ void QuicChromiumClientSession::TryMigrateBackToDefaultNetwork(
// will be cancelled and manager starts to probe |default_network_|
// immediately.
ProbingResult result =
StartProbeNetwork(default_network_, peer_address(), net_log_);
MaybeStartProbing(default_network_, peer_address(), net_log_);
if (result == ProbingResult::DISABLED_WITH_IDLE_SESSION)
return;
......
......@@ -694,10 +694,26 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
void CancelAllRequests(int net_error);
void NotifyRequestsOfConfirmation(int net_error);
ProbingResult StartProbeNetwork(NetworkChangeNotifier::NetworkHandle network,
// Probe on <network, peer_address>.
// If <network, peer_addres> is identical to the current path, the probe
// is sent on a different port.
ProbingResult StartProbing(NetworkChangeNotifier::NetworkHandle network,
const quic::QuicSocketAddress& peer_address,
const NetLogWithSource& migration_net_log);
// Perform a few checks before StartProbing. If any of those checks fails,
// StartProbing will be skipped.
ProbingResult MaybeStartProbing(NetworkChangeNotifier::NetworkHandle network,
const quic::QuicSocketAddress& peer_address,
const NetLogWithSource& migration_net_log);
// Helper method to perform a few checks and initiate connection migration
// attempt when path degrading is detected.
void MaybeMigrateToAlternateNetworkOnPathDegrading();
// Helper method to initiate a port migration on path degrading is detected.
void MaybeMigrateToDifferentPortOnPathDegrading();
// Called when there is only one possible working network: |network|, If any
// error encountered, this session will be closed.
// When the migration succeeds:
......@@ -707,18 +723,6 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
// network.
void MigrateNetworkImmediately(NetworkChangeNotifier::NetworkHandle network);
// Called when probe |network| succeeded.
void OnProbeNetworkSucceeded(
NetworkChangeNotifier::NetworkHandle network,
const quic::QuicSocketAddress& peer_address,
const quic::QuicSocketAddress& self_address,
std::unique_ptr<DatagramClientSocket> socket,
std::unique_ptr<QuicChromiumPacketWriter> writer,
std::unique_ptr<QuicChromiumPacketReader> reader);
// Called when probe |network| failed.
void OnProbeNetworkFailed(NetworkChangeNotifier::NetworkHandle network,
const quic::QuicSocketAddress& peer_address);
void StartMigrateBackToDefaultNetworkTimer(base::TimeDelta delay);
void CancelMigrateBackToDefaultNetworkTimer();
void TryMigrateBackToDefaultNetwork(base::TimeDelta timeout);
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment