-
Notifications
You must be signed in to change notification settings - Fork 5.5k
quic: change QuicNetworkConnectivityObserver interface #35775
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 25 commits
959cd4c
4b969c9
242dc5e
28e805a
a582d79
1e57860
e3663b2
ccd0dd2
7e8e3d3
84eeb68
2337129
9725172
845c19d
462e7bd
76e0894
e47c408
c239b59
2bf31a3
27058bc
fe5b171
2d78be5
f883a1c
2af5cfb
471b7bb
5ad0e26
ddd3739
c2c3909
225d362
eae7c9e
ee6a0b4
bd3fd65
6815335
cdc290d
f668a04
73d0b0e
47d708f
8c576fa
6ab8b05
3dba5e6
809ee7e
7c31d1e
f22a3d9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -77,6 +77,14 @@ constexpr unsigned int InitialFaultThreshold = 1; | |
| // L7 bytes) before switching socket mode. | ||
| constexpr unsigned int MaxFaultThreshold = 3; | ||
|
|
||
| ConnectivityManagerImpl::ConnectivityManagerImpl(Upstream::ClusterManager& cluster_manager, | ||
| DnsCacheManagerSharedPtr dns_cache_manager) | ||
| : cluster_manager_(cluster_manager), dns_cache_manager_(dns_cache_manager) { | ||
| if (quic_upstream_connection_handle_network_change_) { | ||
| cluster_manager_.createNetworkObserverRegistries(quic_observer_registry_factory_); | ||
| } | ||
| } | ||
|
|
||
| ConnectivityManagerImpl::NetworkState ConnectivityManagerImpl::network_state_{ | ||
| 1, NetworkType::Generic, MaxFaultThreshold, SocketMode::DefaultPreferredNetworkMode, | ||
| Thread::MutexBasicLockable{}}; | ||
|
|
@@ -102,6 +110,16 @@ envoy_netconf_t ConnectivityManagerImpl::setPreferredNetwork(NetworkType network | |
| return network_state_.configuration_key_; | ||
| } | ||
|
|
||
| envoy_netconf_t ConnectivityManagerImpl::onNetworkMadeDefault(NetworkType network) { | ||
| ENVOY_LOG_MISC(trace, "Default network changed to {}", static_cast<int>(network)); | ||
| envoy_netconf_t configuration_key = setPreferredNetwork(network); | ||
| for (std::reference_wrapper<Quic::EnvoyMobileQuicNetworkObserverRegistry> registry : | ||
| quic_observer_registry_factory_.getCreatedObserverRegistries()) { | ||
| registry.get().onNetworkMadeDefault(); | ||
| } | ||
| return configuration_key; | ||
| } | ||
|
|
||
| void ConnectivityManagerImpl::setProxySettings(ProxySettingsConstSharedPtr new_proxy_settings) { | ||
| if (proxy_settings_ == nullptr && new_proxy_settings != nullptr) { | ||
| ENVOY_LOG_EVENT(info, "netconf_proxy_change", "{}", new_proxy_settings->asString()); | ||
|
|
@@ -305,16 +323,17 @@ Socket::OptionsSharedPtr ConnectivityManagerImpl::getUpstreamSocketOptions(Netwo | |
| network != NetworkType::Generic) { | ||
| return getAlternateInterfaceSocketOptions(network); | ||
| } | ||
|
|
||
| // Envoy uses the hash signature of overridden socket options to choose a connection pool. | ||
| // Setting a dummy socket option is a hack that allows us to select a different | ||
| // connection pool without materially changing the socket configuration. | ||
| ASSERT(static_cast<int>(network) >= 0 && static_cast<int>(network) < 3); | ||
| int ttl_value = DEFAULT_IP_TTL + static_cast<int>(network); | ||
| auto options = std::make_shared<Socket::Options>(); | ||
| options->push_back(std::make_shared<AddrFamilyAwareSocketOptionImpl>( | ||
| envoy::config::core::v3::SocketOption::STATE_PREBIND, ENVOY_SOCKET_IP_TTL, | ||
| ENVOY_SOCKET_IPV6_UNICAST_HOPS, ttl_value)); | ||
| if (!quic_upstream_connection_handle_network_change_) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are we not doing this when the runtime guard is true?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the old way of not reusing the existing connections for new request. It actually changes how a request is hashed to a connection pool. Since we are going away connections, we don't need to rely on this. And in the new world, we should still be able to reuse the old connection pools, just not the existing connection in it.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, I see. Good point. Nice!
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so I agree with this as a long term plan but without marking H2 and H1 connections as draining won't this possibly be a regression for non-H3 traffic?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a good point! I think this feature needs to be enabled when both H2 and H3 support network change. Adding network connectivity observers to H2 is another big change. I would prefer not to do it in this PR. The runtime guard is default false, do you think we can land the H3 support first and then change H2 and flip the runtime guard? I didn't see how H1 is handled in Chromium. Is network change an issue in H1 at all?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For H1 in Chrome, I think the connections are simply abruptly terminated when the IP address changes:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Filed #36059 for tracking and explanation. |
||
| // Envoy uses the hash signature of overridden socket options to choose a connection pool. | ||
| // Setting a dummy socket option is a hack that allows us to select a different | ||
| // connection pool without materially changing the socket configuration. | ||
| int ttl_value = DEFAULT_IP_TTL + static_cast<int>(network); | ||
| options->push_back(std::make_shared<AddrFamilyAwareSocketOptionImpl>( | ||
| envoy::config::core::v3::SocketOption::STATE_PREBIND, ENVOY_SOCKET_IP_TTL, | ||
| ENVOY_SOCKET_IPV6_UNICAST_HOPS, ttl_value)); | ||
| } | ||
| return options; | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| #include "library/common/network/envoy_mobile_quic_network_observer_registry_factory.h" | ||
|
|
||
| #include "source/common/runtime/runtime_features.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Quic { | ||
|
|
||
| void EnvoyMobileQuicNetworkObserverRegistry::onNetworkMadeDefault() { | ||
| ENVOY_LOG_MISC(trace, "Default network changed."); | ||
| ASSERT(dispatcher_.isThreadSafe()); | ||
| ASSERT(Runtime::runtimeFeatureEnabled( | ||
| "envoy.reloadable_features.quic_upstream_connection_handle_network_change")); | ||
| // Retain the existing observers in a list and iterate on the list as new | ||
| // connections might be created and registered during iteration. | ||
| std::vector<QuicNetworkConnectivityObserver*> existing_observers; | ||
| existing_observers.reserve(registeredQuicObservers().size()); | ||
| for (QuicNetworkConnectivityObserver* observer : registeredQuicObservers()) { | ||
| existing_observers.push_back(observer); | ||
| } | ||
| for (QuicNetworkConnectivityObserver* observer : existing_observers) { | ||
| observer->onNetworkChanged(); | ||
| } | ||
| } | ||
|
|
||
| EnvoyQuicNetworkObserverRegistryPtr | ||
| EnvoyMobileQuicNetworkObserverRegistryFactory::createQuicNetworkObserverRegistry( | ||
| Event::Dispatcher& dispatcher) { | ||
| auto result = std::make_unique<EnvoyMobileQuicNetworkObserverRegistry>(dispatcher); | ||
| thread_local_observer_registries_.emplace_back(*result); | ||
| return result; | ||
| } | ||
|
|
||
| } // namespace Quic | ||
| } // namespace Envoy |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| #pragma once | ||
|
|
||
| #include "source/common/quic/envoy_quic_network_observer_registry_factory.h" | ||
| #include "source/common/quic/quic_network_connectivity_observer.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Quic { | ||
|
|
||
| // A mobile implementation that also handles network change events. | ||
| class EnvoyMobileQuicNetworkObserverRegistry : public EnvoyQuicNetworkObserverRegistry { | ||
| public: | ||
| explicit EnvoyMobileQuicNetworkObserverRegistry(Event::Dispatcher& dispatcher) | ||
| : dispatcher_(dispatcher) {} | ||
|
|
||
| // Called when the default network has changed to notify each registered observer. | ||
| void onNetworkMadeDefault(); | ||
|
danzh2010 marked this conversation as resolved.
Outdated
|
||
|
|
||
| private: | ||
| Event::Dispatcher& dispatcher_; | ||
| }; | ||
|
|
||
| class EnvoyMobileQuicNetworkObserverRegistryFactory | ||
| : public EnvoyQuicNetworkObserverRegistryFactory { | ||
| public: | ||
| EnvoyMobileQuicNetworkObserverRegistryFactory() { thread_local_observer_registries_.reserve(1); } | ||
|
|
||
| EnvoyQuicNetworkObserverRegistryPtr | ||
| createQuicNetworkObserverRegistry(Event::Dispatcher& dispatcher) override; | ||
|
|
||
| std::vector<std::reference_wrapper<EnvoyMobileQuicNetworkObserverRegistry>>& | ||
| getCreatedObserverRegistries() { | ||
| return thread_local_observer_registries_; | ||
| } | ||
|
|
||
| private: | ||
| std::vector<std::reference_wrapper<EnvoyMobileQuicNetworkObserverRegistry>> | ||
| thread_local_observer_registries_; | ||
| }; | ||
|
|
||
| using EnvoyMobileQuicNetworkObserverRegistryPtr = | ||
| std::unique_ptr<EnvoyMobileQuicNetworkObserverRegistry>; | ||
|
|
||
| } // namespace Quic | ||
| } // namespace Envoy | ||
Uh oh!
There was an error while loading. Please reload this page.