Skip to content

Commit

Permalink
ecds: hook UDP session filters with config provider (envoyproxy#35713)
Browse files Browse the repository at this point in the history
Adding a new ``ConfigProviderManager`` for UDP
session filters with tests. Consuming this provider for static filters.
This PR does not add dynamic filters yet, will be done in next PR.

---------

Signed-off-by: Ohad Vano <[email protected]>
  • Loading branch information
ohadvano authored Aug 26, 2024
1 parent 323bb7b commit df8705b
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 7 deletions.
48 changes: 48 additions & 0 deletions source/common/filter/config_discovery_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,41 @@ class UdpListenerDynamicFilterConfigProviderImpl
}
};

class UdpSessionDynamicFilterConfigProviderImpl
: public DynamicFilterConfigProviderImpl<Network::UdpSessionFilterFactoryCb> {
public:
UdpSessionDynamicFilterConfigProviderImpl(
FilterConfigSubscriptionSharedPtr& subscription,
const absl::flat_hash_set<std::string>& require_type_urls,
Server::Configuration::ServerFactoryContext&,
Server::Configuration::FactoryContext& factory_context,
ProtobufTypes::MessagePtr&& default_config, bool last_filter_in_filter_chain,
const std::string& filter_chain_type, absl::string_view stat_prefix,
const Network::ListenerFilterMatcherSharedPtr& listener_filter_matcher)
: DynamicFilterConfigProviderImpl<Network::UdpSessionFilterFactoryCb>(
subscription, require_type_urls, factory_context.serverFactoryContext().threadLocal(),
std::move(default_config), last_filter_in_filter_chain, filter_chain_type, stat_prefix,
listener_filter_matcher),
factory_context_(factory_context) {}

void validateMessage(const std::string&, const Protobuf::Message&,
const std::string&) const override {
// UDP session filters don't use the concept of terminal filters.
}

protected:
Server::Configuration::FactoryContext& factory_context_;

private:
absl::StatusOr<Network::UdpSessionFilterFactoryCb>
instantiateFilterFactory(const Protobuf::Message& message) const override {
auto* factory =
Registry::FactoryRegistry<Server::Configuration::NamedUdpSessionFilterConfigFactory>::
getFactoryByType(message.GetTypeName());
return factory->createFilterFactoryFromProto(message, factory_context_);
}
};

class QuicListenerDynamicFilterConfigProviderImpl
: public ListenerDynamicFilterConfigProviderImpl<Network::QuicListenerFilterFactoryCb> {
public:
Expand Down Expand Up @@ -774,6 +809,19 @@ class UdpListenerFilterConfigProviderManagerImpl
const std::string getConfigDumpType() const override { return "ecds_filter_udp_listener"; }
};

// UDP session filter
class UdpSessionFilterConfigProviderManagerImpl
: public FilterConfigProviderManagerImpl<
Server::Configuration::NamedUdpSessionFilterConfigFactory,
Network::UdpSessionFilterFactoryCb, Server::Configuration::FactoryContext,
UdpSessionDynamicFilterConfigProviderImpl> {
public:
absl::string_view statPrefix() const override { return "udp_session_filter."; }

protected:
const std::string getConfigDumpType() const override { return "ecds_filter_udp_session"; }
};

// QUIC listener filter
class QuicListenerFilterConfigProviderManagerImpl
: public FilterConfigProviderManagerImpl<
Expand Down
18 changes: 17 additions & 1 deletion source/extensions/filters/udp/udp_proxy/config.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "source/extensions/filters/udp/udp_proxy/config.h"

#include "source/common/filter/config_discovery_impl.h"
#include "source/common/formatter/substitution_format_string.h"

namespace Envoy {
Expand Down Expand Up @@ -88,6 +89,8 @@ UdpProxyFilterConfigImpl::UdpProxyFilterConfigImpl(
stats_(generateStats(config.stat_prefix(), context.scope())),
// Default prefer_gro to true for upstream client traffic.
upstream_socket_config_(config.upstream_socket_config(), true),
udp_session_filter_config_provider_manager_(
createSingletonUdpSessionFilterConfigProviderManager(context.serverFactoryContext())),
random_generator_(context.serverFactoryContext().api().randomGenerator()) {
if (use_per_packet_load_balancing_ && config.has_tunneling_config()) {
throw EnvoyException(
Expand Down Expand Up @@ -149,12 +152,25 @@ UdpProxyFilterConfigImpl::UdpProxyFilterConfigImpl(
Server::Configuration::NamedUdpSessionFilterConfigFactory>(filter);
ProtobufTypes::MessagePtr message = Envoy::Config::Utility::translateToFactoryConfig(
filter, context.messageValidationVisitor(), factory);

Network::UdpSessionFilterFactoryCb callback =
factory.createFilterFactoryFromProto(*message, context);
filter_factories_.push_back(callback);
filter_factories_.push_back(
udp_session_filter_config_provider_manager_->createStaticFilterConfigProvider(
callback, filter.name()));
}
}

SINGLETON_MANAGER_REGISTRATION(udp_session_filter_config_provider_manager);

std::shared_ptr<UdpSessionFilterConfigProviderManager>
UdpProxyFilterConfigImpl::createSingletonUdpSessionFilterConfigProviderManager(
Server::Configuration::ServerFactoryContext& context) {
return context.singletonManager().getTyped<UdpSessionFilterConfigProviderManager>(
SINGLETON_MANAGER_REGISTERED_NAME(udp_session_filter_config_provider_manager),
[] { return std::make_shared<Filter::UdpSessionFilterConfigProviderManagerImpl>(); });
}

static Registry::RegisterFactory<UdpProxyFilterConfigFactory,
Server::Configuration::NamedUdpListenerFilterConfigFactory>
register_;
Expand Down
23 changes: 20 additions & 3 deletions source/extensions/filters/udp/udp_proxy/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "envoy/extensions/filters/udp/udp_proxy/v3/udp_proxy.pb.h"
#include "envoy/extensions/filters/udp/udp_proxy/v3/udp_proxy.pb.validate.h"
#include "envoy/filter/config_provider_manager.h"
#include "envoy/server/filter_config.h"

#include "source/extensions/filters/udp/udp_proxy/udp_proxy_filter.h"
Expand Down Expand Up @@ -106,6 +107,12 @@ class TunnelingConfigImpl : public UdpTunnelingConfig {
bool propagate_response_trailers_;
};

using UdpSessionFilterConfigProviderManager =
Filter::FilterConfigProviderManager<Network::UdpSessionFilterFactoryCb,
Server::Configuration::FactoryContext>;
using UdpSessionFilterFactoriesList =
std::vector<Filter::FilterConfigProviderPtr<Network::UdpSessionFilterFactoryCb>>;

class UdpProxyFilterConfigImpl : public UdpProxyFilterConfig,
public UdpSessionFilterChainFactory,
Logger::Loggable<Logger::Id::config> {
Expand Down Expand Up @@ -151,8 +158,12 @@ class UdpProxyFilterConfigImpl : public UdpProxyFilterConfig,

// UdpSessionFilterChainFactory
void createFilterChain(Network::UdpSessionFilterChainFactoryCallbacks& callbacks) const override {
for (const Network::UdpSessionFilterFactoryCb& factory : filter_factories_) {
factory(callbacks);
for (const auto& filter_config_provider : filter_factories_) {
auto config = filter_config_provider->config();
if (config.has_value()) {
Network::UdpSessionFilterFactoryCb& factory = config.value();
factory(callbacks);
}
}
};

Expand All @@ -164,6 +175,10 @@ class UdpProxyFilterConfigImpl : public UdpProxyFilterConfig,
POOL_GAUGE_PREFIX(scope, final_prefix))};
}

std::shared_ptr<UdpSessionFilterConfigProviderManager>
createSingletonUdpSessionFilterConfigProviderManager(
Server::Configuration::ServerFactoryContext& context);

Upstream::ClusterManager& cluster_manager_;
TimeSource& time_source_;
Router::RouterConstSharedPtr router_;
Expand All @@ -178,7 +193,9 @@ class UdpProxyFilterConfigImpl : public UdpProxyFilterConfig,
std::vector<AccessLog::InstanceSharedPtr> session_access_logs_;
std::vector<AccessLog::InstanceSharedPtr> proxy_access_logs_;
UdpTunnelingConfigPtr tunneling_config_;
std::list<Network::UdpSessionFilterFactoryCb> filter_factories_;
std::shared_ptr<UdpSessionFilterConfigProviderManager>
udp_session_filter_config_provider_manager_;
UdpSessionFilterFactoriesList filter_factories_;
Random::RandomGenerator& random_generator_;
};

Expand Down
41 changes: 38 additions & 3 deletions test/common/filter/config_discovery_impl_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,22 @@ class TestUdpListenerFilterFactory
std::string name() const override { return "envoy.test.filter"; }
};

class TestUdpSessionFilterFactory
: public TestFilterFactory,
public Server::Configuration::NamedUdpSessionFilterConfigFactory {
public:
Network::UdpSessionFilterFactoryCb
createFilterFactoryFromProto(const Protobuf::Message&,
Server::Configuration::FactoryContext&) override {
created_ = true;
return [](Network::UdpSessionFilterChainFactoryCallbacks&) -> void {};
}
ProtobufTypes::MessagePtr createEmptyConfigProto() override {
return std::make_unique<ProtobufWkt::StringValue>();
}
std::string name() const override { return "envoy.test.filter"; }
};

class TestQuicListenerFilterFactory
: public TestFilterFactory,
public Server::Configuration::NamedQuicListenerFilterConfigFactory {
Expand Down Expand Up @@ -374,6 +390,23 @@ class UdpListenerFilterConfigDiscoveryImplTest
}
};

// UDP session filter test
class UdpSessionFilterConfigDiscoveryImplTest
: public FilterConfigDiscoveryImplTest<
Network::UdpSessionFilterFactoryCb, Server::Configuration::FactoryContext,
UdpSessionFilterConfigProviderManagerImpl, TestUdpSessionFilterFactory,
Server::Configuration::NamedUdpSessionFilterConfigFactory,
Server::Configuration::MockFactoryContext> {
public:
const std::string getFilterType() const override { return "udp_session"; }
const std::string getConfigReloadCounter() const override {
return "extension_config_discovery.udp_session_filter.foo.config_reload";
}
const std::string getConfigFailCounter() const override {
return "extension_config_discovery.udp_session_filter.foo.config_fail";
}
};

// QUIC listener filter test
class QuicListenerFilterConfigDiscoveryImplTest
: public FilterConfigDiscoveryImplTest<
Expand All @@ -393,7 +426,8 @@ class QuicListenerFilterConfigDiscoveryImplTest

/***************************************************************************************
* Parameterized test for *
* HTTP filter, Network filter, TCP listener filter And UDP listener filter *
* HTTP filter, Network filter, TCP listener filter, UDP session filter and *
* UDP listener filter *
* *
***************************************************************************************/
template <typename FilterConfigDiscoveryTestType>
Expand All @@ -404,7 +438,7 @@ using FilterConfigDiscoveryTestTypes = ::testing::Types<
HttpFilterConfigDiscoveryImplTest, HttpUpstreamFilterConfigDiscoveryImplTest,
NetworkFilterConfigDiscoveryImplTest, NetworkUpstreamFilterConfigDiscoveryImplTest,
TcpListenerFilterConfigDiscoveryImplTest, UdpListenerFilterConfigDiscoveryImplTest,
QuicListenerFilterConfigDiscoveryImplTest>;
UdpSessionFilterConfigDiscoveryImplTest, QuicListenerFilterConfigDiscoveryImplTest>;

TYPED_TEST_SUITE(FilterConfigDiscoveryImplTestParameter, FilterConfigDiscoveryTestTypes);

Expand Down Expand Up @@ -646,7 +680,8 @@ TYPED_TEST(FilterConfigDiscoveryImplTestParameter, TerminalFilterInvalid) {
EXPECT_CALL(config_discovery_test.init_watcher_, ready());

if (config_discovery_test.getFilterType() == "listener" ||
config_discovery_test.getFilterType() == "upstream_network") {
config_discovery_test.getFilterType() == "upstream_network" ||
config_discovery_test.getFilterType() == "udp_session") {
ASSERT_TRUE(config_discovery_test.callbacks_
->onConfigUpdate(decoded_resources.refvec_, response.version_info())
.ok());
Expand Down

0 comments on commit df8705b

Please sign in to comment.