Skip to content

Commit

Permalink
Config switch to turn on/off Quic processing (envoyproxy#9679)
Browse files Browse the repository at this point in the history
Extending quic listener configuration with runtime feature flag for enabling/disabling quic processing.

Signed-off-by: Kateryna Nezdolii <nezdolik@spotify.com>
  • Loading branch information
Kateryna Nezdolii authored May 15, 2020
1 parent 1e1bdcc commit 853ecaa
Show file tree
Hide file tree
Showing 10 changed files with 224 additions and 31 deletions.
8 changes: 7 additions & 1 deletion api/envoy/config/listener/v3/quic_config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ syntax = "proto3";

package envoy.config.listener.v3;

import "envoy/config/core/v3/base.proto";

import "google/protobuf/duration.proto";
import "google/protobuf/wrappers.proto";

Expand All @@ -16,7 +18,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE;
// [#protodoc-title: QUIC listener Config]

// Configuration specific to the QUIC protocol.
// Next id: 4
// Next id: 5
message QuicProtocolOptions {
option (udpa.annotations.versioning).previous_message_type =
"envoy.api.v2.listener.QuicProtocolOptions";
Expand All @@ -32,4 +34,8 @@ message QuicProtocolOptions {
// Connection timeout in milliseconds before the crypto handshake is finished.
// 20000ms if not specified.
google.protobuf.Duration crypto_handshake_timeout = 3;

// Runtime flag that controls whether the listener is enabled or not. If not specified, defaults
// to enabled.
core.v3.RuntimeFeatureFlag enabled = 4;
}
8 changes: 7 additions & 1 deletion api/envoy/config/listener/v4alpha/quic_config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ syntax = "proto3";

package envoy.config.listener.v4alpha;

import "envoy/config/core/v4alpha/base.proto";

import "google/protobuf/duration.proto";
import "google/protobuf/wrappers.proto";

Expand All @@ -16,7 +18,7 @@ option (udpa.annotations.file_status).package_version_status = NEXT_MAJOR_VERSIO
// [#protodoc-title: QUIC listener Config]

// Configuration specific to the QUIC protocol.
// Next id: 4
// Next id: 5
message QuicProtocolOptions {
option (udpa.annotations.versioning).previous_message_type =
"envoy.config.listener.v3.QuicProtocolOptions";
Expand All @@ -32,4 +34,8 @@ message QuicProtocolOptions {
// Connection timeout in milliseconds before the crypto handshake is finished.
// 20000ms if not specified.
google.protobuf.Duration crypto_handshake_timeout = 3;

// Runtime flag that controls whether the listener is enabled or not. If not specified, defaults
// to enabled.
core.v4alpha.RuntimeFeatureFlag enabled = 4;
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions source/extensions/quic_listeners/quiche/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ envoy_cc_library(
"//include/envoy/network:listener_interface",
"//source/common/network:listener_lib",
"//source/common/protobuf:utility_lib",
"//source/common/runtime:runtime_lib",
"//source/server:connection_handler_lib",
"@envoy_api//envoy/config/listener/v3:pkg_cc_proto",
],
Expand Down
20 changes: 13 additions & 7 deletions source/extensions/quic_listeners/quiche/active_quic_listener.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,22 @@ ActiveQuicListener::ActiveQuicListener(Event::Dispatcher& dispatcher,
Network::ConnectionHandler& parent,
Network::ListenerConfig& listener_config,
const quic::QuicConfig& quic_config,
Network::Socket::OptionsSharedPtr options)
Network::Socket::OptionsSharedPtr options,
const envoy::config::core::v3::RuntimeFeatureFlag& enabled)
: ActiveQuicListener(dispatcher, parent,
listener_config.listenSocketFactory().getListenSocket(), listener_config,
quic_config, std::move(options)) {}
quic_config, std::move(options), enabled) {}

ActiveQuicListener::ActiveQuicListener(Event::Dispatcher& dispatcher,
Network::ConnectionHandler& parent,
Network::SocketSharedPtr listen_socket,
Network::ListenerConfig& listener_config,
const quic::QuicConfig& quic_config,
Network::Socket::OptionsSharedPtr options)
Network::Socket::OptionsSharedPtr options,
const envoy::config::core::v3::RuntimeFeatureFlag& enabled)
: Server::ConnectionHandlerImpl::ActiveListenerImplBase(parent, &listener_config),
dispatcher_(dispatcher), version_manager_(quic::CurrentSupportedVersions()),
listen_socket_(*listen_socket) {
listen_socket_(*listen_socket), enabled_(enabled, Runtime::LoaderSingleton::get()) {
if (options != nullptr) {
const bool ok = Network::Socket::applyOptions(
options, listen_socket_, envoy::config::core::v3::SocketOption::STATE_BOUND);
Expand All @@ -44,7 +46,6 @@ ActiveQuicListener::ActiveQuicListener(Event::Dispatcher& dispatcher,
}
listen_socket_.addOptions(options);
}

udp_listener_ = dispatcher_.createUdpListener(std::move(listen_socket), *this);
quic::QuicRandom* const random = quic::QuicRandom::GetInstance();
random->RandBytes(random_seed_, sizeof(random_seed_));
Expand Down Expand Up @@ -93,6 +94,10 @@ void ActiveQuicListener::onData(Network::UdpRecvData& data) {
}

void ActiveQuicListener::onReadReady() {
if (!enabled_.enabled()) {
ENVOY_LOG(trace, "Quic listener {}: runtime disabled", config_->name());
return;
}
quic_dispatcher_->ProcessBufferedChlos(kNumSessionsToCreatePerLoop);
}

Expand All @@ -112,7 +117,7 @@ void ActiveQuicListener::shutdownListener() {

ActiveQuicListenerFactory::ActiveQuicListenerFactory(
const envoy::config::listener::v3::QuicProtocolOptions& config, uint32_t concurrency)
: concurrency_(concurrency) {
: concurrency_(concurrency), enabled_(config.enabled()) {
uint64_t idle_network_timeout_ms =
config.has_idle_timeout() ? DurationUtil::durationToMilliseconds(config.idle_timeout())
: 300000;
Expand Down Expand Up @@ -191,8 +196,9 @@ ActiveQuicListenerFactory::createActiveUdpListener(Network::ConnectionHandler& p
#endif
}
#endif

return std::make_unique<ActiveQuicListener>(disptacher, parent, config, quic_config_,
std::move(options));
std::move(options), enabled_);
}

} // namespace Quic
Expand Down
10 changes: 8 additions & 2 deletions source/extensions/quic_listeners/quiche/active_quic_listener.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
#include "envoy/config/listener/v3/quic_config.pb.h"
#include "envoy/network/connection_handler.h"
#include "envoy/network/listener.h"
#include "envoy/runtime/runtime.h"

#include "common/network/socket_option_impl.h"
#include "common/protobuf/utility.h"
#include "common/runtime/runtime_protos.h"

#include "server/connection_handler_impl.h"

Expand All @@ -25,12 +27,14 @@ class ActiveQuicListener : public Network::UdpListenerCallbacks,

ActiveQuicListener(Event::Dispatcher& dispatcher, Network::ConnectionHandler& parent,
Network::ListenerConfig& listener_config, const quic::QuicConfig& quic_config,
Network::Socket::OptionsSharedPtr options);
Network::Socket::OptionsSharedPtr options,
const envoy::config::core::v3::RuntimeFeatureFlag& enabled);

ActiveQuicListener(Event::Dispatcher& dispatcher, Network::ConnectionHandler& parent,
Network::SocketSharedPtr listen_socket,
Network::ListenerConfig& listener_config, const quic::QuicConfig& quic_config,
Network::Socket::OptionsSharedPtr options);
Network::Socket::OptionsSharedPtr options,
const envoy::config::core::v3::RuntimeFeatureFlag& enabled);

~ActiveQuicListener() override;

Expand Down Expand Up @@ -60,6 +64,7 @@ class ActiveQuicListener : public Network::UdpListenerCallbacks,
quic::QuicVersionManager version_manager_;
std::unique_ptr<EnvoyQuicDispatcher> quic_dispatcher_;
Network::Socket& listen_socket_;
Runtime::FeatureFlag enabled_;
};

using ActiveQuicListenerPtr = std::unique_ptr<ActiveQuicListener>;
Expand All @@ -83,6 +88,7 @@ class ActiveQuicListenerFactory : public Network::ActiveUdpListenerFactory,
quic::QuicConfig quic_config_;
const uint32_t concurrency_;
absl::once_flag install_bpf_once_;
envoy::config::core::v3::RuntimeFeatureFlag enabled_;
};

} // namespace Quic
Expand Down
3 changes: 3 additions & 0 deletions test/extensions/quic_listeners/quiche/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -167,13 +167,16 @@ envoy_cc_test(
],
deps = [
":quic_test_utils_for_envoy_lib",
"//source/extensions/quic_listeners/quiche:active_quic_listener_config_lib",
"//source/extensions/quic_listeners/quiche:active_quic_listener_lib",
"//source/extensions/quic_listeners/quiche:envoy_quic_utils_lib",
"//source/server:configuration_lib",
"//test/mocks/network:network_mocks",
"//test/mocks/server:server_mocks",
"//test/test_common:environment_lib",
"//test/test_common:network_utility_lib",
"//test/test_common:simulated_time_system_lib",
"@envoy_api//envoy/config/core/v3:pkg_cc_proto",
],
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ class ActiveQuicListenerFactoryPeer {
static quic::QuicConfig& quicConfig(ActiveQuicListenerFactory& factory) {
return factory.quic_config_;
}
static envoy::config::core::v3::RuntimeFeatureFlag&
runtimeEnabled(ActiveQuicListenerFactory& factory) {
return factory.enabled_;
}
};

TEST(ActiveQuicListenerConfigTest, CreateActiveQuicListenerFactory) {
Expand All @@ -29,6 +33,9 @@ TEST(ActiveQuicListenerConfigTest, CreateActiveQuicListenerFactory) {
idle_timeout: {
seconds: 2
}
enabled:
default_value: true
runtime_key: foo_key
)EOF";
TestUtility::loadFromYaml(yaml, *config);
Network::ActiveUdpListenerFactoryPtr listener_factory =
Expand All @@ -41,6 +48,38 @@ TEST(ActiveQuicListenerConfigTest, CreateActiveQuicListenerFactory) {
EXPECT_EQ(2000u, quic_config.IdleNetworkTimeout().ToMilliseconds());
// Default value if not present in config.
EXPECT_EQ(20000u, quic_config.max_time_before_crypto_handshake().ToMilliseconds());
envoy::config::core::v3::RuntimeFeatureFlag& runtime_enabled =
ActiveQuicListenerFactoryPeer::runtimeEnabled(
dynamic_cast<ActiveQuicListenerFactory&>(*listener_factory));
EXPECT_EQ(true, runtime_enabled.default_value().value());
EXPECT_EQ("foo_key", runtime_enabled.runtime_key());
}

TEST(ActiveQuicListenerConfigTest, QuicListenerFlagNotConfigured) {
std::string listener_name = QuicListenerName;
auto& config_factory =
Config::Utility::getAndCheckFactoryByName<Server::ActiveUdpListenerConfigFactory>(
listener_name);
ProtobufTypes::MessagePtr config = config_factory.createEmptyConfigProto();

std::string yaml = R"EOF(
max_concurrent_streams: 10
idle_timeout: {
seconds: 2
}
)EOF";
TestUtility::loadFromYaml(yaml, *config);
Network::ActiveUdpListenerFactoryPtr listener_factory =
config_factory.createActiveUdpListenerFactory(*config, /*concurrency=*/1);
EXPECT_NE(nullptr, listener_factory);
envoy::config::core::v3::RuntimeFeatureFlag& runtime_enabled =
ActiveQuicListenerFactoryPeer::runtimeEnabled(
dynamic_cast<ActiveQuicListenerFactory&>(*listener_factory));
auto& quic_config =
dynamic_cast<const envoy::config::listener::v3::QuicProtocolOptions&>(*config);
EXPECT_FALSE(runtime_enabled.has_default_value());
EXPECT_FALSE(quic_config.has_enabled());
EXPECT_EQ("", runtime_enabled.runtime_key());
}

} // namespace Quic
Expand Down
Loading

0 comments on commit 853ecaa

Please sign in to comment.