diff --git a/api/envoy/config/listener/v3/BUILD b/api/envoy/config/listener/v3/BUILD index c2d6c133a73ae..f4f900c4db89f 100644 --- a/api/envoy/config/listener/v3/BUILD +++ b/api/envoy/config/listener/v3/BUILD @@ -11,6 +11,8 @@ api_proto_package( "//envoy/config/core/v3:pkg", "//envoy/type/v3:pkg", "@com_github_cncf_udpa//udpa/annotations:pkg", + "@com_github_cncf_udpa//xds/annotations/v3:pkg", "@com_github_cncf_udpa//xds/core/v3:pkg", + "@com_github_cncf_udpa//xds/type/matcher/v3:pkg", ], ) diff --git a/api/envoy/config/listener/v3/listener.proto b/api/envoy/config/listener/v3/listener.proto index df64bb8e50028..b4ef416e00a26 100644 --- a/api/envoy/config/listener/v3/listener.proto +++ b/api/envoy/config/listener/v3/listener.proto @@ -13,7 +13,9 @@ import "envoy/config/listener/v3/udp_listener_config.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/wrappers.proto"; +import "xds/annotations/v3/status.proto"; import "xds/core/v3/collection_entry.proto"; +import "xds/type/matcher/v3/matcher.proto"; import "envoy/annotations/deprecation.proto"; import "udpa/annotations/security.proto"; @@ -36,7 +38,7 @@ message ListenerCollection { repeated xds.core.v3.CollectionEntry entries = 1; } -// [#next-free-field: 32] +// [#next-free-field: 33] message Listener { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.Listener"; @@ -120,6 +122,25 @@ message Listener { // :ref:`FAQ entry `. repeated FilterChain filter_chains = 3; + // :ref:`Matcher API ` resolving the filter chain name from the + // network properties. This matcher is used as a replacement for the filter chain match condition + // :ref:`filter_chain_match + // `. If specified, all + // :ref:`filter_chains ` must have a + // non-empty and unique :ref:`name ` field + // and not specify :ref:`filter_chain_match + // ` field. + // + // .. note:: + // + // Once matched, each connection is permanently bound to its filter chain. + // If the matcher changes but the filter chain remains the same, the + // connections bound to the filter chain are not drained. If, however, the + // filter chain is removed or structurally modified, then the drain for its + // connections is initiated. + xds.type.matcher.v3.Matcher filter_chain_matcher = 32 + [(xds.annotations.v3.field_status).work_in_progress = true]; + // If a connection is redirected using *iptables*, the port on which the proxy // receives it might be different from the original destination address. When this flag is set to // true, the listener hands off redirected connections to the listener associated with the diff --git a/api/envoy/config/listener/v3/listener_components.proto b/api/envoy/config/listener/v3/listener_components.proto index 13501fb30d7a9..aed27c3714806 100644 --- a/api/envoy/config/listener/v3/listener_components.proto +++ b/api/envoy/config/listener/v3/listener_components.proto @@ -11,6 +11,8 @@ import "google/protobuf/any.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/wrappers.proto"; +import "xds/annotations/v3/status.proto"; + import "envoy/annotations/deprecation.proto"; import "udpa/annotations/status.proto"; import "udpa/annotations/versioning.proto"; @@ -258,10 +260,11 @@ message FilterChain { // establishment, the connection is summarily closed. google.protobuf.Duration transport_socket_connect_timeout = 9; - // [#not-implemented-hide:] The unique name (or empty) by which this filter chain is known. If no - // name is provided, Envoy will allocate an internal UUID for the filter chain. If the filter - // chain is to be dynamically updated or removed via FCDS a unique name must be provided. - string name = 7; + // The unique name (or empty) by which this filter chain is known. + // Note: :ref:`filter_chain_matcher + // ` + // requires that filter chains are uniquely named within a listener. + string name = 7 [(xds.annotations.v3.field_status).work_in_progress = true]; // [#not-implemented-hide:] The configuration to specify whether the filter chain will be built on-demand. // If this field is not empty, the filter chain will be built on-demand. diff --git a/docs/root/intro/arch_overview/advanced/matching/_include/listener_complicated.yaml b/docs/root/intro/arch_overview/advanced/matching/_include/listener_complicated.yaml new file mode 100644 index 0000000000000..771699290b9c4 --- /dev/null +++ b/docs/root/intro/arch_overview/advanced/matching/_include/listener_complicated.yaml @@ -0,0 +1,114 @@ +static_resources: + listeners: + - name: outbound + address: + socket_address: + protocol: TCP + address: 0.0.0.0 + port_value: 15000 + listener_filters: + - name: original_dst + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.listener.original_dst.v3.OriginalDst + traffic_direction: OUTBOUND + filter_chains: + - name: http + filters: + - name: http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: ingress_http + route_config: + name: local_route + virtual_hosts: + - name: local_service + domains: ["*"] + routes: + - match: + prefix: "/" + route: + cluster: some_service + http_filters: + - name: router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + - name: internal + filters: + - name: tcp_proxy + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + stat_prefix: internal + cluster: some_service + - name: tls + transport_socket: + name: tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + common_tls_context: + tls_certificates: + - certificate_chain: {filename: "certs/servercert.pem"} + private_key: {filename: "certs/serverkey.pem"} + filters: + - name: tcp_proxy + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + stat_prefix: tls + cluster: some_service +# Snippet: 58-102 + filter_chain_matcher: + matcher_tree: + input: + name: port + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.DestinationPortInput + exact_match_map: + map: + "80": + action: + name: http + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: http + "443": + matcher: + matcher_tree: + input: + name: ip + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.SourceIPInput + custom_match: + name: ip-matcher + typed_config: + "@type": type.googleapis.com/xds.type.matcher.v3.IPMatcher + range_matchers: + - ranges: + - address_prefix: 192.0.0.0 + prefix_len: 2 + - address_prefix: 10.0.0.0 + prefix_len: 24 + on_match: + action: + name: internal + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: internal + - ranges: + - address_prefix: 0.0.0.0 + on_match: + action: + name: tls + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: tls + + clusters: + - name: some_service + load_assignment: + cluster_name: some_service + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 10.1.2.10 + port_value: 10002 diff --git a/docs/root/intro/arch_overview/advanced/matching/_include/listener_tls.yaml b/docs/root/intro/arch_overview/advanced/matching/_include/listener_tls.yaml new file mode 100644 index 0000000000000..7c7337cb04a3f --- /dev/null +++ b/docs/root/intro/arch_overview/advanced/matching/_include/listener_tls.yaml @@ -0,0 +1,68 @@ +static_resources: + listeners: + - name: outbound + address: + socket_address: + protocol: TCP + address: 0.0.0.0 + port_value: 8443 + listener_filters: + - name: tls_inspector + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector + filter_chains: + - name: tls + transport_socket: + name: tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + common_tls_context: + tls_certificates: + - certificate_chain: {filename: "certs/servercert.pem"} + private_key: {filename: "certs/serverkey.pem"} + filters: + - name: tcp_proxy + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + stat_prefix: tls + cluster: some_service + - name: plaintext + filters: + - name: tcp_proxy + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + stat_prefix: plaintext + cluster: some_service +# Snippet: 37-56 + filter_chain_matcher: + matcher_tree: + input: + name: transport + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.TransportProtocolInput + exact_match_map: + map: + "tls": + action: + name: tls + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: tls + on_no_match: + action: + name: plaintext + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: plaintext + + clusters: + - name: some_service + load_assignment: + cluster_name: some_service + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 10.1.2.10 + port_value: 10002 diff --git a/docs/root/intro/arch_overview/advanced/matching/_include/listener_vip.yaml b/docs/root/intro/arch_overview/advanced/matching/_include/listener_vip.yaml new file mode 100644 index 0000000000000..261fa84469a7b --- /dev/null +++ b/docs/root/intro/arch_overview/advanced/matching/_include/listener_vip.yaml @@ -0,0 +1,53 @@ +static_resources: + listeners: + - name: outbound + address: + socket_address: + protocol: TCP + address: 0.0.0.0 + port_value: 15000 + listener_filters: + - name: proxy_protocol + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.listener.proxy_protocol.v3.ProxyProtocol + filter_chains: + - name: vip + filters: + - name: tcp_proxy + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + stat_prefix: vip + cluster: original_dst + - name: default + filters: + - name: tcp_proxy + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + stat_prefix: default + cluster: original_dst +# Snippet: 29-48 + filter_chain_matcher: + matcher_tree: + input: + name: destination_ip + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.DestinationIPInput + prefix_match_map: + map: + "10.0.0.": + action: + name: vip + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: vip + on_no_match: + action: + name: default + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: default + + clusters: + - name: original_dst + type: ORIGINAL_DST + lb_policy: CLUSTER_PROVIDED diff --git a/docs/root/intro/arch_overview/advanced/matching/matching.rst b/docs/root/intro/arch_overview/advanced/matching/matching.rst index a08746363104a..c4b4e20eaf871 100644 --- a/docs/root/intro/arch_overview/advanced/matching/matching.rst +++ b/docs/root/intro/arch_overview/advanced/matching/matching.rst @@ -5,3 +5,4 @@ Generic Matching :maxdepth: 2 matching_api + matching_listener diff --git a/docs/root/intro/arch_overview/advanced/matching/matching_listener.rst b/docs/root/intro/arch_overview/advanced/matching/matching_listener.rst new file mode 100644 index 0000000000000..b02eada396b22 --- /dev/null +++ b/docs/root/intro/arch_overview/advanced/matching/matching_listener.rst @@ -0,0 +1,63 @@ +.. _arch_overview_matching_listener: + +Matching Filter Chains in Listeners +=================================== + +Envoy listeners implement the :ref:`matching API ` for selecting a filter +chain based on a collection of :ref:`network inputs `. Matching is done +once per connection. Connections are drained when the associated named filter chain configuration changes, but not when +the filter chain matcher is the only updated field in a listener. + +The action in the matcher API must be a string value corresponding to the name of the filter chain. If there is no +filter chain with the given name, the match fails, and the :ref:`default filter chain +` is used if specified, or the connection is +rejected. Filter chain matcher requires that all filter chains in a listener are uniquely named. + +The matcher API replaces the existing filter :ref:`filter_chain_match +` field. When using the matcher API, the filter +chain match field is ignored and should not be set. + +Examples +######## + +Detect TLS traffic +****************** + +The following examples uses :ref:`tls_inspector ` listener filter to detect +whether the transport appears to be TLS, in which case the matcher in the listener selects the filter chain ``tls``. +Otherwise, the filter chain ``plaintext`` is used. + +.. literalinclude:: _include/listener_tls.yaml + :language: yaml + :lines: 37-56 + :caption: :download:`listener_tls.yaml <_include/listener_tls.yaml>` + +Match Against the Destination IP +******************************** + +The following example assumes :ref:`PROXY protocol ` is used for incoming +traffic. If the recovered destination IP is in CIDR ``10.0.0.0/24``, then the filter chain ``vip`` is used. Otherwise, +the filter chain ``default`` is used. + +.. literalinclude:: _include/listener_vip.yaml + :language: yaml + :lines: 29-48 + :caption: :download:`listener_vip.yaml <_include/listener_vip.yaml>` + +Match Against the Destination Port and the Source IP +**************************************************** + +The following example uses :ref:`original_dst ` listener filter to recover the +original destination port. The matcher in the listener selects one of the three filter chains ``http``, ``internal``, +and ``tls`` as follows: + +* If the destination port is ``80``, then the filter chain ``http`` accepts the connection. +* If the destination port is ``443`` and the source IP is in the range ``192.0.0.0/2`` or ``10.0.0.0/24``, then the + filter chain ``internal`` accepts the connection. If the source IP is not in the ranges then the filter chain ``tls`` + accepts the connection. +* Otherwise, the connection is rejected, because there is no default filter chain. + +.. literalinclude:: _include/listener_complicated.yaml + :language: yaml + :lines: 58-102 + :caption: :download:`listener_complicated.yaml <_include/listener_complicated.yaml>` diff --git a/source/server/BUILD b/source/server/BUILD index edb978f0b9e63..4350e56378437 100644 --- a/source/server/BUILD +++ b/source/server/BUILD @@ -540,14 +540,19 @@ envoy_cc_library( deps = [ ":filter_chain_factory_context_callback", "//envoy/config:typed_metadata_interface", + "//envoy/matcher:matcher_interface", + "//envoy/network:filter_interface", "//envoy/server:instance_interface", "//envoy/server:listener_manager_interface", "//envoy/server:transport_socket_config_interface", "//source/common/common:empty_string", "//source/common/config:utility_lib", "//source/common/init:manager_lib", + "//source/common/matcher:matcher_lib", "//source/common/network:cidr_range_lib", "//source/common/network:lc_trie_lib", + "//source/common/network/matching:data_impl_lib", + "//source/common/network/matching:inputs_lib", "//source/server:configuration_lib", "@envoy_api//envoy/config/listener/v3:pkg_cc_proto", ], diff --git a/source/server/filter_chain_manager_impl.cc b/source/server/filter_chain_manager_impl.cc index 224315b7e245b..cc54e304814dc 100644 --- a/source/server/filter_chain_manager_impl.cc +++ b/source/server/filter_chain_manager_impl.cc @@ -6,6 +6,9 @@ #include "source/common/common/empty_string.h" #include "source/common/common/fmt.h" #include "source/common/config/utility.h" +#include "source/common/matcher/matcher.h" +#include "source/common/network/matching/data_impl.h" +#include "source/common/network/matching/inputs.h" #include "source/common/network/socket_interface.h" #include "source/common/protobuf/utility.h" #include "source/server/configuration_impl.h" @@ -27,6 +30,48 @@ Network::Address::InstanceConstSharedPtr fakeAddress() { Network::Utility::parseInternetAddress("255.255.255.255")); } +struct FilterChainNameAction : public Matcher::ActionBase { + explicit FilterChainNameAction(Network::DrainableFilterChainSharedPtr chain) : chain_(chain) {} + const Network::DrainableFilterChainSharedPtr chain_; +}; + +using FilterChainActionFactoryContext = + absl::flat_hash_map; + +class FilterChainNameActionFactory : public Matcher::ActionFactory, + Logger::Loggable { +public: + std::string name() const override { return "filter-chain-name"; } + Matcher::ActionFactoryCb createActionFactoryCb(const Protobuf::Message& config, + FilterChainActionFactoryContext& filter_chains, + ProtobufMessage::ValidationVisitor&) override { + Network::DrainableFilterChainSharedPtr chain = nullptr; + const auto& name = dynamic_cast(config); + const auto chain_match = filter_chains.find(name.value()); + if (chain_match != filter_chains.end()) { + chain = chain_match->second; + } else { + ENVOY_LOG(debug, "matcher API points to an absent filter chain '{}'", name.value()); + } + return [chain]() { return std::make_unique(chain); }; + } + ProtobufTypes::MessagePtr createEmptyConfigProto() override { + return std::make_unique(); + } +}; + +REGISTER_FACTORY(FilterChainNameActionFactory, + Matcher::ActionFactory); + +class FilterChainNameActionValidationVisitor + : public Matcher::MatchTreeValidationVisitor { +public: + absl::Status performDataInputValidation(const Matcher::DataInputFactory&, + absl::string_view) override { + return absl::OkStatus(); + } +}; + } // namespace PerFilterChainFactoryContextImpl::PerFilterChainFactoryContextImpl( @@ -160,6 +205,7 @@ bool FilterChainManagerImpl::isWildcardServerName(const std::string& name) { } void FilterChainManagerImpl::addFilterChains( + const xds::type::matcher::v3::Matcher* filter_chain_matcher, absl::Span filter_chain_span, const envoy::config::listener::v3::FilterChain* default_filter_chain, FilterChainFactoryBuilder& filter_chain_factory_builder, @@ -169,6 +215,8 @@ void FilterChainManagerImpl::addFilterChains( MessageUtil> filter_chains; uint32_t new_filter_chain_size = 0; + absl::flat_hash_map filter_chains_by_name; + for (const auto& filter_chain : filter_chain_span) { const auto& filter_chain_match = filter_chain->filter_chain_match(); if (!filter_chain_match.address_suffix().empty() || filter_chain_match.has_suffix_len()) { @@ -176,43 +224,15 @@ void FilterChainManagerImpl::addFilterChains( "unimplemented fields", address_->asString(), filter_chain->name())); } - const auto& matching_iter = filter_chains.find(filter_chain_match); - if (matching_iter != filter_chains.end()) { - throw EnvoyException(fmt::format("error adding listener '{}': filter chain '{}' has " - "the same matching rules defined as '{}'", - address_->asString(), filter_chain->name(), - matching_iter->second)); - } - filter_chains.insert({filter_chain_match, filter_chain->name()}); - - auto createAddressVector = [](const auto& prefix_ranges) -> std::vector { - std::vector ips; - ips.reserve(prefix_ranges.size()); - for (const auto& ip : prefix_ranges) { - const auto& cidr_range = Network::Address::CidrRange::create(ip); - ips.push_back(cidr_range.asString()); - } - return ips; - }; - - // Validate IP addresses. - std::vector destination_ips = - createAddressVector(filter_chain_match.prefix_ranges()); - std::vector source_ips = - createAddressVector(filter_chain_match.source_prefix_ranges()); - std::vector direct_source_ips = - createAddressVector(filter_chain_match.direct_source_prefix_ranges()); - - std::vector server_names; - // Reject partial wildcards, we don't match on them. - for (const auto& server_name : filter_chain_match.server_names()) { - if (server_name.find('*') != std::string::npos && !isWildcardServerName(server_name)) { - throw EnvoyException( - fmt::format("error adding listener '{}': partial wildcards are not supported in " - "\"server_names\"", - address_->asString())); + if (!filter_chain_matcher) { + const auto& matching_iter = filter_chains.find(filter_chain_match); + if (matching_iter != filter_chains.end()) { + throw EnvoyException(fmt::format("error adding listener '{}': filter chain '{}' has " + "the same matching rules defined as '{}'", + address_->asString(), filter_chain->name(), + matching_iter->second)); } - server_names.push_back(absl::AsciiStrToLower(server_name)); + filter_chains.insert({filter_chain_match, filter_chain->name()}); } // Reuse created filter chain if possible. @@ -225,19 +245,75 @@ void FilterChainManagerImpl::addFilterChains( ++new_filter_chain_size; } - addFilterChainForDestinationPorts( - destination_ports_map_, - PROTOBUF_GET_WRAPPED_OR_DEFAULT(filter_chain_match, destination_port, 0), destination_ips, - server_names, filter_chain_match.transport_protocol(), - filter_chain_match.application_protocols(), direct_source_ips, - filter_chain_match.source_type(), source_ips, filter_chain_match.source_ports(), - filter_chain_impl); + // If using the matcher, require usage of "name" field and skip building the index. + if (filter_chain_matcher) { + if (filter_chain->name().empty()) { + throw EnvoyException(fmt::format( + "error adding listener '{}': \"name\" field is required when using a listener matcher", + address_->asString())); + } + auto [_, inserted] = + filter_chains_by_name.try_emplace(filter_chain->name(), filter_chain_impl); + if (!inserted) { + throw EnvoyException( + fmt::format("error adding listener '{}': \"name\" field is duplicated with value '{}'", + address_->asString(), filter_chain->name())); + } + if (filter_chain->has_filter_chain_match()) { + ENVOY_LOG(debug, "filter chain match in chain '{}' is ignored", filter_chain->name()); + } + } else { + auto createAddressVector = [](const auto& prefix_ranges) -> std::vector { + std::vector ips; + ips.reserve(prefix_ranges.size()); + for (const auto& ip : prefix_ranges) { + const auto& cidr_range = Network::Address::CidrRange::create(ip); + ips.push_back(cidr_range.asString()); + } + return ips; + }; + + // Validate IP addresses. + std::vector destination_ips = + createAddressVector(filter_chain_match.prefix_ranges()); + std::vector source_ips = + createAddressVector(filter_chain_match.source_prefix_ranges()); + std::vector direct_source_ips = + createAddressVector(filter_chain_match.direct_source_prefix_ranges()); + + std::vector server_names; + // Reject partial wildcards, we don't match on them. + for (const auto& server_name : filter_chain_match.server_names()) { + if (server_name.find('*') != std::string::npos && !isWildcardServerName(server_name)) { + throw EnvoyException( + fmt::format("error adding listener '{}': partial wildcards are not supported in " + "\"server_names\"", + address_->asString())); + } + server_names.push_back(absl::AsciiStrToLower(server_name)); + } + + addFilterChainForDestinationPorts( + destination_ports_map_, + PROTOBUF_GET_WRAPPED_OR_DEFAULT(filter_chain_match, destination_port, 0), destination_ips, + server_names, filter_chain_match.transport_protocol(), + filter_chain_match.application_protocols(), direct_source_ips, + filter_chain_match.source_type(), source_ips, filter_chain_match.source_ports(), + filter_chain_impl); + } fc_contexts_[*filter_chain] = filter_chain_impl; } convertIPsToTries(); copyOrRebuildDefaultFilterChain(default_filter_chain, filter_chain_factory_builder, context_creator); + // Construct matcher if it is present in the listener configuration. + if (filter_chain_matcher) { + FilterChainNameActionValidationVisitor validation_visitor; + Matcher::MatchTreeFactory factory( + filter_chains_by_name, parent_context_.getServerFactoryContext(), validation_visitor); + matcher_ = factory.create(*filter_chain_matcher)(); + } ENVOY_LOG(debug, "new fc_contexts has {} filter chains, including {} newly built", fc_contexts_.size(), new_filter_chain_size); } @@ -468,6 +544,10 @@ std::pair> makeCidrListEntry(const s const Network::FilterChain* FilterChainManagerImpl::findFilterChain(const Network::ConnectionSocket& socket) const { + if (matcher_) { + return findFilterChainUsingMatcher(socket); + } + const auto& address = socket.connectionInfoProvider().localAddress(); const Network::FilterChain* best_match_filter_chain = nullptr; @@ -496,6 +576,19 @@ FilterChainManagerImpl::findFilterChain(const Network::ConnectionSocket& socket) : default_filter_chain_.get(); } +const Network::FilterChain* +FilterChainManagerImpl::findFilterChainUsingMatcher(const Network::ConnectionSocket& socket) const { + Network::Matching::MatchingDataImpl data(socket); + const auto& match_result = Matcher::evaluateMatch(*matcher_, data); + ASSERT(match_result.match_state_ == Matcher::MatchState::MatchComplete, + "Matching must complete for network streams."); + if (match_result.result_) { + const auto result = match_result.result_(); + return result->getTyped().chain_.get(); + } + return default_filter_chain_.get(); +} + const Network::FilterChain* FilterChainManagerImpl::findFilterChainForDestinationIP( const DestinationIPsTrie& destination_ips_trie, const Network::ConnectionSocket& socket) const { auto address = socket.connectionInfoProvider().localAddress(); diff --git a/source/server/filter_chain_manager_impl.h b/source/server/filter_chain_manager_impl.h index 04f9565d5fdb2..e3322602c35f1 100644 --- a/source/server/filter_chain_manager_impl.h +++ b/source/server/filter_chain_manager_impl.h @@ -6,7 +6,9 @@ #include "envoy/config/listener/v3/listener_components.pb.h" #include "envoy/config/typed_metadata.h" +#include "envoy/matcher/matcher.h" #include "envoy/network/drain_decision.h" +#include "envoy/network/filter.h" #include "envoy/server/filter_config.h" #include "envoy/server/instance.h" #include "envoy/server/options.h" @@ -217,6 +219,7 @@ class FilterChainManagerImpl : public Network::FilterChainManager, // Add all filter chains into this manager. During the lifetime of FilterChainManagerImpl this // should be called at most once. void addFilterChains( + const xds::type::matcher::v3::Matcher* filter_chain_matcher, absl::Span filter_chain_span, const envoy::config::listener::v3::FilterChain* default_filter_chain, FilterChainFactoryBuilder& filter_chain_factory_builder, @@ -237,6 +240,8 @@ class FilterChainManagerImpl : public Network::FilterChainManager, private: void convertIPsToTries(); + const Network::FilterChain* + findFilterChainUsingMatcher(const Network::ConnectionSocket& socket) const; // Build default filter chain from filter chain message. Skip the build but copy from original // filter chain manager if the default filter chain message duplicates the message in origin @@ -387,6 +392,9 @@ class FilterChainManagerImpl : public Network::FilterChainManager, // init manager owned by the corresponding listener. The reference is valid when building the // filter chain. Init::Manager& init_manager_; + + // Matcher selecting the filter chain name. + Matcher::MatchTreePtr matcher_; }; } // namespace Server } // namespace Envoy diff --git a/source/server/listener_impl.cc b/source/server/listener_impl.cc index 9fdc5f84d8870..957c62694279f 100644 --- a/source/server/listener_impl.cc +++ b/source/server/listener_impl.cc @@ -655,6 +655,7 @@ void ListenerImpl::buildFilterChains() { transport_factory_context_->setInitManager(*dynamic_init_manager_); ListenerFilterChainFactoryBuilder builder(*this, *transport_factory_context_); filter_chain_manager_.addFilterChains( + config_.has_filter_chain_matcher() ? &config_.filter_chain_matcher() : nullptr, config_.filter_chains(), config_.has_default_filter_chain() ? &config_.default_filter_chain() : nullptr, builder, filter_chain_manager_); @@ -974,6 +975,8 @@ bool ListenerMessageUtil::filterChainOnlyChange(const envoy::config::listener::v envoy::config::listener::v3::Listener::GetDescriptor()->FindFieldByName("filter_chains")); differencer.IgnoreField(envoy::config::listener::v3::Listener::GetDescriptor()->FindFieldByName( "default_filter_chain")); + differencer.IgnoreField(envoy::config::listener::v3::Listener::GetDescriptor()->FindFieldByName( + "filter_chain_matcher")); return differencer.Compare(lhs, rhs); } diff --git a/test/integration/xds_integration_test.cc b/test/integration/xds_integration_test.cc index 32f471d10b7a8..fdd4ff666d35f 100644 --- a/test/integration/xds_integration_test.cc +++ b/test/integration/xds_integration_test.cc @@ -103,14 +103,39 @@ TEST_P(UdpaXdsIntegrationTestListCollection, RouterRequestAndResponseWithBodyNoB } class LdsInplaceUpdateTcpProxyIntegrationTest - : public testing::TestWithParam, + : public testing::TestWithParam>, public BaseIntegrationTest { public: LdsInplaceUpdateTcpProxyIntegrationTest() - : BaseIntegrationTest(GetParam(), ConfigHelper::baseConfig() + R"EOF( + : BaseIntegrationTest(std::get<0>(GetParam()), ConfigHelper::baseConfig() + + (std::get<1>(GetParam()) ? R"EOF( + filter_chain_matcher: + matcher_tree: + input: + name: alpn + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.ApplicationProtocolInput + exact_match_map: + map: + "'alpn0'": + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + "'alpn1'": + action: + name: bar + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: bar +)EOF" + : "") + + R"EOF( filter_chains: - filter_chain_match: application_protocols: ["alpn0"] + name: foo filters: - name: envoy.filters.network.tcp_proxy typed_config: @@ -119,6 +144,7 @@ class LdsInplaceUpdateTcpProxyIntegrationTest cluster: cluster_0 - filter_chain_match: application_protocols: ["alpn1"] + name: bar filters: - name: envoy.filters.network.tcp_proxy typed_config: @@ -137,7 +163,8 @@ class LdsInplaceUpdateTcpProxyIntegrationTest "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy stat_prefix: tcp_stats cluster: cluster_0 -)EOF") {} +)EOF"), + matcher_(std::get<1>(GetParam())) {} void initialize() override { config_helper_.renameListener("tcp"); @@ -182,6 +209,7 @@ class LdsInplaceUpdateTcpProxyIntegrationTest std::unique_ptr context_manager_; Network::TransportSocketFactoryPtr context_; testing::NiceMock secret_manager_; + bool matcher_; }; // Verify that tcp connection 1 is closed while client 0 survives when deleting filter chain 1. @@ -206,6 +234,24 @@ TEST_P(LdsInplaceUpdateTcpProxyIntegrationTest, ReloadConfigDeletingFilterChain) [&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { auto* listener = bootstrap.mutable_static_resources()->mutable_listeners(0); listener->mutable_filter_chains()->RemoveLast(); + if (matcher_) { + TestUtility::loadFromYaml(R"EOF( + matcher_tree: + input: + name: alpn + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.ApplicationProtocolInput + exact_match_map: + map: + "'alpn0'": + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF", + *listener->mutable_filter_chain_matcher()); + } }); new_config_helper.setLds("1"); test_server_->waitForCounterGe("listener_manager.listener_in_place_updated", 1); @@ -251,6 +297,25 @@ TEST_P(LdsInplaceUpdateTcpProxyIntegrationTest, ReloadConfigAddingFilterChain) { *listener->mutable_filter_chains(2) ->mutable_filter_chain_match() ->mutable_application_protocols(0) = "alpn2"; + listener->mutable_filter_chains(2)->set_name("baz"); + if (matcher_) { + TestUtility::loadFromYaml(R"EOF( + matcher_tree: + input: + name: alpn + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.ApplicationProtocolInput + exact_match_map: + map: + "'alpn2'": + action: + name: baz + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: baz + )EOF", + *listener->mutable_filter_chain_matcher()); + } }); new_config_helper.setLds("1"); test_server_->waitForCounterGe("listener_manager.listener_in_place_updated", 1); @@ -289,10 +354,12 @@ TEST_P(LdsInplaceUpdateTcpProxyIntegrationTest, ReloadConfigAddingFilterChain) { } class LdsInplaceUpdateHttpIntegrationTest - : public testing::TestWithParam, + : public testing::TestWithParam>, public HttpIntegrationTest { public: - LdsInplaceUpdateHttpIntegrationTest() : HttpIntegrationTest(Http::CodecType::HTTP1, GetParam()) {} + LdsInplaceUpdateHttpIntegrationTest() + : HttpIntegrationTest(Http::CodecType::HTTP1, std::get<0>(GetParam())), + matcher_(std::get<1>(GetParam())) {} void inplaceInitialize(bool add_default_filter_chain = false) { autonomous_upstream_ = true; @@ -316,6 +383,7 @@ class LdsInplaceUpdateHttpIntegrationTest bootstrap.mutable_static_resources()->mutable_listeners(0)->mutable_filter_chains(0); *filter_chain_0->mutable_filter_chain_match()->mutable_application_protocols()->Add() = "alpn0"; + filter_chain_0->set_name("alpn0"); auto* filter_chain_1 = bootstrap.mutable_static_resources() ->mutable_listeners(0) ->mutable_filter_chains() @@ -325,6 +393,7 @@ class LdsInplaceUpdateHttpIntegrationTest // filter chain 1 // alpn1, route to cluster_1 *filter_chain_1->mutable_filter_chain_match()->mutable_application_protocols(0) = "alpn1"; + filter_chain_1->set_name("alpn1"); auto* config_blob = filter_chain_1->mutable_filters(0)->mutable_typed_config(); @@ -349,6 +418,39 @@ class LdsInplaceUpdateHttpIntegrationTest ->mutable_listeners(0) ->mutable_default_filter_chain(); default_filter_chain->MergeFrom(*filter_chain_0); + default_filter_chain->set_name("default"); + } + if (matcher_) { + TestUtility::loadFromYaml(R"EOF( + matcher_tree: + input: + name: alpn + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.ApplicationProtocolInput + exact_match_map: + map: + "'alpn0'": + action: + name: alpn0 + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: alpn0 + "'alpn1'": + action: + name: alpn1 + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: alpn1 + "'alpn2'": + action: + name: alpn2 + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: alpn2 + )EOF", + *bootstrap.mutable_static_resources() + ->mutable_listeners(0) + ->mutable_filter_chain_matcher()); } }); @@ -397,6 +499,7 @@ class LdsInplaceUpdateHttpIntegrationTest testing::NiceMock secret_manager_; Network::Address::InstanceConstSharedPtr address_; bool use_default_balancer_{false}; + bool matcher_; }; // Verify that http response on filter chain 1 and default filter chain have "Connection: close" @@ -457,10 +560,12 @@ TEST_P(LdsInplaceUpdateHttpIntegrationTest, ReloadConfigAddingFilterChain) { *listener->mutable_filter_chains(2) ->mutable_filter_chain_match() ->mutable_application_protocols(0) = "alpn2"; + listener->mutable_filter_chains(2)->set_name("alpn2"); auto default_filter_chain = bootstrap.mutable_static_resources()->mutable_listeners(0)->mutable_default_filter_chain(); default_filter_chain->MergeFrom(*listener->mutable_filter_chains(1)); + default_filter_chain->set_name("default"); }); new_config_helper.setLds("1"); test_server_->waitForCounterGe("listener_manager.listener_in_place_updated", 1); @@ -534,13 +639,15 @@ TEST_P(LdsInplaceUpdateHttpIntegrationTest, OverlappingFilterChainServesNewConne // Verify default filter chain update is filter chain only update. TEST_P(LdsInplaceUpdateHttpIntegrationTest, DefaultFilterChainUpdate) {} -INSTANTIATE_TEST_SUITE_P(IpVersions, LdsInplaceUpdateHttpIntegrationTest, - testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), - TestUtility::ipTestParamsToString); +INSTANTIATE_TEST_SUITE_P( + IpVersionsAndMatcher, LdsInplaceUpdateHttpIntegrationTest, + testing::Combine(testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), + testing::Values(false, true))); -INSTANTIATE_TEST_SUITE_P(IpVersions, LdsInplaceUpdateTcpProxyIntegrationTest, - testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), - TestUtility::ipTestParamsToString); +INSTANTIATE_TEST_SUITE_P( + IpVersionsAndMatcher, LdsInplaceUpdateTcpProxyIntegrationTest, + testing::Combine(testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), + testing::Values(false, true))); using LdsIntegrationTest = HttpProtocolIntegrationTest; @@ -627,9 +734,10 @@ TEST_P(LdsIntegrationTest, FailConfigLoad) { class LdsStsIntegrationTest : public Event::SimulatedTimeSystem, public LdsInplaceUpdateTcpProxyIntegrationTest {}; -INSTANTIATE_TEST_SUITE_P(IpVersions, LdsStsIntegrationTest, - testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), - TestUtility::ipTestParamsToString); +INSTANTIATE_TEST_SUITE_P( + IpVersionsAndMatcher, LdsStsIntegrationTest, + testing::Combine(testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), + testing::Values(false, true))); // Verify that the listener in place update will accomplish anyway if the listener is removed. TEST_P(LdsStsIntegrationTest, TcpListenerRemoveFilterChainCalledAfterListenerIsRemoved) { diff --git a/test/server/BUILD b/test/server/BUILD index 27170db1790fe..9852322591cb5 100644 --- a/test/server/BUILD +++ b/test/server/BUILD @@ -286,6 +286,7 @@ envoy_cc_test_library( data = ["//test/extensions/transport_sockets/tls/test_data:certs"], deps = [ "//source/common/init:manager_lib", + "//source/extensions/common/matcher:trie_matcher_lib", "//source/server:listener_manager_lib", "//test/mocks/init:init_mocks", "//test/mocks/matcher:matcher_mocks", @@ -322,6 +323,7 @@ envoy_cc_test( "//source/common/protobuf", "//source/extensions/filters/listener/original_dst:config", "//source/extensions/filters/listener/proxy_protocol:config", + "//source/extensions/filters/listener/tls_inspector:config", "//source/extensions/filters/network/http_connection_manager:config", "//source/extensions/filters/network/tcp_proxy:config", "//source/extensions/request_id/uuid:config", diff --git a/test/server/filter_chain_benchmark_test.cc b/test/server/filter_chain_benchmark_test.cc index f793cb07bf231..de3c28389a622 100644 --- a/test/server/filter_chain_benchmark_test.cc +++ b/test/server/filter_chain_benchmark_test.cc @@ -231,7 +231,7 @@ BENCHMARK_DEFINE_F(FilterChainBenchmarkFixture, FilterChainManagerBuildTest) FilterChainManagerImpl filter_chain_manager{ std::make_shared("127.0.0.1", 1234), factory_context, init_manager_}; - filter_chain_manager.addFilterChains(filter_chains_, nullptr, dummy_builder_, + filter_chain_manager.addFilterChains(nullptr, filter_chains_, nullptr, dummy_builder_, filter_chain_manager); } } @@ -255,7 +255,7 @@ BENCHMARK_DEFINE_F(FilterChainBenchmarkFixture, FilterChainFindTest) std::make_shared("127.0.0.1", 1234), factory_context, init_manager_}; - filter_chain_manager.addFilterChains(filter_chains_, nullptr, dummy_builder_, + filter_chain_manager.addFilterChains(nullptr, filter_chains_, nullptr, dummy_builder_, filter_chain_manager); for (auto _ : state) { UNREFERENCED_PARAMETER(_); diff --git a/test/server/filter_chain_manager_impl_test.cc b/test/server/filter_chain_manager_impl_test.cc index e62d8c399da0f..11d09c45258e6 100644 --- a/test/server/filter_chain_manager_impl_test.cc +++ b/test/server/filter_chain_manager_impl_test.cc @@ -55,7 +55,7 @@ class MockFilterChainFactoryBuilder : public FilterChainFactoryBuilder { (const)); }; -class FilterChainManagerImplTest : public testing::Test { +class FilterChainManagerImplTest : public testing::TestWithParam { public: void SetUp() override { local_address_ = std::make_shared("127.0.0.1", 1234); @@ -63,6 +63,7 @@ class FilterChainManagerImplTest : public testing::Test { TestUtility::loadFromYaml( TestEnvironment::substitute(filter_chain_yaml, Network::Address::IpVersion::v4), filter_chain_template_); + TestUtility::loadFromYaml(filter_chain_matcher, matcher_); } const Network::FilterChain* @@ -101,6 +102,7 @@ class FilterChainManagerImplTest : public testing::Test { const envoy::config::listener::v3::FilterChain& filter_chain, const envoy::config::listener::v3::FilterChain* fallback_filter_chain = nullptr) { filter_chain_manager_.addFilterChains( + GetParam() ? &matcher_ : nullptr, std::vector{&filter_chain}, fallback_filter_chain, filter_chain_factory_builder_, filter_chain_manager_); } @@ -112,6 +114,7 @@ class FilterChainManagerImplTest : public testing::Test { // Reusable template. const std::string filter_chain_yaml = R"EOF( + name: foo filter_chain_match: destination_port: 10000 transport_socket: @@ -126,8 +129,24 @@ class FilterChainManagerImplTest : public testing::Test { keys: - filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/ticket_key_a" )EOF"; + const std::string filter_chain_matcher = R"EOF( + matcher_tree: + input: + name: port + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.DestinationPortInput + exact_match_map: + map: + "10000": + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF"; Init::ManagerImpl init_manager_{"for_filter_chain_manager_test"}; envoy::config::listener::v3::FilterChain filter_chain_template_; + xds::type::matcher::v3::Matcher matcher_; std::shared_ptr build_out_filter_chain_{ std::make_shared()}; envoy::config::listener::v3::FilterChain fallback_filter_chain_; @@ -142,15 +161,16 @@ class FilterChainManagerImplTest : public testing::Test { init_manager_}; }; -TEST_F(FilterChainManagerImplTest, FilterChainMatchNothing) { +TEST_P(FilterChainManagerImplTest, FilterChainMatchNothing) { auto filter_chain = findFilterChainHelper(10000, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); EXPECT_EQ(filter_chain, nullptr); } -TEST_F(FilterChainManagerImplTest, FilterChainMatchCaseInSensitive) { +TEST_P(FilterChainManagerImplTest, FilterChainMatchCaseInSensitive) { envoy::config::listener::v3::FilterChain new_filter_chain = filter_chain_template_; new_filter_chain.mutable_filter_chain_match()->add_server_names("foo.EXAMPLE.com"); filter_chain_manager_.addFilterChains( + GetParam() ? &matcher_ : nullptr, std::vector{&new_filter_chain}, nullptr, filter_chain_factory_builder_, filter_chain_manager_); auto filter_chain = @@ -158,13 +178,19 @@ TEST_F(FilterChainManagerImplTest, FilterChainMatchCaseInSensitive) { EXPECT_NE(filter_chain, nullptr); } -TEST_F(FilterChainManagerImplTest, AddSingleFilterChain) { +TEST_P(FilterChainManagerImplTest, AddSingleFilterChain) { addSingleFilterChainHelper(filter_chain_template_); - auto* filter_chain = findFilterChainHelper(10000, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); - EXPECT_NE(filter_chain, nullptr); + { + auto* filter_chain = findFilterChainHelper(10000, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); + EXPECT_NE(filter_chain, nullptr); + } + { + auto* filter_chain = findFilterChainHelper(15000, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); + EXPECT_EQ(filter_chain, nullptr); + } } -TEST_F(FilterChainManagerImplTest, FilterChainUseFallbackIfNoFilterChainMatches) { +TEST_P(FilterChainManagerImplTest, FilterChainUseFallbackIfNoFilterChainMatches) { // The build helper will build matchable filter chain and then build the default filter chain. EXPECT_CALL(filter_chain_factory_builder_, buildFilterChain(_, _)) .WillOnce(Return(build_out_fallback_filter_chain_)); @@ -180,7 +206,7 @@ TEST_F(FilterChainManagerImplTest, FilterChainUseFallbackIfNoFilterChainMatches) EXPECT_EQ(fallback_filter_chain, build_out_fallback_filter_chain_.get()); } -TEST_F(FilterChainManagerImplTest, LookupFilterChainContextByFilterChainMessage) { +TEST_P(FilterChainManagerImplTest, LookupFilterChainContextByFilterChainMessage) { std::vector filter_chain_messages; for (int i = 0; i < 2; i++) { @@ -192,12 +218,13 @@ TEST_F(FilterChainManagerImplTest, LookupFilterChainContextByFilterChainMessage) } EXPECT_CALL(filter_chain_factory_builder_, buildFilterChain(_, _)).Times(2); filter_chain_manager_.addFilterChains( + GetParam() ? &matcher_ : nullptr, std::vector{&filter_chain_messages[0], &filter_chain_messages[1]}, nullptr, filter_chain_factory_builder_, filter_chain_manager_); } -TEST_F(FilterChainManagerImplTest, DuplicateContextsAreNotBuilt) { +TEST_P(FilterChainManagerImplTest, DuplicateContextsAreNotBuilt) { std::vector filter_chain_messages; for (int i = 0; i < 3; i++) { @@ -210,6 +237,7 @@ TEST_F(FilterChainManagerImplTest, DuplicateContextsAreNotBuilt) { EXPECT_CALL(filter_chain_factory_builder_, buildFilterChain(_, _)); filter_chain_manager_.addFilterChains( + GetParam() ? &matcher_ : nullptr, std::vector{&filter_chain_messages[0]}, nullptr, filter_chain_factory_builder_, filter_chain_manager_); @@ -220,12 +248,13 @@ TEST_F(FilterChainManagerImplTest, DuplicateContextsAreNotBuilt) { // built because it reuse the filter chain context in the previous filter chain manager EXPECT_CALL(filter_chain_factory_builder_, buildFilterChain(_, _)).Times(2); new_filter_chain_manager.addFilterChains( + GetParam() ? &matcher_ : nullptr, std::vector{ &filter_chain_messages[0], &filter_chain_messages[1], &filter_chain_messages[2]}, nullptr, filter_chain_factory_builder_, new_filter_chain_manager); } -TEST_F(FilterChainManagerImplTest, CreatedFilterChainFactoryContextHasIndependentDrainClose) { +TEST_P(FilterChainManagerImplTest, CreatedFilterChainFactoryContextHasIndependentDrainClose) { std::vector filter_chain_messages; for (int i = 0; i < 3; i++) { envoy::config::listener::v3::FilterChain new_filter_chain = filter_chain_template_; @@ -255,5 +284,8 @@ TEST_F(FilterChainManagerImplTest, CreatedFilterChainFactoryContextHasIndependen EXPECT_TRUE(context0->drainDecision().drainClose()); EXPECT_FALSE(context1->drainDecision().drainClose()); } + +INSTANTIATE_TEST_SUITE_P(Matcher, FilterChainManagerImplTest, ::testing::Values(true, false)); + } // namespace Server } // namespace Envoy diff --git a/test/server/listener_manager_impl_quic_only_test.cc b/test/server/listener_manager_impl_quic_only_test.cc index 8ad549a3a5e81..fe5e923f6384f 100644 --- a/test/server/listener_manager_impl_quic_only_test.cc +++ b/test/server/listener_manager_impl_quic_only_test.cc @@ -26,8 +26,8 @@ class ListenerManagerImplQuicOnlyTest : public ListenerManagerImplTest { }; #if defined(ENVOY_ENABLE_QUIC) -TEST_F(ListenerManagerImplQuicOnlyTest, QuicListenerFactoryAndSslContext) { - const std::string yaml = TestEnvironment::substitute(R"EOF( +TEST_P(ListenerManagerImplQuicOnlyTest, QuicListenerFactoryAndSslContext) { + std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: address: 127.0.0.1 @@ -36,6 +36,7 @@ TEST_F(ListenerManagerImplQuicOnlyTest, QuicListenerFactoryAndSslContext) { filter_chains: - filter_chain_match: transport_protocol: "quic" + name: foo filters: - name: envoy.filters.network.http_connection_manager typed_config: @@ -72,7 +73,25 @@ TEST_F(ListenerManagerImplQuicOnlyTest, QuicListenerFactoryAndSslContext) { udp_listener_config: quic_options: {} )EOF", - Network::Address::IpVersion::v4); + Network::Address::IpVersion::v4); + if (use_matcher_) { + yaml = yaml + R"EOF( +filter_chain_matcher: + matcher_tree: + input: + name: transport + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.TransportProtocolInput + exact_match_map: + map: + "quic": + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF"; + } envoy::config::listener::v3::Listener listener_proto = parseListenerFromV3Yaml(yaml); ON_CALL(udp_gso_syscall_, supportsUdpGso()) @@ -111,7 +130,7 @@ TEST_F(ListenerManagerImplQuicOnlyTest, QuicListenerFactoryAndSslContext) { } #endif - manager_->addOrUpdateListener(listener_proto, "", true); + addOrUpdateListener(listener_proto); EXPECT_EQ(1u, manager_->listeners().size()); EXPECT_FALSE(manager_->listeners()[0] .get() @@ -155,7 +174,7 @@ TEST_F(ListenerManagerImplQuicOnlyTest, QuicListenerFactoryAndSslContext) { } #endif -TEST_F(ListenerManagerImplQuicOnlyTest, QuicListenerFactoryWithWrongTransportSocket) { +TEST_P(ListenerManagerImplQuicOnlyTest, QuicListenerFactoryWithWrongTransportSocket) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: @@ -165,6 +184,7 @@ TEST_F(ListenerManagerImplQuicOnlyTest, QuicListenerFactoryWithWrongTransportSoc filter_chains: - filter_chain_match: transport_protocol: "quic" + name: foo filters: [] transport_socket: name: envoy.transport_sockets.quic @@ -194,15 +214,15 @@ TEST_F(ListenerManagerImplQuicOnlyTest, QuicListenerFactoryWithWrongTransportSoc envoy::config::listener::v3::Listener listener_proto = parseListenerFromV3Yaml(yaml); #if defined(ENVOY_ENABLE_QUIC) - EXPECT_THROW_WITH_REGEX(manager_->addOrUpdateListener(listener_proto, "", true), EnvoyException, + EXPECT_THROW_WITH_REGEX(addOrUpdateListener(listener_proto), EnvoyException, "wrong transport socket config specified for quic transport socket"); #else - EXPECT_THROW_WITH_REGEX(manager_->addOrUpdateListener(listener_proto, "", true), EnvoyException, + EXPECT_THROW_WITH_REGEX(addOrUpdateListener(listener_proto), EnvoyException, "QUIC is configured but not enabled in the build."); #endif } -TEST_F(ListenerManagerImplQuicOnlyTest, QuicListenerFactoryWithWrongCodec) { +TEST_P(ListenerManagerImplQuicOnlyTest, QuicListenerFactoryWithWrongCodec) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: @@ -212,6 +232,7 @@ TEST_F(ListenerManagerImplQuicOnlyTest, QuicListenerFactoryWithWrongCodec) { filter_chains: - filter_chain_match: transport_protocol: "quic" + name: foo filters: [] transport_socket: name: envoy.transport_sockets.quic @@ -242,16 +263,16 @@ TEST_F(ListenerManagerImplQuicOnlyTest, QuicListenerFactoryWithWrongCodec) { envoy::config::listener::v3::Listener listener_proto = parseListenerFromV3Yaml(yaml); #if defined(ENVOY_ENABLE_QUIC) - EXPECT_THROW_WITH_REGEX(manager_->addOrUpdateListener(listener_proto, "", true), EnvoyException, + EXPECT_THROW_WITH_REGEX(addOrUpdateListener(listener_proto), EnvoyException, "error building network filter chain for quic listener: requires exactly " "one http_connection_manager filter."); #else - EXPECT_THROW_WITH_REGEX(manager_->addOrUpdateListener(listener_proto, "", true), EnvoyException, + EXPECT_THROW_WITH_REGEX(addOrUpdateListener(listener_proto), EnvoyException, "QUIC is configured but not enabled in the build."); #endif } -TEST_F(ListenerManagerImplQuicOnlyTest, QuicListenerFactoryWithConnectionBalencer) { +TEST_P(ListenerManagerImplQuicOnlyTest, QuicListenerFactoryWithConnectionBalencer) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: @@ -261,6 +282,7 @@ TEST_F(ListenerManagerImplQuicOnlyTest, QuicListenerFactoryWithConnectionBalence filter_chains: - filter_chain_match: transport_protocol: "quic" + name: foo filters: - name: envoy.filters.network.http_connection_manager typed_config: @@ -302,15 +324,17 @@ TEST_F(ListenerManagerImplQuicOnlyTest, QuicListenerFactoryWithConnectionBalence envoy::config::listener::v3::Listener listener_proto = parseListenerFromV3Yaml(yaml); #if defined(ENVOY_ENABLE_QUIC) - EXPECT_THROW_WITH_REGEX(manager_->addOrUpdateListener(listener_proto, "", true), EnvoyException, + EXPECT_THROW_WITH_REGEX(addOrUpdateListener(listener_proto), EnvoyException, "connection_balance_config is configured for QUIC listener which doesn't " "work with connection balancer."); #else - EXPECT_THROW_WITH_REGEX(manager_->addOrUpdateListener(listener_proto, "", true), EnvoyException, + EXPECT_THROW_WITH_REGEX(addOrUpdateListener(listener_proto), EnvoyException, "QUIC is configured but not enabled in the build."); #endif } +INSTANTIATE_TEST_SUITE_P(Matcher, ListenerManagerImplQuicOnlyTest, ::testing::Values(false, true)); + } // namespace } // namespace Server } // namespace Envoy diff --git a/test/server/listener_manager_impl_test.cc b/test/server/listener_manager_impl_test.cc index f3a7590c78581..edfa69b865112 100644 --- a/test/server/listener_manager_impl_test.cc +++ b/test/server/listener_manager_impl_test.cc @@ -23,7 +23,9 @@ #include "source/common/network/socket_interface_impl.h" #include "source/common/network/utility.h" #include "source/common/protobuf/protobuf.h" +#include "source/extensions/common/matcher/trie_matcher.h" #include "source/extensions/filters/listener/original_dst/original_dst.h" +#include "source/extensions/filters/listener/tls_inspector/tls_inspector.h" #include "source/extensions/transport_sockets/tls/ssl_socket.h" #include "test/mocks/init/mocks.h" @@ -73,7 +75,8 @@ class ListenerManagerImplWithRealFiltersTest : public ListenerManagerImplTest { address: socket_address: { address: 127.0.0.1, port_value: 1111 } filter_chains: - - filters: + - filters: [] + name: foo )EOF"); listener.set_name(name); return listener; @@ -94,10 +97,10 @@ class ListenerManagerImplWithRealFiltersTest : public ListenerManagerImplTest { expectCreateListenSocket(expected_state, expected_num_options, bind_type); expectSetsockopt(expected_option.level(), expected_option.option(), expected_value, expected_num_options); - manager_->addOrUpdateListener(listener, "", true); + addOrUpdateListener(listener); EXPECT_EQ(1U, manager_->listeners().size()); } else { - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(listener, "", true), EnvoyException, + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(listener), EnvoyException, "MockListenerComponentFactory: Setting socket options failed"); EXPECT_EQ(0U, manager_->listeners().size()); } @@ -127,7 +130,7 @@ class ListenerManagerImplForInPlaceFilterChainUpdateTest : public Event::Simulat ListenerHandle*) { EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(*worker_, addListener(_, _, _, _)); - manager_->addOrUpdateListener(listener_proto, "", true); + addOrUpdateListener(listener_proto); worker_->callAddCompletion(); EXPECT_EQ(1UL, manager_->listeners().size()); checkStats(__LINE__, 1, 0, 0, 0, 1, 0, 0); @@ -151,7 +154,7 @@ class ListenerManagerImplForInPlaceFilterChainUpdateTest : public Event::Simulat EXPECT_CALL(*worker_, stopListener(_, _)); EXPECT_CALL(*old_listener_handle->drain_manager_, startDrainSequence(_)); - EXPECT_TRUE(manager_->addOrUpdateListener(new_listener_proto, "", true)); + EXPECT_TRUE(addOrUpdateListener(new_listener_proto)); EXPECT_CALL(*worker_, removeListener(_, _)); old_listener_handle->drain_manager_->drain_sequence_completion_(); @@ -182,7 +185,7 @@ class MockLdsApi : public LdsApi { MOCK_METHOD(std::string, versionInfo, (), (const)); }; -TEST_F(ListenerManagerImplWithRealFiltersTest, EmptyFilter) { +TEST_P(ListenerManagerImplWithRealFiltersTest, EmptyFilter) { const std::string yaml = R"EOF( address: socket_address: @@ -190,18 +193,19 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, EmptyFilter) { port_value: 1234 filter_chains: - filters: [] + name: foo )EOF"; EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(&manager_->httpContext(), &server_.httpContext()); EXPECT_EQ(1U, manager_->listeners().size()); EXPECT_EQ(std::chrono::milliseconds(15000), manager_->listeners().front().get().listenerFiltersTimeout()); } -TEST_F(ListenerManagerImplWithRealFiltersTest, DefaultListenerPerConnectionBufferLimit) { +TEST_P(ListenerManagerImplWithRealFiltersTest, DefaultListenerPerConnectionBufferLimit) { const std::string yaml = R"EOF( address: socket_address: @@ -209,14 +213,15 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, DefaultListenerPerConnectionBuffe port_value: 1234 filter_chains: - filters: [] + name: foo )EOF"; EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1024 * 1024U, manager_->listeners().back().get().perConnectionBufferLimitBytes()); } -TEST_F(ListenerManagerImplWithRealFiltersTest, DuplicatePortNotAllowed) { +TEST_P(ListenerManagerImplWithRealFiltersTest, DuplicatePortNotAllowed) { const std::string yaml1 = R"EOF( name: foo address: @@ -225,6 +230,7 @@ name: foo port_value: 1234 filter_chains: - filters: [] + name: foo )EOF"; const std::string yaml2 = R"EOF( @@ -235,16 +241,17 @@ name: bar port_value: 1234 filter_chains: - filters: [] + name: foo )EOF"; EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml1), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml1)); EXPECT_THROW_WITH_MESSAGE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml2), "", true), EnvoyException, + addOrUpdateListener(parseListenerFromV3Yaml(yaml2)), EnvoyException, "error adding listener: 'bar' has duplicate address '127.0.0.1:1234' as existing listener"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, SetListenerPerConnectionBufferLimit) { +TEST_P(ListenerManagerImplWithRealFiltersTest, SetListenerPerConnectionBufferLimit) { const std::string yaml = R"EOF( address: socket_address: @@ -252,15 +259,16 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SetListenerPerConnectionBufferLim port_value: 1234 filter_chains: - filters: [] + name: foo per_connection_buffer_limit_bytes: 8192 )EOF"; EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(8192U, manager_->listeners().back().get().perConnectionBufferLimitBytes()); } -TEST_F(ListenerManagerImplWithRealFiltersTest, TlsTransportSocket) { +TEST_P(ListenerManagerImplWithRealFiltersTest, TlsTransportSocket) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: @@ -268,6 +276,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, TlsTransportSocket) { port_value: 1234 filter_chains: - filters: [] + name: foo transport_socket: name: tls typed_config: @@ -288,7 +297,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, TlsTransportSocket) { Network::Address::IpVersion::v4); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); auto filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); @@ -296,7 +305,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, TlsTransportSocket) { EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); } -TEST_F(ListenerManagerImplWithRealFiltersTest, TransportSocketConnectTimeout) { +TEST_P(ListenerManagerImplWithRealFiltersTest, TransportSocketConnectTimeout) { const std::string yaml = R"EOF( address: socket_address: @@ -304,17 +313,18 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, TransportSocketConnectTimeout) { port_value: 1234 filter_chains: - filters: [] + name: foo transport_socket_connect_timeout: 3s )EOF"; EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); auto filter_chain = findFilterChain(1234, "127.0.0.1", "", "", {}, "8.8.8.8", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_EQ(filter_chain->transportSocketConnectTimeout(), std::chrono::seconds(3)); } -TEST_F(ListenerManagerImplWithRealFiltersTest, UdpAddress) { +TEST_P(ListenerManagerImplWithRealFiltersTest, UdpAddress) { EXPECT_CALL(*worker_, start(_, _)); EXPECT_FALSE(manager_->isWorkerStarted()); manager_->startWorkers(guard_dog_, callback_.AsStdFunction()); @@ -351,11 +361,11 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, UdpAddress) { uint32_t) -> Network::SocketSharedPtr { return listener_factory_.socket_; })); EXPECT_CALL(*listener_factory_.socket_, setSocketOption(_, _, _, _)).Times(testing::AtLeast(1)); EXPECT_CALL(os_sys_calls_, close(_)).WillRepeatedly(Return(Api::SysCallIntResult{0, errno})); - manager_->addOrUpdateListener(listener_proto, "", true); + addOrUpdateListener(listener_proto); EXPECT_EQ(1u, manager_->listeners().size()); } -TEST_F(ListenerManagerImplWithRealFiltersTest, AllowOnlyDefaultFilterChain) { +TEST_P(ListenerManagerImplWithRealFiltersTest, AllowOnlyDefaultFilterChain) { const std::string yaml = R"EOF( address: socket_address: @@ -365,11 +375,11 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, AllowOnlyDefaultFilterChain) { filters: [] )EOF"; - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1, manager_->listeners().size()); } -TEST_F(ListenerManagerImplWithRealFiltersTest, BadListenerConfig) { +TEST_P(ListenerManagerImplWithRealFiltersTest, BadListenerConfig) { const std::string yaml = R"EOF( address: socket_address: @@ -380,11 +390,11 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, BadListenerConfig) { test: a )EOF"; - EXPECT_THROW_WITH_REGEX(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), - EnvoyException, "test: Cannot find field"); + EXPECT_THROW_WITH_REGEX(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, + "test: Cannot find field"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, BadListenerConfigNoFilterChains) { +TEST_P(ListenerManagerImplWithRealFiltersTest, BadListenerConfigNoFilterChains) { const std::string yaml = R"EOF( address: socket_address: @@ -392,11 +402,11 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, BadListenerConfigNoFilterChains) port_value: 1234 )EOF"; - EXPECT_THROW_WITH_REGEX(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), - EnvoyException, "no filter chains specified"); + EXPECT_THROW_WITH_REGEX(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, + "no filter chains specified"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, BadFilterConfig) { +TEST_P(ListenerManagerImplWithRealFiltersTest, BadFilterConfig) { const std::string yaml = R"EOF( address: socket_address: @@ -406,24 +416,26 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, BadFilterConfig) { - filters: - foo: type name: name + name: foo )EOF"; - EXPECT_THROW_WITH_REGEX(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), - EnvoyException, "foo: Cannot find field"); + EXPECT_THROW_WITH_REGEX(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, + "foo: Cannot find field"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, BadConnectionLessUdpConfigWithFilterChain) { +TEST_P(ListenerManagerImplWithRealFiltersTest, BadConnectionLessUdpConfigWithFilterChain) { const std::string yaml = R"EOF( address: socket_address: protocol: UDP address: 127.0.0.1 port_value: 1234 -filter_chains: {} +filter_chains: +- filters: [] + name: foo )EOF"; - EXPECT_THROW_WITH_REGEX(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), - EnvoyException, + EXPECT_THROW_WITH_REGEX(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, "1 filter chain\\(s\\) specified for connection-less UDP listener"); } @@ -445,7 +457,7 @@ class NonTerminalFilterFactory : public Configuration::NamedNetworkFilterConfigF std::string name() const override { return "non_terminal"; } }; -TEST_F(ListenerManagerImplWithRealFiltersTest, TerminalNotLast) { +TEST_P(ListenerManagerImplWithRealFiltersTest, TerminalNotLast) { TestScopedRuntime scoped_runtime; scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); @@ -460,15 +472,16 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, TerminalNotLast) { filter_chains: - filters: - name: non_terminal + name: foo )EOF"; EXPECT_THROW_WITH_REGEX( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), EnvoyException, + addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, "Error: non-terminal filter named non_terminal of type non_terminal is the last " "filter in a network filter chain."); } -TEST_F(ListenerManagerImplWithRealFiltersTest, NotTerminalLast) { +TEST_P(ListenerManagerImplWithRealFiltersTest, NotTerminalLast) { const std::string yaml = R"EOF( address: socket_address: @@ -482,15 +495,16 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, NotTerminalLast) { stat_prefix: tcp cluster: cluster - name: unknown_but_will_not_be_processed + name: foo )EOF"; EXPECT_THROW_WITH_REGEX( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), EnvoyException, + addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, "Error: terminal filter named envoy.filters.network.tcp_proxy of type " "envoy.filters.network.tcp_proxy must be the last filter in a network filter chain."); } -TEST_F(ListenerManagerImplWithRealFiltersTest, BadFilterName) { +TEST_P(ListenerManagerImplWithRealFiltersTest, BadFilterName) { const std::string yaml = R"EOF( address: socket_address: @@ -499,10 +513,11 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, BadFilterName) { filter_chains: - filters: - name: invalid + name: foo )EOF"; EXPECT_THROW_WITH_MESSAGE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), EnvoyException, + addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, "Didn't find a registered implementation for 'invalid' with type URL: ''"); } @@ -535,7 +550,7 @@ class TestStatsConfigFactory : public Configuration::NamedNetworkFilterConfigFac } }; -TEST_F(ListenerManagerImplWithRealFiltersTest, StatsScopeTest) { +TEST_P(ListenerManagerImplWithRealFiltersTest, StatsScopeTest) { TestScopedRuntime scoped_runtime; scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); @@ -551,18 +566,19 @@ bind_to_port: false filter_chains: - filters: - name: stats_test + name: foo )EOF"; EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, ListenerComponentFactory::BindType::NoBind, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); manager_->listeners().front().get().listenerScope().counterFromString("foo").inc(); EXPECT_EQ(1UL, server_.stats_store_.counterFromString("bar").value()); EXPECT_EQ(1UL, server_.stats_store_.counterFromString("listener.127.0.0.1_1234.foo").value()); } -TEST_F(ListenerManagerImplTest, RejectIpv4CompatOnIpv4Address) { +TEST_P(ListenerManagerImplTest, RejectIpv4CompatOnIpv4Address) { const std::string yaml = R"EOF( name: "foo" address: @@ -574,13 +590,12 @@ TEST_F(ListenerManagerImplTest, RejectIpv4CompatOnIpv4Address) { - filters: [] )EOF"; - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), - EnvoyException, + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, "Only IPv6 address '::' or valid IPv4-mapped IPv6 address can set " "ipv4_compat: 0.0.0.0:13333"); } -TEST_F(ListenerManagerImplTest, AcceptIpv4CompatOnIpv4Address) { +TEST_P(ListenerManagerImplTest, AcceptIpv4CompatOnIpv4Address) { auto scoped_runtime_guard = std::make_unique(); scoped_runtime_guard->mergeValues( {{"envoy.reloadable_features.strict_check_on_ipv4_compat", "false"}}); @@ -595,10 +610,10 @@ TEST_F(ListenerManagerImplTest, AcceptIpv4CompatOnIpv4Address) { - filters: [] )EOF"; - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(yaml))); } -TEST_F(ListenerManagerImplTest, RejectIpv4CompatOnNonIpv4MappedIpv6address) { +TEST_P(ListenerManagerImplTest, RejectIpv4CompatOnNonIpv4MappedIpv6address) { const std::string yaml = R"EOF( name: "foo" address: @@ -611,11 +626,11 @@ TEST_F(ListenerManagerImplTest, RejectIpv4CompatOnNonIpv4MappedIpv6address) { )EOF"; EXPECT_THROW_WITH_MESSAGE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), EnvoyException, + addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, "Only IPv6 address '::' or valid IPv4-mapped IPv6 address can set ipv4_compat: [::1]:13333"); } -TEST_F(ListenerManagerImplTest, AcceptIpv4CompatOnIpv6AnyAddress) { +TEST_P(ListenerManagerImplTest, AcceptIpv4CompatOnIpv6AnyAddress) { const std::string yaml = R"EOF( name: "foo" address: @@ -627,10 +642,10 @@ TEST_F(ListenerManagerImplTest, AcceptIpv4CompatOnIpv6AnyAddress) { - filters: [] )EOF"; - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(yaml))); } -TEST_F(ListenerManagerImplTest, AcceptIpv4CompatOnNonCanonicalIpv6AnyAddress) { +TEST_P(ListenerManagerImplTest, AcceptIpv4CompatOnNonCanonicalIpv6AnyAddress) { const std::string yaml = R"EOF( name: "foo" address: @@ -642,10 +657,10 @@ TEST_F(ListenerManagerImplTest, AcceptIpv4CompatOnNonCanonicalIpv6AnyAddress) { - filters: [] )EOF"; - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(yaml))); } -TEST_F(ListenerManagerImplTest, AcceptIpv4CompatOnNonIpv4MappedIpv6address) { +TEST_P(ListenerManagerImplTest, AcceptIpv4CompatOnNonIpv4MappedIpv6address) { auto scoped_runtime_guard = std::make_unique(); scoped_runtime_guard->mergeValues( {{"envoy.reloadable_features.strict_check_on_ipv4_compat", "false"}}); @@ -660,10 +675,10 @@ TEST_F(ListenerManagerImplTest, AcceptIpv4CompatOnNonIpv4MappedIpv6address) { - filters: [] )EOF"; - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(yaml))); } -TEST_F(ListenerManagerImplTest, UnsupportedInternalListener) { +TEST_P(ListenerManagerImplTest, UnsupportedInternalListener) { auto scoped_runtime = std::make_unique(); // Workaround of triggering death at windows platform. scoped_runtime->mergeValues({{"envoy.reloadable_features.internal_address", "false"}}); @@ -677,10 +692,10 @@ TEST_F(ListenerManagerImplTest, UnsupportedInternalListener) { - filters: [] )EOF"; - EXPECT_DEATH(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), ".*"); + EXPECT_DEATH(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), ".*"); } -TEST_F(ListenerManagerImplTest, RejectListenerWithSocketAddressWithInternalListenerConfig) { +TEST_P(ListenerManagerImplTest, RejectListenerWithSocketAddressWithInternalListenerConfig) { auto scoped_runtime = std::make_unique(); scoped_runtime->mergeValues({{"envoy.reloadable_features.internal_address", "true"}}); @@ -695,13 +710,12 @@ TEST_F(ListenerManagerImplTest, RejectListenerWithSocketAddressWithInternalListe - filters: [] )EOF"; - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), - EnvoyException, + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, "error adding listener '127.0.0.1:1234': address is not an internal " "address but an internal listener config is provided"); } -TEST_F(ListenerManagerImplTest, RejectTcpOptionsWithInternalListenerConfig) { +TEST_P(ListenerManagerImplTest, RejectTcpOptionsWithInternalListenerConfig) { auto scoped_runtime = std::make_unique(); scoped_runtime->mergeValues({{"envoy.reloadable_features.internal_address", "true"}}); @@ -738,19 +752,19 @@ TEST_F(ListenerManagerImplTest, RejectTcpOptionsWithInternalListenerConfig) { { auto new_listener = listener; new_listener.mutable_socket_options()->Add(); - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(new_listener, "", true), EnvoyException, + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(new_listener), EnvoyException, "error adding listener 'envoy://test_internal_listener_name': does " "not support socket option") } { auto new_listener = listener; new_listener.set_enable_mptcp(true); - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(new_listener, "", true), EnvoyException, + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(new_listener), EnvoyException, "listener foo: enable_mptcp can only be used with IP addresses") } } -TEST_F(ListenerManagerImplTest, NotDefaultListenerFiltersTimeout) { +TEST_P(ListenerManagerImplTest, NotDefaultListenerFiltersTimeout) { const std::string yaml = R"EOF( name: "foo" address: @@ -761,12 +775,12 @@ TEST_F(ListenerManagerImplTest, NotDefaultListenerFiltersTimeout) { )EOF"; EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(yaml))); EXPECT_EQ(std::chrono::milliseconds(), manager_->listeners().front().get().listenerFiltersTimeout()); } -TEST_F(ListenerManagerImplTest, ModifyOnlyDrainType) { +TEST_P(ListenerManagerImplTest, ModifyOnlyDrainType) { InSequence s; // Add foo listener. @@ -782,13 +796,13 @@ TEST_F(ListenerManagerImplTest, ModifyOnlyDrainType) { ListenerHandle* listener_foo = expectListenerCreate(false, true, envoy::config::listener::v3::Listener::MODIFY_ONLY); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); checkStats(__LINE__, 1, 0, 0, 0, 1, 0, 0); EXPECT_CALL(*listener_foo, onDestroy()); } -TEST_F(ListenerManagerImplTest, AddListenerAddressNotMatching) { +TEST_P(ListenerManagerImplTest, AddListenerAddressNotMatching) { time_system_.setSystemTime(std::chrono::milliseconds(1001001001001)); InSequence s; @@ -810,8 +824,7 @@ filter_chains: {} ListenerHandle* listener_foo = expectListenerCreate(false, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "version1", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "version1")); checkStats(__LINE__, 1, 0, 0, 0, 1, 0, 0); EXPECT_CALL(*lds_api, versionInfo()).WillOnce(Return("version1")); checkConfigDump(R"EOF( @@ -850,8 +863,8 @@ filter_chains: {} // Another socket should be created. EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(*listener_foo, onDestroy()); - EXPECT_TRUE(manager_->addOrUpdateListener( - parseListenerFromV3Yaml(listener_foo_different_address_yaml), "version2", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_different_address_yaml), + "version2")); checkStats(__LINE__, 1, 1, 0, 0, 1, 0, 0); EXPECT_CALL(*lds_api, versionInfo()).WillOnce(Return("version2")); checkConfigDump(R"EOF( @@ -894,8 +907,7 @@ filter_chains: {} ListenerHandle* listener_baz = expectListenerCreate(true, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(listener_baz->target_, initialize()); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_baz_yaml), "version3", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_baz_yaml), "version3")); EXPECT_CALL(*lds_api, versionInfo()).WillOnce(Return("version3")); checkConfigDump(R"EOF( version_info: version3 @@ -950,8 +962,8 @@ filter_chains: {} listener_baz->target_.ready(); })); EXPECT_CALL(listener_baz_different_address->target_, initialize()); - EXPECT_TRUE(manager_->addOrUpdateListener( - parseListenerFromV3Yaml(listener_baz_different_address_yaml), "version4", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_baz_different_address_yaml), + "version4")); EXPECT_CALL(*lds_api, versionInfo()).WillOnce(Return("version4")); checkConfigDump(R"EOF( version_info: version4 @@ -998,7 +1010,7 @@ version_info: version4 // Make sure that a listener creation does not fail on IPv4 only setups when FilterChainMatch is not // specified and we try to create default CidrRange. See makeCidrListEntry function for // more details. -TEST_F(ListenerManagerImplTest, AddListenerOnIpv4OnlySetups) { +TEST_P(ListenerManagerImplTest, AddListenerOnIpv4OnlySetups) { InSequence s; const std::string listener_foo_yaml = R"EOF( @@ -1022,7 +1034,7 @@ drain_type: default EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); checkStats(__LINE__, 1, 0, 0, 0, 1, 0, 0); EXPECT_CALL(*listener_foo, onDestroy()); } @@ -1030,7 +1042,7 @@ drain_type: default // Make sure that a listener creation does not fail on IPv6 only setups when FilterChainMatch is not // specified and we try to create default CidrRange. See makeCidrListEntry function for // more details. -TEST_F(ListenerManagerImplTest, AddListenerOnIpv6OnlySetups) { +TEST_P(ListenerManagerImplTest, AddListenerOnIpv6OnlySetups) { InSequence s; const std::string listener_foo_yaml = R"EOF( @@ -1054,13 +1066,13 @@ drain_type: default EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); checkStats(__LINE__, 1, 0, 0, 0, 1, 0, 0); EXPECT_CALL(*listener_foo, onDestroy()); } // Make sure that a listener that is not added_via_api cannot be updated or removed. -TEST_F(ListenerManagerImplTest, UpdateRemoveNotModifiableListener) { +TEST_P(ListenerManagerImplTest, UpdateRemoveNotModifiableListener) { time_system_.setSystemTime(std::chrono::milliseconds(1001001001001)); InSequence s; @@ -1078,7 +1090,7 @@ name: foo ListenerHandle* listener_foo = expectListenerCreate(false, false); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", false)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", false)); checkStats(__LINE__, 1, 0, 0, 0, 1, 0, 0); checkConfigDump(R"EOF( static_listeners: @@ -1107,8 +1119,7 @@ name: foo - name: fake )EOF"; - EXPECT_FALSE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml), "", false)); + EXPECT_FALSE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml), "", false)); checkStats(__LINE__, 1, 0, 0, 0, 1, 0, 0); // Remove foo listener. Should be blocked. @@ -1119,7 +1130,7 @@ name: foo } // Tests that when listener tears down, server's initManager is notified. -TEST_F(ListenerManagerImplTest, ListenerTeardownNotifiesServerInitManager) { +TEST_P(ListenerManagerImplTest, ListenerTeardownNotifiesServerInitManager) { time_system_.setSystemTime(std::chrono::milliseconds(1001001001001)); InSequence s; @@ -1158,8 +1169,7 @@ filter_chains: {} ListenerHandle* listener_foo = expectListenerCreate(true, true); EXPECT_CALL(server_, initManager()).WillOnce(ReturnRef(server_init_mgr)); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), - "version1", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "version1")); checkStats(__LINE__, 1, 0, 0, 0, 1, 0, 0); EXPECT_CALL(*lds_api, versionInfo()).WillOnce(Return("version1")); @@ -1211,8 +1221,7 @@ version_info: version1 EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); // Version 2 listener will be initialized by listener manager directly. EXPECT_CALL(listener_foo2->target_, initialize()); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), - "version2", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "version2")); // Version2 is in warming list as listener_foo2->target_ is not ready yet. checkStats(__LINE__, /*added=*/2, 0, /*removed=*/1, /*warming=*/1, 0, 0, 0); EXPECT_CALL(*lds_api, versionInfo()).WillOnce(Return("version2")); @@ -1242,7 +1251,7 @@ version_info: version1 } } -TEST_F(ListenerManagerImplTest, OverrideListener) { +TEST_P(ListenerManagerImplTest, OverrideListener) { InSequence s; time_system_.setSystemTime(std::chrono::milliseconds(1001001001001)); @@ -1263,8 +1272,7 @@ filter_chains: {} ListenerHandle* listener_foo = expectListenerCreate(false, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "version1", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "version1", true)); checkStats(__LINE__, 1, 0, 0, 0, 1, 0, 0); // Start workers and capture ListenerImpl. @@ -1298,8 +1306,7 @@ name: foo EXPECT_CALL(*worker_, addListener(_, _, _, _)); auto* timer = new Event::MockTimer(dynamic_cast(&server_.dispatcher())); EXPECT_CALL(*timer, enableTimer(_, _)); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml))); EXPECT_EQ(1UL, manager_->listeners().size()); worker_->callAddCompletion(); @@ -1315,7 +1322,7 @@ name: foo EXPECT_EQ(1, server_.stats_store_.counter("listener_manager.listener_create_success").value()); } -TEST_F(ListenerManagerImplTest, AddOrUpdateListener) { +TEST_P(ListenerManagerImplTest, AddOrUpdateListener) { time_system_.setSystemTime(std::chrono::milliseconds(1001001001001)); NiceMock mock_matcher; ON_CALL(mock_matcher, match(_)).WillByDefault(Return(false)); @@ -1343,8 +1350,7 @@ filter_chains: {} ListenerHandle* listener_foo = expectListenerCreate(false, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "version1", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "version1", true)); checkStats(__LINE__, 1, 0, 0, 0, 1, 0, 0); EXPECT_CALL(*lds_api, versionInfo()).WillOnce(Return("version1")); checkConfigDump(R"EOF( @@ -1375,7 +1381,7 @@ version_info: version1 mock_matcher); // Update duplicate should be a NOP. - EXPECT_FALSE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_FALSE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); checkStats(__LINE__, 1, 0, 0, 0, 1, 0, 0); // Update foo listener. @@ -1396,8 +1402,8 @@ per_connection_buffer_limit_bytes: 10 EXPECT_CALL(*listener_factory_.socket_, duplicate()) .WillOnce(Return(ByMove(std::unique_ptr(duplicated_socket)))); EXPECT_CALL(*listener_foo, onDestroy()); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml), - "version2", true)); + EXPECT_TRUE( + addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml), "version2", true)); checkStats(__LINE__, 1, 1, 0, 0, 1, 0, 0); EXPECT_CALL(*lds_api, versionInfo()).WillOnce(Return("version2")); checkConfigDump(R"EOF( @@ -1451,8 +1457,7 @@ version_info: version2 .value()); // Update duplicate should be a NOP. - EXPECT_FALSE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml), "", true)); + EXPECT_FALSE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml))); checkStats(__LINE__, 1, 1, 0, 0, 1, 0, 0); time_system_.setSystemTime(std::chrono::milliseconds(3003003003003)); @@ -1464,8 +1469,7 @@ version_info: version2 EXPECT_CALL(*worker_, addListener(_, _, _, _)); EXPECT_CALL(*worker_, stopListener(_, _)); EXPECT_CALL(*listener_foo_update1->drain_manager_, startDrainSequence(_)); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "version3", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "version3", true)); worker_->callAddCompletion(); checkStats(__LINE__, 1, 2, 0, 0, 1, 1, 0); EXPECT_CALL(*lds_api, versionInfo()).WillOnce(Return("version3")); @@ -1533,8 +1537,7 @@ filter_chains: {} ListenerHandle* listener_bar = expectListenerCreate(false, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(*worker_, addListener(_, _, _, _)); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_bar_yaml), "version4", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_bar_yaml), "version4", true)); EXPECT_EQ(2UL, manager_->listeners().size()); worker_->callAddCompletion(); checkStats(__LINE__, 2, 2, 0, 0, 2, 0, 0); @@ -1554,8 +1557,7 @@ filter_chains: {} ListenerHandle* listener_baz = expectListenerCreate(true, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(listener_baz->target_, initialize()); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_baz_yaml), "version5", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_baz_yaml), "version5", true)); EXPECT_EQ(2UL, manager_->listeners().size()); checkStats(__LINE__, 3, 2, 0, 1, 2, 0, 0); EXPECT_CALL(*lds_api, versionInfo()).WillOnce(Return("version5")); @@ -1615,7 +1617,7 @@ version_info: version5 mock_matcher); // Update a duplicate baz that is currently warming. - EXPECT_FALSE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_baz_yaml), "", true)); + EXPECT_FALSE(addOrUpdateListener(parseListenerFromV3Yaml(listener_baz_yaml))); checkStats(__LINE__, 3, 2, 0, 1, 2, 0, 0); // Update baz while it is warming. @@ -1637,8 +1639,7 @@ name: baz listener_baz->target_.ready(); })); EXPECT_CALL(listener_baz_update1->target_, initialize()); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_baz_update1_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_baz_update1_yaml))); EXPECT_EQ(2UL, manager_->listeners().size()); checkStats(__LINE__, 3, 3, 0, 1, 2, 0, 0); @@ -1654,7 +1655,7 @@ name: baz EXPECT_CALL(*listener_baz_update1, onDestroy()); } -TEST_F(ListenerManagerImplTest, UpdateActiveToWarmAndBack) { +TEST_P(ListenerManagerImplTest, UpdateActiveToWarmAndBack) { InSequence s; EXPECT_CALL(*worker_, start(_, _)); @@ -1674,7 +1675,7 @@ name: foo ListenerHandle* listener_foo = expectListenerCreate(true, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(listener_foo->target_, initialize()); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); checkStats(__LINE__, 1, 0, 0, 1, 0, 0, 0); EXPECT_CALL(*worker_, addListener(_, _, _, _)); listener_foo->target_.ready(); @@ -1697,8 +1698,7 @@ per_connection_buffer_limit_bytes: 999 ListenerHandle* listener_foo_update1 = expectListenerCreate(true, true); EXPECT_CALL(*listener_factory_.socket_, duplicate()); EXPECT_CALL(listener_foo_update1->target_, initialize()); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml))); // Should be both active and warming now. EXPECT_EQ(1UL, manager_->listeners(ListenerManager::WARMING).size()); @@ -1707,7 +1707,7 @@ per_connection_buffer_limit_bytes: 999 // Update foo back to original active, should cause the warming listener to be removed. EXPECT_CALL(*listener_foo_update1, onDestroy()); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); checkStats(__LINE__, 1, 2, 0, 0, 1, 0, 0); EXPECT_EQ(0UL, manager_->listeners(ListenerManager::WARMING).size()); @@ -1716,7 +1716,7 @@ per_connection_buffer_limit_bytes: 999 EXPECT_CALL(*listener_foo, onDestroy()); } -TEST_F(ListenerManagerImplTest, AddReusableDrainingListener) { +TEST_P(ListenerManagerImplTest, AddReusableDrainingListener) { InSequence s; EXPECT_CALL(*worker_, start(_, _)); @@ -1740,7 +1740,7 @@ name: foo ListenerHandle* listener_foo = expectListenerCreate(false, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(*worker_, addListener(_, _, _, _)); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); worker_->callAddCompletion(); checkStats(__LINE__, 1, 0, 0, 0, 1, 0, 0); @@ -1763,7 +1763,7 @@ name: foo ListenerHandle* listener_foo2 = expectListenerCreate(false, true); EXPECT_CALL(*listener_factory_.socket_, duplicate()); EXPECT_CALL(*worker_, addListener(_, _, _, _)); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); worker_->callAddCompletion(); checkStats(__LINE__, 2, 0, 1, 0, 1, 1, 0); @@ -1776,7 +1776,7 @@ name: foo EXPECT_CALL(*listener_foo2, onDestroy()); } -TEST_F(ListenerManagerImplTest, AddClosedDrainingListener) { +TEST_P(ListenerManagerImplTest, AddClosedDrainingListener) { InSequence s; EXPECT_CALL(*worker_, start(_, _)); @@ -1800,7 +1800,7 @@ name: foo ListenerHandle* listener_foo = expectListenerCreate(false, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(*worker_, addListener(_, _, _, _)); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); worker_->callAddCompletion(); checkStats(__LINE__, 1, 0, 0, 0, 1, 0, 0); @@ -1818,7 +1818,7 @@ name: foo ListenerHandle* listener_foo2 = expectListenerCreate(false, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(*worker_, addListener(_, _, _, _)); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); worker_->callAddCompletion(); checkStats(__LINE__, 2, 0, 1, 0, 1, 1, 0); @@ -1829,7 +1829,7 @@ name: foo EXPECT_CALL(*listener_foo2, onDestroy()); } -TEST_F(ListenerManagerImplTest, BindToPortEqualToFalse) { +TEST_P(ListenerManagerImplTest, BindToPortEqualToFalse) { InSequence s; auto mock_interface = std::make_unique( std::vector{Network::Address::IpVersion::v4}); @@ -1866,10 +1866,10 @@ bind_to_port: false })); EXPECT_CALL(listener_foo->target_, initialize()); EXPECT_CALL(*listener_foo, onDestroy()); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); } -TEST_F(ListenerManagerImplTest, UpdateBindToPortEqualToFalse) { +TEST_P(ListenerManagerImplTest, UpdateBindToPortEqualToFalse) { InSequence s; auto mock_interface = std::make_unique( std::vector{Network::Address::IpVersion::v4}); @@ -1905,7 +1905,7 @@ bind_to_port: false address, socket_type, options, bind_type, creation_options, worker_index); })); EXPECT_CALL(*worker_, addListener(_, _, _, _)); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); worker_->callAddCompletion(); @@ -1925,7 +1925,7 @@ bind_to_port: false worker_->callRemovalCompletion(); } -TEST_F(ListenerManagerImplTest, DEPRECATED_FEATURE_TEST(DeprecatedBindToPortEqualToFalse)) { +TEST_P(ListenerManagerImplTest, DEPRECATED_FEATURE_TEST(DeprecatedBindToPortEqualToFalse)) { InSequence s; ProdListenerComponentFactory real_listener_factory(server_); EXPECT_CALL(*worker_, start(_, _)); @@ -1964,10 +1964,10 @@ name: foo })); EXPECT_CALL(listener_foo->target_, initialize()); EXPECT_CALL(*listener_foo, onDestroy()); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); } -TEST_F(ListenerManagerImplTest, ReusePortEqualToTrue) { +TEST_P(ListenerManagerImplTest, ReusePortEqualToTrue) { InSequence s; ProdListenerComponentFactory real_listener_factory(server_); EXPECT_CALL(*worker_, start(_, _)); @@ -2010,10 +2010,10 @@ name: foo })); EXPECT_CALL(listener_foo->target_, initialize()); EXPECT_CALL(*listener_foo, onDestroy()); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); } -TEST_F(ListenerManagerImplTest, NotSupportedDatagramUds) { +TEST_P(ListenerManagerImplTest, NotSupportedDatagramUds) { ProdListenerComponentFactory real_listener_factory(server_); EXPECT_THROW_WITH_MESSAGE(real_listener_factory.createListenSocket( std::make_shared("/foo"), @@ -2022,7 +2022,7 @@ TEST_F(ListenerManagerImplTest, NotSupportedDatagramUds) { "socket type SocketType::Datagram not supported for pipes"); } -TEST_F(ListenerManagerImplTest, CantListen) { +TEST_P(ListenerManagerImplTest, CantListen) { InSequence s; EXPECT_CALL(*worker_, start(_, _)); @@ -2041,7 +2041,7 @@ name: foo ListenerHandle* listener_foo = expectListenerCreate(true, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(listener_foo->target_, initialize()); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml)); EXPECT_CALL(*listener_factory_.socket_->io_handle_, listen(_)) .WillOnce(Return(Api::SysCallIntResult{-1, 100})); @@ -2053,7 +2053,7 @@ name: foo server_.stats_store_.counterFromString("listener_manager.listener_create_failure").value()); } -TEST_F(ListenerManagerImplTest, CantBindSocket) { +TEST_P(ListenerManagerImplTest, CantBindSocket) { time_system_.setSystemTime(std::chrono::milliseconds(1001001001001)); InSequence s; @@ -2076,8 +2076,7 @@ enable_reuse_port: false createListenSocket(_, _, _, ListenerComponentFactory::BindType::NoReusePort, _, 0)) .WillOnce(Throw(EnvoyException("can't bind"))); EXPECT_CALL(*listener_foo, onDestroy()); - EXPECT_THROW(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true), - EnvoyException); + EXPECT_THROW(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml)), EnvoyException); EXPECT_EQ( 1UL, server_.stats_store_.counterFromString("listener_manager.listener_create_failure").value()); @@ -2112,7 +2111,7 @@ enable_reuse_port: false } // Verify that errors tracked on endListenerUpdate show up in the config dump/ -TEST_F(ListenerManagerImplTest, ConfigDumpWithExternalError) { +TEST_P(ListenerManagerImplTest, ConfigDumpWithExternalError) { time_system_.setSystemTime(std::chrono::milliseconds(1001001001001)); InSequence s; @@ -2149,7 +2148,7 @@ TEST_F(ListenerManagerImplTest, ConfigDumpWithExternalError) { )EOF"); } -TEST_F(ListenerManagerImplTest, ListenerDraining) { +TEST_P(ListenerManagerImplTest, ListenerDraining) { InSequence s; EXPECT_CALL(*worker_, start(_, _)); @@ -2168,7 +2167,7 @@ name: foo ListenerHandle* listener_foo = expectListenerCreate(false, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(*worker_, addListener(_, _, _, _)); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); worker_->callAddCompletion(); checkStats(__LINE__, 1, 0, 0, 0, 1, 0, 0); @@ -2199,7 +2198,7 @@ name: foo checkStats(__LINE__, 1, 0, 1, 0, 0, 0, 0); } -TEST_F(ListenerManagerImplTest, RemoveListener) { +TEST_P(ListenerManagerImplTest, RemoveListener) { InSequence s; EXPECT_CALL(*worker_, start(_, _)); @@ -2222,7 +2221,7 @@ name: foo ListenerHandle* listener_foo = expectListenerCreate(true, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(listener_foo->target_, initialize()); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); EXPECT_EQ(0UL, manager_->listeners().size()); checkStats(__LINE__, 1, 0, 0, 1, 0, 0, 0); @@ -2236,7 +2235,7 @@ name: foo listener_foo = expectListenerCreate(true, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(listener_foo->target_, initialize()); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); checkStats(__LINE__, 2, 0, 1, 1, 0, 0, 0); EXPECT_CALL(*worker_, addListener(_, _, _, _)); listener_foo->target_.ready(); @@ -2259,8 +2258,7 @@ per_connection_buffer_limit_bytes: 999 ListenerHandle* listener_foo_update1 = expectListenerCreate(true, true); EXPECT_CALL(*listener_factory_.socket_, duplicate()); EXPECT_CALL(listener_foo_update1->target_, initialize()); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml))); EXPECT_EQ(1UL, manager_->listeners().size()); checkStats(__LINE__, 2, 1, 1, 1, 1, 0, 0); @@ -2282,7 +2280,7 @@ per_connection_buffer_limit_bytes: 999 // Validates that StopListener functionality works correctly when only inbound listeners are // stopped. -TEST_F(ListenerManagerImplTest, StopListeners) { +TEST_P(ListenerManagerImplTest, StopListeners) { InSequence s; EXPECT_CALL(*worker_, start(_, _)); @@ -2304,7 +2302,7 @@ traffic_direction: INBOUND EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(listener_foo->target_, initialize()); auto foo_inbound_proto = parseListenerFromV3Yaml(listener_foo_yaml); - EXPECT_TRUE(manager_->addOrUpdateListener(foo_inbound_proto, "", true)); + EXPECT_TRUE(addOrUpdateListener(foo_inbound_proto)); checkStats(__LINE__, 1, 0, 0, 1, 0, 0, 0); EXPECT_CALL(*worker_, addListener(_, _, _, _)); listener_foo->target_.ready(); @@ -2327,8 +2325,7 @@ traffic_direction: OUTBOUND ListenerHandle* listener_foo_outbound = expectListenerCreate(true, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(listener_foo_outbound->target_, initialize()); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_outbound_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_outbound_yaml))); EXPECT_CALL(*worker_, addListener(_, _, _, _)); listener_foo_outbound->target_.ready(); worker_->callAddCompletion(); @@ -2355,8 +2352,7 @@ traffic_direction: OUTBOUND ListenerHandle* listener_bar_outbound = expectListenerCreate(false, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(*worker_, addListener(_, _, _, _)); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_bar_outbound_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_bar_outbound_yaml))); EXPECT_EQ(3UL, manager_->listeners().size()); worker_->callAddCompletion(); @@ -2371,7 +2367,7 @@ traffic_direction: INBOUND filter_chains: - filters: [] )EOF"; - EXPECT_FALSE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_bar_yaml), "", true)); + EXPECT_FALSE(addOrUpdateListener(parseListenerFromV3Yaml(listener_bar_yaml))); // Explicitly validate that in place filter chain update is not allowed. auto in_place_foo_inbound_proto = foo_inbound_proto; @@ -2380,14 +2376,14 @@ traffic_direction: INBOUND ->mutable_destination_port() ->set_value(9999); - EXPECT_FALSE(manager_->addOrUpdateListener(in_place_foo_inbound_proto, "", true)); + EXPECT_FALSE(addOrUpdateListener(in_place_foo_inbound_proto)); EXPECT_CALL(*listener_foo, onDestroy()); EXPECT_CALL(*listener_foo_outbound, onDestroy()); EXPECT_CALL(*listener_bar_outbound, onDestroy()); } // Validates that StopListener functionality works correctly when all listeners are stopped. -TEST_F(ListenerManagerImplTest, StopAllListeners) { +TEST_P(ListenerManagerImplTest, StopAllListeners) { InSequence s; EXPECT_CALL(*worker_, start(_, _)); @@ -2407,7 +2403,7 @@ name: foo ListenerHandle* listener_foo = expectListenerCreate(true, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(listener_foo->target_, initialize()); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); checkStats(__LINE__, 1, 0, 0, 1, 0, 0, 0); EXPECT_CALL(*worker_, addListener(_, _, _, _)); listener_foo->target_.ready(); @@ -2431,11 +2427,11 @@ name: bar filter_chains: - filters: [] )EOF"; - EXPECT_FALSE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_bar_yaml), "", true)); + EXPECT_FALSE(addOrUpdateListener(parseListenerFromV3Yaml(listener_bar_yaml))); } // Validate that stopping a warming listener, removes directly from warming listener list. -TEST_F(ListenerManagerImplTest, StopWarmingListener) { +TEST_P(ListenerManagerImplTest, StopWarmingListener) { InSequence s; EXPECT_CALL(*worker_, start(_, _)); @@ -2456,7 +2452,7 @@ traffic_direction: INBOUND ListenerHandle* listener_foo = expectListenerCreate(true, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(listener_foo->target_, initialize()); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); checkStats(__LINE__, 1, 0, 0, 1, 0, 0, 0); EXPECT_CALL(*worker_, addListener(_, _, _, _)); listener_foo->target_.ready(); @@ -2480,8 +2476,7 @@ per_connection_buffer_limit_bytes: 999 ListenerHandle* listener_foo_update1 = expectListenerCreate(true, true); EXPECT_CALL(*listener_factory_.socket_, duplicate()); EXPECT_CALL(listener_foo_update1->target_, initialize()); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml))); EXPECT_EQ(1UL, manager_->listeners().size()); // Stop foo which should remove warming listener. @@ -2493,7 +2488,7 @@ per_connection_buffer_limit_bytes: 999 EXPECT_EQ(1, server_.stats_store_.counterFromString("listener_manager.listener_stopped").value()); } -TEST_F(ListenerManagerImplTest, StatsNameValidCharacterTest) { +TEST_P(ListenerManagerImplTest, StatsNameValidCharacterTest) { const std::string yaml = R"EOF( address: socket_address: @@ -2503,13 +2498,13 @@ TEST_F(ListenerManagerImplTest, StatsNameValidCharacterTest) { - filters: [] )EOF"; - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); manager_->listeners().front().get().listenerScope().counterFromString("foo").inc(); EXPECT_EQ(1UL, server_.stats_store_.counterFromString("listener.[__1]_10000.foo").value()); } -TEST_F(ListenerManagerImplTest, ListenerStatPrefix) { +TEST_P(ListenerManagerImplTest, ListenerStatPrefix) { const std::string yaml = R"EOF( stat_prefix: test_prefix address: @@ -2520,13 +2515,13 @@ stat_prefix: test_prefix - filters: [] )EOF"; - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); manager_->listeners().front().get().listenerScope().counterFromString("foo").inc(); EXPECT_EQ(1UL, server_.stats_store_.counterFromString("listener.test_prefix.foo").value()); } -TEST_F(ListenerManagerImplTest, DuplicateAddressDontBind) { +TEST_P(ListenerManagerImplTest, DuplicateAddressDontBind) { InSequence s; EXPECT_CALL(*worker_, start(_, _)); @@ -2548,7 +2543,7 @@ bind_to_port: false EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, ListenerComponentFactory::BindType::NoBind, _, 0)); EXPECT_CALL(listener_foo->target_, initialize()); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); // Add bar with same non-binding address. Should fail. const std::string listener_bar_yaml = R"EOF( @@ -2565,8 +2560,7 @@ bind_to_port: false ListenerHandle* listener_bar = expectListenerCreate(true, true); EXPECT_CALL(*listener_bar, onDestroy()); EXPECT_THROW_WITH_MESSAGE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_bar_yaml), "", true), - EnvoyException, + addOrUpdateListener(parseListenerFromV3Yaml(listener_bar_yaml)), EnvoyException, "error adding listener: 'bar' has duplicate address '0.0.0.0:1234' as existing listener"); // Move foo to active and then try to add again. This should still fail. @@ -2577,14 +2571,13 @@ bind_to_port: false listener_bar = expectListenerCreate(true, true); EXPECT_CALL(*listener_bar, onDestroy()); EXPECT_THROW_WITH_MESSAGE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_bar_yaml), "", true), - EnvoyException, + addOrUpdateListener(parseListenerFromV3Yaml(listener_bar_yaml)), EnvoyException, "error adding listener: 'bar' has duplicate address '0.0.0.0:1234' as existing listener"); EXPECT_CALL(*listener_foo, onDestroy()); } -TEST_F(ListenerManagerImplTest, EarlyShutdown) { +TEST_P(ListenerManagerImplTest, EarlyShutdown) { // If stopWorkers is called before the workers are started, it should be a no-op: they should be // neither started nor stopped. EXPECT_CALL(*worker_, start(_, _)).Times(0); @@ -2592,8 +2585,8 @@ TEST_F(ListenerManagerImplTest, EarlyShutdown) { manager_->stopWorkers(); } -TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDestinationPortMatch) { - const std::string yaml = TestEnvironment::substitute(R"EOF( +TEST_P(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDestinationPortMatch) { + std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } listener_filters: @@ -2603,6 +2596,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDestinationP filter_chains: - filter_chain_match: destination_port: 8080 + name: foo transport_socket: name: tls typed_config: @@ -2612,11 +2606,29 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDestinationP - certificate_chain: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_cert.pem" } private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_key.pem" } )EOF", - Network::Address::IpVersion::v4); + Network::Address::IpVersion::v4); + if (use_matcher_) { + yaml = yaml + R"EOF( + filter_chain_matcher: + matcher_tree: + input: + name: port + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.DestinationPortInput + exact_match_map: + map: + "8080": + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF"; + } EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); // IPv4 client connects to unknown port - no match. @@ -2639,8 +2651,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDestinationP EXPECT_EQ(filter_chain, nullptr); } -TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDirectSourceIPMatch) { - const std::string yaml = TestEnvironment::substitute(R"EOF( +TEST_P(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDirectSourceIPMatch) { + std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } listener_filters: @@ -2650,6 +2662,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDirectSource filter_chains: - filter_chain_match: direct_source_prefix_ranges: { address_prefix: 127.0.0.0, prefix_len: 8 } + name: foo transport_socket: name: tls typed_config: @@ -2659,11 +2672,35 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDirectSource - certificate_chain: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_cert.pem" } private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_key.pem" } )EOF", - Network::Address::IpVersion::v4); + Network::Address::IpVersion::v4); + if (use_matcher_) { + yaml = yaml + R"EOF( + filter_chain_matcher: + matcher_tree: + input: + name: ip + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.DirectSourceIPInput + custom_match: + name: ip-matcher + typed_config: + "@type": type.googleapis.com/xds.type.matcher.v3.IPMatcher + range_matchers: + - ranges: + - address_prefix: 127.0.0.0 + prefix_len: 8 + on_match: + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF"; + } EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); // IPv4 client connects to unknown IP - no match. @@ -2686,8 +2723,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDirectSource EXPECT_EQ(filter_chain, nullptr); } -TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDestinationIPMatch) { - const std::string yaml = TestEnvironment::substitute(R"EOF( +TEST_P(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDestinationIPMatch) { + std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } listener_filters: @@ -2697,6 +2734,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDestinationI filter_chains: - filter_chain_match: prefix_ranges: { address_prefix: 127.0.0.0, prefix_len: 8 } + name: foo transport_socket: name: tls typed_config: @@ -2706,11 +2744,35 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDestinationI - certificate_chain: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_cert.pem" } private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_key.pem" } )EOF", - Network::Address::IpVersion::v4); + Network::Address::IpVersion::v4); + if (use_matcher_) { + yaml = yaml + R"EOF( + filter_chain_matcher: + matcher_tree: + input: + name: ip + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.DestinationIPInput + custom_match: + name: ip-matcher + typed_config: + "@type": type.googleapis.com/xds.type.matcher.v3.IPMatcher + range_matchers: + - ranges: + - address_prefix: 127.0.0.0 + prefix_len: 8 + on_match: + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF"; + } EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); // IPv4 client connects to unknown IP - no match. @@ -2733,8 +2795,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDestinationI EXPECT_EQ(filter_chain, nullptr); } -TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithServerNamesMatch) { - const std::string yaml = TestEnvironment::substitute(R"EOF( +TEST_P(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithServerNamesMatch) { + std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } listener_filters: @@ -2744,6 +2806,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithServerNamesM filter_chains: - filter_chain_match: server_names: "server1.example.com" + name: foo transport_socket: name: tls typed_config: @@ -2753,11 +2816,29 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithServerNamesM - certificate_chain: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_cert.pem" } private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_key.pem" } )EOF", - Network::Address::IpVersion::v4); + Network::Address::IpVersion::v4); + if (use_matcher_) { + yaml = yaml + R"EOF( + filter_chain_matcher: + matcher_tree: + input: + name: ip + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.ServerNameInput + exact_match_map: + map: + "server1.example.com": + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF"; + } EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); // TLS client without SNI - no match. @@ -2781,8 +2862,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithServerNamesM EXPECT_EQ(server_names.front(), "server1.example.com"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithTransportProtocolMatch) { - const std::string yaml = TestEnvironment::substitute(R"EOF( +TEST_P(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithTransportProtocolMatch) { + std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } listener_filters: @@ -2792,6 +2873,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithTransportPro filter_chains: - filter_chain_match: transport_protocol: "tls" + name: foo transport_socket: name: tls typed_config: @@ -2801,11 +2883,29 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithTransportPro - certificate_chain: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_cert.pem" } private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_key.pem" } )EOF", - Network::Address::IpVersion::v4); + Network::Address::IpVersion::v4); + if (use_matcher_) { + yaml = yaml + R"EOF( + filter_chain_matcher: + matcher_tree: + input: + name: transport + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.TransportProtocolInput + exact_match_map: + map: + "tls": + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF"; + } EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); // TCP client - no match. @@ -2824,8 +2924,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithTransportPro EXPECT_EQ(server_names.front(), "server1.example.com"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithApplicationProtocolMatch) { - const std::string yaml = TestEnvironment::substitute(R"EOF( +TEST_P(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithApplicationProtocolMatch) { + std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } listener_filters: @@ -2836,6 +2936,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithApplicationP - filter_chain_match: application_protocols: "http/1.1" source_type: ANY + name: foo transport_socket: name: tls typed_config: @@ -2845,11 +2946,30 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithApplicationP - certificate_chain: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_cert.pem" } private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_key.pem" } )EOF", - Network::Address::IpVersion::v4); + Network::Address::IpVersion::v4); + if (use_matcher_) { + // TODO(kyessenov) Switch to using prefix/suffix/containment matching for ALPN. + yaml = yaml + R"EOF( + filter_chain_matcher: + matcher_tree: + input: + name: application + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.ApplicationProtocolInput + exact_match_map: + map: + "'h2','http/1.1'": + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF"; + } EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); // TLS client without ALPN - no match. @@ -2872,8 +2992,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithApplicationP } // Define a source_type filter chain match and test against it. -TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourceTypeMatch) { - const std::string yaml = TestEnvironment::substitute(R"EOF( +TEST_P(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourceTypeMatch) { + std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } listener_filters: @@ -2883,6 +3003,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourceTypeMa filter_chains: - filter_chain_match: source_type: SAME_IP_OR_LOOPBACK + name: foo transport_socket: name: tls typed_config: @@ -2892,11 +3013,29 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourceTypeMa - certificate_chain: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_cert.pem" } private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_key.pem" } )EOF", - Network::Address::IpVersion::v4); + Network::Address::IpVersion::v4); + if (use_matcher_) { + yaml = yaml + R"EOF( + filter_chain_matcher: + matcher_tree: + input: + name: source-type + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.SourceTypeInput + exact_match_map: + map: + local: + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF"; + } EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); // EXTERNAL IPv4 client without "http/1.1" ALPN - no match. @@ -2932,8 +3071,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourceTypeMa } // Verify source IP matches. -TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourceIpMatch) { - const std::string yaml = TestEnvironment::substitute(R"EOF( +TEST_P(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourceIpMatch) { + std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } listener_filters: @@ -2945,6 +3084,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourceIpMatc source_prefix_ranges: - address_prefix: 10.0.0.1 prefix_len: 24 + name: foo transport_socket: name: tls typed_config: @@ -2954,11 +3094,35 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourceIpMatc - certificate_chain: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_cert.pem" } private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_key.pem" } )EOF", - Network::Address::IpVersion::v4); + Network::Address::IpVersion::v4); + if (use_matcher_) { + yaml = yaml + R"EOF( + filter_chain_matcher: + matcher_tree: + input: + name: ip + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.SourceIPInput + custom_match: + name: ip-matcher + typed_config: + "@type": type.googleapis.com/xds.type.matcher.v3.IPMatcher + range_matchers: + - ranges: + - address_prefix: 10.0.0.1 + prefix_len: 24 + on_match: + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF"; + } EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); // IPv4 client with source 10.0.1.1. No match. @@ -2993,8 +3157,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourceIpMatc } // Verify source IPv6 matches. -TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourceIpv6Match) { - const std::string yaml = TestEnvironment::substitute(R"EOF( +TEST_P(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourceIpv6Match) { + std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } listener_filters: @@ -3006,6 +3170,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourceIpv6Ma source_prefix_ranges: - address_prefix: 2001:0db8:85a3:0000:0000:0000:0000:0000 prefix_len: 64 + name: foo transport_socket: name: tls typed_config: @@ -3015,11 +3180,35 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourceIpv6Ma - certificate_chain: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_cert.pem" } private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_key.pem" } )EOF", - Network::Address::IpVersion::v4); + Network::Address::IpVersion::v4); + if (use_matcher_) { + yaml = yaml + R"EOF( + filter_chain_matcher: + matcher_tree: + input: + name: ip + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.SourceIPInput + custom_match: + name: ip-matcher + typed_config: + "@type": type.googleapis.com/xds.type.matcher.v3.IPMatcher + range_matchers: + - ranges: + - address_prefix: 2001:0db8:85a3:0000:0000:0000:0000:0000 + prefix_len: 64 + on_match: + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF"; + } EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); // IPv6 client with matching subnet. Match. @@ -3034,8 +3223,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourceIpv6Ma } // Verify source port matches. -TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourcePortMatch) { - const std::string yaml = TestEnvironment::substitute(R"EOF( +TEST_P(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourcePortMatch) { + std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } listener_filters: @@ -3046,6 +3235,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourcePortMa - filter_chain_match: source_ports: - 100 + name: foo transport_socket: name: tls typed_config: @@ -3055,11 +3245,29 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourcePortMa - certificate_chain: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_cert.pem" } private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_key.pem" } )EOF", - Network::Address::IpVersion::v4); + Network::Address::IpVersion::v4); + if (use_matcher_) { + yaml = yaml + R"EOF( + filter_chain_matcher: + matcher_tree: + input: + name: port + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.SourcePortInput + exact_match_map: + map: + "100": + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF"; + } EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); // Client with source port 100. Match. @@ -3082,8 +3290,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourcePortMa } // Define multiple source_type filter chain matches and test against them. -TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainWithSourceTypeMatch) { - const std::string yaml = TestEnvironment::substitute(R"EOF( +TEST_P(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithSourceTypeMatch) { + std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } listener_filters: @@ -3093,6 +3301,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainWithSourceType filter_chains: - filter_chain_match: source_type: SAME_IP_OR_LOOPBACK + name: foo transport_socket: name: tls typed_config: @@ -3104,6 +3313,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainWithSourceType - filter_chain_match: application_protocols: "http/1.1" source_type: EXTERNAL + name: bar transport_socket: name: tls typed_config: @@ -3114,6 +3324,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainWithSourceType private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_uri_key.pem" } - filter_chain_match: source_type: ANY + name: baz transport_socket: name: tls typed_config: @@ -3123,11 +3334,66 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainWithSourceType - certificate_chain: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_multiple_dns_cert.pem" } private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_multiple_dns_key.pem" } )EOF", - Network::Address::IpVersion::v4); + Network::Address::IpVersion::v4); + if (use_matcher_) { + // TODO(kyessenov) Switch to using prefix/suffix/containment matching for ALPN. + yaml = yaml + R"EOF( + filter_chain_matcher: + matcher_tree: + input: + name: source-type + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.SourceTypeInput + exact_match_map: + map: + local: + matcher: + matcher_tree: + input: + name: application + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.ApplicationProtocolInput + exact_match_map: + map: + "'h2','http/1.1'": + action: + name: none + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: none + on_no_match: + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + on_no_match: + matcher: + matcher_tree: + input: + name: application + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.ApplicationProtocolInput + exact_match_map: + map: + "'h2','http/1.1'": + action: + name: bar + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: bar + on_no_match: + action: + name: baz + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: baz + )EOF"; + } EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); // LOCAL TLS client with "http/1.1" ALPN - no match. @@ -3171,8 +3437,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainWithSourceType EXPECT_EQ(server_names.front(), "*.example.com"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinationPortMatch) { - const std::string yaml = TestEnvironment::substitute(R"EOF( +TEST_P(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinationPortMatch) { + std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } listener_filters: @@ -3182,6 +3448,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinati filter_chains: - filter_chain_match: # empty + name: foo transport_socket: name: tls typed_config: @@ -3192,6 +3459,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinati private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_uri_key.pem" } - filter_chain_match: destination_port: 8080 + name: bar transport_socket: name: tls typed_config: @@ -3202,6 +3470,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinati private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_key.pem" } - filter_chain_match: destination_port: 8081 + name: baz transport_socket: name: tls typed_config: @@ -3211,11 +3480,41 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinati - certificate_chain: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_multiple_dns_cert.pem" } private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_multiple_dns_key.pem" } )EOF", - Network::Address::IpVersion::v4); + Network::Address::IpVersion::v4); + if (use_matcher_) { + yaml = yaml + R"EOF( + filter_chain_matcher: + matcher_tree: + input: + name: port + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.DestinationPortInput + exact_match_map: + map: + "8080": + action: + name: bar + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: bar + "8081": + action: + name: baz + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: baz + on_no_match: + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF"; + } EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); // IPv4 client connects to default port - using 1st filter chain. @@ -3258,8 +3557,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinati EXPECT_EQ(uri[0], "spiffe://lyft.com/test-team"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinationIPMatch) { - const std::string yaml = TestEnvironment::substitute(R"EOF( +TEST_P(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinationIPMatch) { + std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } listener_filters: @@ -3269,6 +3568,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinati filter_chains: - filter_chain_match: # empty + name: foo transport_socket: name: tls typed_config: @@ -3279,6 +3579,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinati private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_uri_key.pem" } - filter_chain_match: prefix_ranges: { address_prefix: 192.168.0.1, prefix_len: 32 } + name: bar transport_socket: name: tls typed_config: @@ -3289,6 +3590,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinati private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_key.pem" } - filter_chain_match: prefix_ranges: { address_prefix: 192.168.0.0, prefix_len: 16 } + name: baz transport_socket: name: tls typed_config: @@ -3298,11 +3600,50 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinati - certificate_chain: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_multiple_dns_cert.pem" } private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_multiple_dns_key.pem" } )EOF", - Network::Address::IpVersion::v4); + Network::Address::IpVersion::v4); + if (use_matcher_) { + yaml = yaml + R"EOF( + filter_chain_matcher: + matcher_tree: + input: + name: ip + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.DestinationIPInput + custom_match: + name: ip-matcher + typed_config: + "@type": type.googleapis.com/xds.type.matcher.v3.IPMatcher + range_matchers: + - ranges: + - address_prefix: 192.168.0.1 + prefix_len: 32 + on_match: + action: + name: bar + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: bar + - ranges: + - address_prefix: 192.168.0.0 + prefix_len: 16 + on_match: + action: + name: baz + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: baz + on_no_match: + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF"; + } EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); // UDS client connects - using 1st filter chain with no IP match @@ -3354,8 +3695,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinati EXPECT_EQ(uri[0], "spiffe://lyft.com/test-team"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDirectSourceIPMatch) { - const std::string yaml = TestEnvironment::substitute(R"EOF( +TEST_P(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDirectSourceIPMatch) { + std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } listener_filters: @@ -3365,6 +3706,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDirectSou filter_chains: - filter_chain_match: # empty + name: foo transport_socket: name: tls typed_config: @@ -3375,6 +3717,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDirectSou private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_uri_key.pem" } - filter_chain_match: direct_source_prefix_ranges: { address_prefix: 192.168.0.1, prefix_len: 32 } + name: bar transport_socket: name: tls typed_config: @@ -3385,6 +3728,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDirectSou private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_key.pem" } - filter_chain_match: direct_source_prefix_ranges: { address_prefix: 192.168.0.0, prefix_len: 16 } + name: baz transport_socket: name: tls typed_config: @@ -3394,11 +3738,50 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDirectSou - certificate_chain: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_multiple_dns_cert.pem" } private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_multiple_dns_key.pem" } )EOF", - Network::Address::IpVersion::v4); + Network::Address::IpVersion::v4); + if (use_matcher_) { + yaml = yaml + R"EOF( + filter_chain_matcher: + matcher_tree: + input: + name: ip + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.DirectSourceIPInput + custom_match: + name: ip-matcher + typed_config: + "@type": type.googleapis.com/xds.type.matcher.v3.IPMatcher + range_matchers: + - ranges: + - address_prefix: 192.168.0.1 + prefix_len: 32 + on_match: + action: + name: bar + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: bar + - ranges: + - address_prefix: 192.168.0.0 + prefix_len: 16 + on_match: + action: + name: baz + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: baz + on_no_match: + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF"; + } EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); // UDS client connects - using 1st filter chain with no IP match @@ -3441,7 +3824,10 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDirectSou EXPECT_EQ(server_names.front(), "*.example.com"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithServerNamesMatch) { +TEST_P(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithServerNamesMatch) { + if (use_matcher_) { + GTEST_SKIP() << "Server name matching not implemented for unified matcher"; + } const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } @@ -3494,7 +3880,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithServerNam EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); // TLS client without SNI - using 1st filter chain. @@ -3541,8 +3927,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithServerNam EXPECT_EQ(server_names.front(), "*.example.com"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithTransportProtocolMatch) { - const std::string yaml = TestEnvironment::substitute(R"EOF( +TEST_P(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithTransportProtocolMatch) { + std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } listener_filters: @@ -3552,8 +3938,10 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithTransport filter_chains: - filter_chain_match: # empty + name: foo - filter_chain_match: transport_protocol: "tls" + name: bar transport_socket: name: tls typed_config: @@ -3563,11 +3951,35 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithTransport - certificate_chain: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_cert.pem" } private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_key.pem" } )EOF", - Network::Address::IpVersion::v4); + Network::Address::IpVersion::v4); + if (use_matcher_) { + yaml = yaml + R"EOF( + filter_chain_matcher: + matcher_tree: + input: + name: transport + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.TransportProtocolInput + exact_match_map: + map: + "tls": + action: + name: bar + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: bar + on_no_match: + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF"; + } EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); // TCP client - using 1st filter chain. @@ -3587,8 +3999,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithTransport EXPECT_EQ(server_names.front(), "server1.example.com"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithApplicationProtocolMatch) { - const std::string yaml = TestEnvironment::substitute(R"EOF( +TEST_P(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithApplicationProtocolMatch) { + std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } listener_filters: @@ -3596,9 +4008,11 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithApplicati typed_config: "@type": type.googleapis.com/google.protobuf.Struct filter_chains: - - filter_chain_match: + - name: foo + filter_chain_match: # empty - - filter_chain_match: + - name: bar + filter_chain_match: application_protocols: ["dummy", "h2"] transport_socket: name: tls @@ -3609,11 +4023,35 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithApplicati - certificate_chain: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_cert.pem" } private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_key.pem" } )EOF", - Network::Address::IpVersion::v4); + Network::Address::IpVersion::v4); + if (use_matcher_) { + yaml = yaml + R"EOF( + filter_chain_matcher: + matcher_tree: + input: + name: transport + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.ApplicationProtocolInput + exact_match_map: + map: + "'h2','http/1.1'": + action: + name: bar + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: bar + on_no_match: + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF"; + } EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); // TLS client without ALPN - using 1st filter chain. @@ -3636,7 +4074,10 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithApplicati EXPECT_EQ(server_names.front(), "server1.example.com"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithMultipleRequirementsMatch) { +TEST_P(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithMultipleRequirementsMatch) { + if (use_matcher_) { + GTEST_SKIP() << "ALPN list and server name matching not implemented for unified matcher"; + } const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } @@ -3664,7 +4105,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithMultipleR EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); // TLS client without SNI and ALPN - using 1st filter chain. @@ -3700,7 +4141,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithMultipleR EXPECT_EQ(server_names.front(), "server1.example.com"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDifferentSessionTicketKeys) { +TEST_P(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDifferentSessionTicketKeys) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } @@ -3711,6 +4152,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDifferent filter_chains: - filter_chain_match: server_names: "example.com" + name: foo transport_socket: name: tls typed_config: @@ -3724,6 +4166,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDifferent - filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/ticket_key_a" - filter_chain_match: server_names: "www.example.com" + name: bar transport_socket: name: tls typed_config: @@ -3740,11 +4183,11 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDifferent EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); } -TEST_F(ListenerManagerImplWithRealFiltersTest, +TEST_P(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithMixedUseOfSessionTicketKeys) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: @@ -3756,6 +4199,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, filter_chains: - filter_chain_match: server_names: "example.com" + name: foo transport_socket: name: tls typed_config: @@ -3769,6 +4213,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, - filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/ticket_key_a" - filter_chain_match: server_names: "www.example.com" + name: bar transport_socket: name: tls typed_config: @@ -3782,12 +4227,12 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); } -TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithInvalidDestinationIPMatch) { - const std::string yaml = TestEnvironment::substitute(R"EOF( +TEST_P(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithInvalidDestinationIPMatch) { + std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } listener_filters: @@ -3797,14 +4242,43 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithInvalidDesti filter_chains: - filter_chain_match: prefix_ranges: { address_prefix: a.b.c.d, prefix_len: 32 } + name: foo )EOF", - Network::Address::IpVersion::v4); + Network::Address::IpVersion::v4); + + if (use_matcher_) { + yaml = yaml + R"EOF( + filter_chain_matcher: + matcher_tree: + input: + name: ip + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.DestinationIPInput + custom_match: + name: ip-matcher + typed_config: + "@type": type.googleapis.com/xds.type.matcher.v3.IPMatcher + range_matchers: + - ranges: + - address_prefix: a.b.c.d + prefix_len: 32 + on_match: + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF"; + } - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), - EnvoyException, "malformed IP address: a.b.c.d"); + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, + "malformed IP address: a.b.c.d"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithInvalidServerNamesMatch) { +TEST_P(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithInvalidServerNamesMatch) { + if (use_matcher_) { + GTEST_SKIP() << "Server name matching not implemented for unified matcher"; + } const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } @@ -3818,13 +4292,12 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithInvalidServe )EOF", Network::Address::IpVersion::v4); - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), - EnvoyException, + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, "error adding listener '127.0.0.1:1234': partial wildcards are not " "supported in \"server_names\""); } -TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithSameMatch) { +TEST_P(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithSameMatch) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } @@ -3842,13 +4315,16 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithSameMatch )EOF", Network::Address::IpVersion::v4); - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), - EnvoyException, + if (use_matcher_) { + EXPECT_NO_THROW(addOrUpdateListener(parseListenerFromV3Yaml(yaml))); + return; + } + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, "error adding listener '127.0.0.1:1234': filter chain 'bar' has " "the same matching rules defined as 'foo'"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, +TEST_P(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithSameMatchPlusUnimplementedFields) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: @@ -3869,11 +4345,11 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, Network::Address::IpVersion::v4); EXPECT_THROW_WITH_MESSAGE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), EnvoyException, + addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, "error adding listener '127.0.0.1:1234': filter chain 'bar' contains unimplemented fields"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithOverlappingRules) { +TEST_P(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithOverlappingRules) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } @@ -3882,20 +4358,92 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithOverlappi typed_config: "@type": type.googleapis.com/google.protobuf.Struct filter_chains: - - filter_chain_match: + - name: foo + filter_chain_match: server_names: "example.com" - - filter_chain_match: + - name: bar + filter_chain_match: server_names: ["example.com", "www.example.com"] )EOF", Network::Address::IpVersion::v4); - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), - EnvoyException, + if (use_matcher_) { + EXPECT_NO_THROW(addOrUpdateListener(parseListenerFromV3Yaml(yaml))); + return; + } + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, "error adding listener '127.0.0.1:1234': multiple filter chains with " "overlapping matching rules are defined"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, TlsCertificateInline) { +TEST_P(ListenerManagerImplWithRealFiltersTest, MatcherFilterChainWithoutName) { + const std::string yaml = TestEnvironment::substitute(R"EOF( + address: + socket_address: { address: 127.0.0.1, port_value: 1234 } + listener_filters: + - name: tls_inspector + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector + filter_chain_matcher: + matcher_tree: + input: + name: port + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.DestinationPortInput + exact_match_map: + map: + "10000": + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + filter_chains: + - filters: [] + )EOF", + Network::Address::IpVersion::v4); + + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, + "error adding listener '127.0.0.1:1234': \"name\" field is required " + "when using a listener matcher"); +} + +TEST_P(ListenerManagerImplWithRealFiltersTest, MatcherFilterChainWithDuplicateName) { + const std::string yaml = TestEnvironment::substitute(R"EOF( + address: + socket_address: { address: 127.0.0.1, port_value: 1234 } + listener_filters: + - name: tls_inspector + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector + filter_chain_matcher: + matcher_tree: + input: + name: port + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.DestinationPortInput + exact_match_map: + map: + "10000": + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + filter_chains: + - name: foo + filters: [] + - name: foo + filters: [] + )EOF", + Network::Address::IpVersion::v4); + + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, + "error adding listener '127.0.0.1:1234': \"name\" field is duplicated " + "with value 'foo'"); +} + +TEST_P(ListenerManagerImplWithRealFiltersTest, TlsCertificateInline) { const std::string cert = TestEnvironment::readFileToStringForTest(TestEnvironment::substitute( "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns3_chain.pem")); const std::string pkey = TestEnvironment::readFileToStringForTest(TestEnvironment::substitute( @@ -3906,7 +4454,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, TlsCertificateInline) { address: socket_address: { address: 127.0.0.1, port_value: 1234 } filter_chains: - - transport_socket: + - name: foo + transport_socket: name: tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext @@ -3923,18 +4472,19 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, TlsCertificateInline) { EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); } -TEST_F(ListenerManagerImplWithRealFiltersTest, TlsCertificateChainInlinePrivateKeyFilename) { +TEST_P(ListenerManagerImplWithRealFiltersTest, TlsCertificateChainInlinePrivateKeyFilename) { const std::string cert = TestEnvironment::readFileToStringForTest(TestEnvironment::substitute( "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns3_chain.pem")); const std::string yaml = TestEnvironment::substitute(absl::StrCat(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } filter_chains: - - transport_socket: + - name: foo + transport_socket: name: tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext @@ -3948,16 +4498,17 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, TlsCertificateChainInlinePrivateK EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); } -TEST_F(ListenerManagerImplWithRealFiltersTest, TlsCertificateIncomplete) { +TEST_P(ListenerManagerImplWithRealFiltersTest, TlsCertificateIncomplete) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } filter_chains: - - transport_socket: + - name: foo + transport_socket: name: tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext @@ -3967,16 +4518,17 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, TlsCertificateIncomplete) { )EOF", Network::Address::IpVersion::v4); - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), - EnvoyException, "Failed to load incomplete private key from path: "); + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, + "Failed to load incomplete private key from path: "); } -TEST_F(ListenerManagerImplWithRealFiltersTest, TlsCertificateInvalidCertificateChain) { +TEST_P(ListenerManagerImplWithRealFiltersTest, TlsCertificateInvalidCertificateChain) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } filter_chains: - - transport_socket: + - name: foo + transport_socket: name: tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext @@ -3987,11 +4539,11 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, TlsCertificateInvalidCertificateC )EOF", Network::Address::IpVersion::v4); - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), - EnvoyException, "Failed to load certificate chain from "); + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, + "Failed to load certificate chain from "); } -TEST_F(ListenerManagerImplWithRealFiltersTest, TlsCertificateInvalidIntermediateCA) { +TEST_P(ListenerManagerImplWithRealFiltersTest, TlsCertificateInvalidIntermediateCA) { const std::string leaf = TestEnvironment::readFileToStringForTest(TestEnvironment::substitute( "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns3_cert.pem")); const std::string yaml = TestEnvironment::substitute( @@ -4000,7 +4552,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, TlsCertificateInvalidIntermediate address: socket_address: { address: 127.0.0.1, port_value: 1234 } filter_chains: - - transport_socket: + - name: foo + transport_socket: name: tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext @@ -4013,16 +4566,17 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, TlsCertificateInvalidIntermediate )EOF"), Network::Address::IpVersion::v4); - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), - EnvoyException, "Failed to load certificate chain from "); + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, + "Failed to load certificate chain from "); } -TEST_F(ListenerManagerImplWithRealFiltersTest, TlsCertificateInvalidPrivateKey) { +TEST_P(ListenerManagerImplWithRealFiltersTest, TlsCertificateInvalidPrivateKey) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } filter_chains: - - transport_socket: + - name: foo + transport_socket: name: tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext @@ -4033,18 +4587,18 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, TlsCertificateInvalidPrivateKey) )EOF", Network::Address::IpVersion::v4); - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), - EnvoyException, + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, "Failed to load private key from , " "Cause: error:0900006e:PEM routines:OPENSSL_internal:NO_START_LINE"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, TlsCertificateInvalidTrustedCA) { +TEST_P(ListenerManagerImplWithRealFiltersTest, TlsCertificateInvalidTrustedCA) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } filter_chains: - - transport_socket: + - name: foo + transport_socket: name: tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext @@ -4057,16 +4611,17 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, TlsCertificateInvalidTrustedCA) { )EOF", Network::Address::IpVersion::v4); - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), - EnvoyException, "Failed to load trusted CA certificates from "); + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, + "Failed to load trusted CA certificates from "); } -TEST_F(ListenerManagerImplWithRealFiltersTest, TlsCertificateCertPrivateKeyMismatch) { +TEST_P(ListenerManagerImplWithRealFiltersTest, TlsCertificateCertPrivateKeyMismatch) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } filter_chains: - - transport_socket: + - name: foo + transport_socket: name: tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext @@ -4078,12 +4633,12 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, TlsCertificateCertPrivateKeyMisma Network::Address::IpVersion::v4); EXPECT_THROW_WITH_REGEX( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), EnvoyException, + addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, "Failed to load private key from .*, " "Cause: error:0b000074:X.509 certificate routines:OPENSSL_internal:KEY_VALUES_MISMATCH"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, Metadata) { +TEST_P(ListenerManagerImplWithRealFiltersTest, Metadata) { #ifdef SOL_IP const std::string yaml = TestEnvironment::substitute(R"EOF( address: @@ -4092,6 +4647,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, Metadata) { traffic_direction: INBOUND filter_chains: - filter_chain_match: + name: foo filters: - name: http typed_config: @@ -4123,7 +4679,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, Metadata) { return ProdListenerComponentFactory::createListenerFilterFactoryList_(filters, context); })); server_.server_factory_context_->cluster_manager_.initializeClusters({"service_foo"}, {}); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); ASSERT_NE(nullptr, listener_factory_context); EXPECT_EQ("test_value", Config::Metadata::metadataValue( &listener_factory_context->listenerMetadata(), "com.bar.foo", "baz") @@ -4132,7 +4688,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, Metadata) { #endif } -TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstFilterWin32NoTrafficDirection) { +TEST_P(ListenerManagerImplWithRealFiltersTest, OriginalDstFilterWin32NoTrafficDirection) { #ifdef WIN32 const std::string yaml = TestEnvironment::substitute(R"EOF( address: @@ -4145,7 +4701,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstFilterWin32NoTrafficDi )EOF", Network::Address::IpVersion::v4); - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(parseListenerFromV3Yaml(yaml)); , EnvoyException, "[Windows] Setting original destination filter on a listener without " "specifying the traffic_direction." @@ -4153,7 +4709,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstFilterWin32NoTrafficDi #endif } -TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstFilterWin32NoFeatureSupport) { +TEST_P(ListenerManagerImplWithRealFiltersTest, OriginalDstFilterWin32NoFeatureSupport) { #if defined(WIN32) && !defined(SOL_IP) const std::string yaml = TestEnvironment::substitute(R"EOF( address: @@ -4166,19 +4722,21 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstFilterWin32NoFeatureSu "@type": type.googleapis.com/envoy.extensions.filters.listener.original_dst.v3.OriginalDst )EOF", Network::Address::IpVersion::v4); - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(parseListenerFromV3Yaml(yaml)); , EnvoyException, "[Windows] Envoy was compiled without support for `SO_ORIGINAL_DST`, " "the original destination filter cannot be used"); #endif } -TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstFilter) { +TEST_P(ListenerManagerImplWithRealFiltersTest, OriginalDstFilter) { #ifdef SOL_IP const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1111 } - filter_chains: {} + filter_chains: + - filters: [] + name: foo traffic_direction: INBOUND listener_filters: - name: "envoy.filters.listener.original_dst" @@ -4188,7 +4746,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstFilter) { Network::Address::IpVersion::v4); EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); Network::ListenerConfig& listener = manager_->listeners().back().get(); @@ -4255,7 +4813,7 @@ class OriginalDstTestConfigFactory : public Configuration::NamedListenerFilterCo std::string name() const override { return "test.listener.original_dst"; } }; -TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterOutbound) { +TEST_P(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterOutbound) { TestScopedRuntime scoped_runtime; scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); @@ -4266,7 +4824,9 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterOutbound) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1111 } - filter_chains: {} + filter_chains: + - filters: [] + name: foo traffic_direction: OUTBOUND listener_filters: - name: "test.listener.original_dst" @@ -4275,7 +4835,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterOutbound) { EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); Network::ListenerConfig& listener = manager_->listeners().back().get(); @@ -4313,7 +4873,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterOutbound) { #endif } -TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstFilterStopsIteration) { +TEST_P(ListenerManagerImplWithRealFiltersTest, OriginalDstFilterStopsIteration) { TestScopedRuntime scoped_runtime; scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); @@ -4324,7 +4884,9 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstFilterStopsIteration) const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1111 } - filter_chains: {} + filter_chains: + - filters: [] + name: foo traffic_direction: OUTBOUND listener_filters: - name: "test.listener.original_dst" @@ -4333,7 +4895,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstFilterStopsIteration) EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); Network::ListenerConfig& listener = manager_->listeners().back().get(); @@ -4366,7 +4928,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstFilterStopsIteration) #endif } -TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterInbound) { +TEST_P(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterInbound) { TestScopedRuntime scoped_runtime; scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); @@ -4377,7 +4939,9 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterInbound) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1111 } - filter_chains: {} + filter_chains: + - filters: [] + name: foo traffic_direction: INBOUND listener_filters: - name: "test.listener.original_dst" @@ -4386,7 +4950,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterInbound) { EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); Network::ListenerConfig& listener = manager_->listeners().back().get(); @@ -4429,7 +4993,7 @@ class OriginalDstTestFilterIPv6 } }; -TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterIPv6) { +TEST_P(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterIPv6) { class OriginalDstTestConfigFactory : public Configuration::NamedListenerFilterConfigFactory { public: // NamedListenerFilterConfigFactory @@ -4461,7 +5025,9 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterIPv6) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: ::0001, port_value: 1111 } - filter_chains: {} + filter_chains: + - filters: [] + name: foo listener_filters: - name: "test.listener.original_dstipv6" )EOF", @@ -4469,7 +5035,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterIPv6) { EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); Network::ListenerConfig& listener = manager_->listeners().back().get(); @@ -4500,7 +5066,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterIPv6) { // Validate that when neither transparent nor freebind is not set in the // Listener, we see no socket option set. -TEST_F(ListenerManagerImplWithRealFiltersTest, TransparentFreebindListenerDisabled) { +TEST_P(ListenerManagerImplWithRealFiltersTest, TransparentFreebindListenerDisabled) { const std::string yaml = TestEnvironment::substitute(R"EOF( name: "TestListener" address: @@ -4509,7 +5075,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, TransparentFreebindListenerDisabl freebind: false enable_reuse_port: false filter_chains: - - filters: + - filters: [] + name: foo )EOF", Network::Address::IpVersion::v4); EXPECT_CALL(listener_factory_, @@ -4521,7 +5088,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, TransparentFreebindListenerDisabl EXPECT_EQ(options, nullptr); return listener_factory_.socket_; })); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); } @@ -4531,7 +5098,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, TransparentFreebindListenerDisabl // involving the network stack. We only test the IPv4 case here, as the logic // around IPv4/IPv6 handling is tested generically in // socket_option_impl_test.cc. -TEST_F(ListenerManagerImplWithRealFiltersTest, TransparentListenerEnabled) { +TEST_P(ListenerManagerImplWithRealFiltersTest, TransparentListenerEnabled) { auto listener = createIPv4Listener("TransparentListener"); listener.mutable_transparent()->set_value(true); listener.mutable_enable_reuse_port()->set_value(false); @@ -4546,7 +5113,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, TransparentListenerEnabled) { // involving the network stack. We only test the IPv4 case here, as the logic // around IPv4/IPv6 handling is tested generically in // socket_option_impl_test.cc. -TEST_F(ListenerManagerImplWithRealFiltersTest, FreebindListenerEnabled) { +TEST_P(ListenerManagerImplWithRealFiltersTest, FreebindListenerEnabled) { auto listener = createIPv4Listener("FreebindListener"); listener.mutable_freebind()->set_value(true); listener.mutable_enable_reuse_port()->set_value(false); @@ -4561,7 +5128,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, FreebindListenerEnabled) { // involving the network stack. We only test the IPv4 case here, as the logic // around IPv4/IPv6 handling is tested generically in // socket_option_impl_test.cc. -TEST_F(ListenerManagerImplWithRealFiltersTest, FastOpenListenerEnabled) { +TEST_P(ListenerManagerImplWithRealFiltersTest, FastOpenListenerEnabled) { auto listener = createIPv4Listener("FastOpenListener"); listener.mutable_tcp_fast_open_queue_length()->set_value(1); listener.mutable_enable_reuse_port()->set_value(false); @@ -4572,7 +5139,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, FastOpenListenerEnabled) { // Validate that when reuse_port is set in the Listener, we see the socket option // propagated to setsockopt(). -TEST_F(ListenerManagerImplWithRealFiltersTest, ReusePortListenerEnabledForTcp) { +TEST_P(ListenerManagerImplWithRealFiltersTest, ReusePortListenerEnabledForTcp) { auto listener = createIPv4Listener("ReusePortListener"); // When reuse_port is true, port should be 0 for creating the shared socket, // otherwise socket creation will be done on worker thread. @@ -4584,7 +5151,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, ReusePortListenerEnabledForTcp) { } } -TEST_F(ListenerManagerImplWithRealFiltersTest, ReusePortListenerDisabled) { +TEST_P(ListenerManagerImplWithRealFiltersTest, ReusePortListenerDisabled) { auto listener = createIPv4Listener("UdpListener"); listener.mutable_address()->mutable_socket_address()->set_protocol( envoy::config::core::v3::SocketAddress::UDP); @@ -4592,7 +5159,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, ReusePortListenerDisabled) { listener.mutable_enable_reuse_port()->set_value(false); server_.options_.concurrency_ = 2; - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(listener, "", true), EnvoyException, + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(listener), EnvoyException, "Listening on UDP when concurrency is > 1 without the SO_REUSEPORT " "socket option results in " "unstable packet proxying. Configure the reuse_port listener option " @@ -4600,14 +5167,15 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, ReusePortListenerDisabled) { EXPECT_EQ(0, manager_->listeners().size()); } -TEST_F(ListenerManagerImplWithRealFiltersTest, LiteralSockoptListenerEnabled) { +TEST_P(ListenerManagerImplWithRealFiltersTest, LiteralSockoptListenerEnabled) { const envoy::config::listener::v3::Listener listener = parseListenerFromV3Yaml(R"EOF( name: SockoptsListener address: socket_address: { address: 127.0.0.1, port_value: 1111 } enable_reuse_port: false filter_chains: - - filters: + - filters: [] + name: foo socket_options: [ # The socket goes through socket() and bind() but never listen(), so if we # ever saw (7, 8, 9) being applied it would cause a EXPECT_CALL failure. @@ -4628,13 +5196,13 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, LiteralSockoptListenerEnabled) { /* expected_sockopt_level */ 4, /* expected_sockopt_name */ 5, /* expected_value */ 6); - manager_->addOrUpdateListener(listener, "", true); + addOrUpdateListener(listener); EXPECT_EQ(1U, manager_->listeners().size()); } // This test relies on linux-only code, and a linux-only name IPPROTO_MPTCP #if defined(__linux__) -TEST_F(ListenerManagerImplWithRealFiltersTest, Mptcp) { +TEST_P(ListenerManagerImplWithRealFiltersTest, Mptcp) { envoy::config::listener::v3::Listener listener = parseListenerFromV3Yaml(R"EOF( name: mptcp-udp enable_mptcp: true @@ -4643,7 +5211,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, Mptcp) { address: 127.0.0.1 port_value: 1111 filter_chains: - - filters: + - filters: [] + name: foo )EOF"); ListenerHandle* listener_foo = expectListenerCreate(false, true); @@ -4678,13 +5247,13 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, Mptcp) { address, socket_type, options, bind_type, creation_options, worker_index); })); - EXPECT_TRUE(manager_->addOrUpdateListener(listener, "", true)); + EXPECT_TRUE(addOrUpdateListener(listener)); checkStats(__LINE__, 1, 0, 0, 0, 1, 0, 0); EXPECT_CALL(*listener_foo, onDestroy()); } #endif -TEST_F(ListenerManagerImplWithRealFiltersTest, MptcpOnUdp) { +TEST_P(ListenerManagerImplWithRealFiltersTest, MptcpOnUdp) { envoy::config::listener::v3::Listener listener = parseListenerFromV3Yaml(R"EOF( name: mptcp-udp enable_mptcp: true @@ -4694,13 +5263,14 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MptcpOnUdp) { port_value: 1111 protocol: UDP filter_chains: - - filters: + - filters: [] + name: foo )EOF"); - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(listener, "", true), EnvoyException, + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(listener), EnvoyException, "listener mptcp-udp: enable_mptcp can only be used with TCP listeners"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, MptcpOnUnixDomainSocket) { +TEST_P(ListenerManagerImplWithRealFiltersTest, MptcpOnUnixDomainSocket) { envoy::config::listener::v3::Listener listener = parseListenerFromV3Yaml(R"EOF( name: mptcp-udp enable_mptcp: true @@ -4708,13 +5278,14 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MptcpOnUnixDomainSocket) { pipe: path: /path filter_chains: - - filters: + - filters: [] + name: foo )EOF"); - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(listener, "", true), EnvoyException, + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(listener), EnvoyException, "listener mptcp-udp: enable_mptcp can only be used with IP addresses"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, MptcpNotSupported) { +TEST_P(ListenerManagerImplWithRealFiltersTest, MptcpNotSupported) { envoy::config::listener::v3::Listener listener = parseListenerFromV3Yaml(R"EOF( name: mptcp-udp enable_mptcp: true @@ -4723,23 +5294,25 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MptcpNotSupported) { address: 127.0.0.1 port_value: 1111 filter_chains: - - filters: + - filters: [] + name: foo )EOF"); EXPECT_CALL(os_sys_calls_, supportsMptcp()).WillOnce(Return(false)); EXPECT_THROW_WITH_MESSAGE( - manager_->addOrUpdateListener(listener, "", true), EnvoyException, + addOrUpdateListener(listener), EnvoyException, "listener mptcp-udp: enable_mptcp is set but MPTCP is not supported by the operating system"); } // Set the resolver to the default IP resolver. The address resolver logic is unit tested in // resolver_impl_test.cc. -TEST_F(ListenerManagerImplWithRealFiltersTest, AddressResolver) { +TEST_P(ListenerManagerImplWithRealFiltersTest, AddressResolver) { const std::string yaml = TestEnvironment::substitute(R"EOF( name: AddressResolverdListener address: socket_address: { address: 127.0.0.1, port_value: 1111, resolver_name: envoy.mock.resolver } filter_chains: - - filters: + - filters: [] + name: foo )EOF", Network::Address::IpVersion::v4); @@ -4750,16 +5323,17 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, AddressResolver) { Registry::InjectFactory register_resolver(mock_resolver); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); } -TEST_F(ListenerManagerImplWithRealFiltersTest, CRLFilename) { +TEST_P(ListenerManagerImplWithRealFiltersTest, CRLFilename) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } filter_chains: - - transport_socket: + - name: foo + transport_socket: name: tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext @@ -4775,18 +5349,19 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, CRLFilename) { EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); } -TEST_F(ListenerManagerImplWithRealFiltersTest, CRLInline) { +TEST_P(ListenerManagerImplWithRealFiltersTest, CRLInline) { const std::string crl = TestEnvironment::readFileToStringForTest(TestEnvironment::substitute( "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/ca_cert.crl")); const std::string yaml = TestEnvironment::substitute(absl::StrCat(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } filter_chains: - - transport_socket: + - name: foo + transport_socket: name: tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext @@ -4803,16 +5378,17 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, CRLInline) { EXPECT_CALL(server_.api_.random_, uuid()); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); } -TEST_F(ListenerManagerImplWithRealFiltersTest, InvalidCRLInline) { +TEST_P(ListenerManagerImplWithRealFiltersTest, InvalidCRLInline) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } filter_chains: - - transport_socket: + - name: foo + transport_socket: name: tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext @@ -4826,16 +5402,17 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, InvalidCRLInline) { )EOF", Network::Address::IpVersion::v4); - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), - EnvoyException, "Failed to load CRL from "); + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, + "Failed to load CRL from "); } -TEST_F(ListenerManagerImplWithRealFiltersTest, CRLWithNoCA) { +TEST_P(ListenerManagerImplWithRealFiltersTest, CRLWithNoCA) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } filter_chains: - - transport_socket: + - name: foo + transport_socket: name: tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext @@ -4848,16 +5425,17 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, CRLWithNoCA) { )EOF", Network::Address::IpVersion::v4); - EXPECT_THROW_WITH_REGEX(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), - EnvoyException, "^Failed to load CRL from .* without trusted CA$"); + EXPECT_THROW_WITH_REGEX(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, + "^Failed to load CRL from .* without trusted CA$"); } -TEST_F(ListenerManagerImplWithRealFiltersTest, VerifySanWithNoCA) { +TEST_P(ListenerManagerImplWithRealFiltersTest, VerifySanWithNoCA) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } filter_chains: - - transport_socket: + - name: foo + transport_socket: name: tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext @@ -4871,19 +5449,19 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, VerifySanWithNoCA) { )EOF", Network::Address::IpVersion::v4); - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), - EnvoyException, + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, "SAN-based verification of peer certificates without trusted CA " "is insecure and not allowed"); } // Disabling certificate expiration checks only makes sense with a trusted CA. -TEST_F(ListenerManagerImplWithRealFiltersTest, VerifyIgnoreExpirationWithNoCA) { +TEST_P(ListenerManagerImplWithRealFiltersTest, VerifyIgnoreExpirationWithNoCA) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } filter_chains: - - transport_socket: + - name: foo + transport_socket: name: tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext @@ -4896,18 +5474,18 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, VerifyIgnoreExpirationWithNoCA) { )EOF", Network::Address::IpVersion::v4); - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true), - EnvoyException, + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(parseListenerFromV3Yaml(yaml)), EnvoyException, "Certificate validity period is always ignored without trusted CA"); } // Verify that with a CA, expired certificates are allowed. -TEST_F(ListenerManagerImplWithRealFiltersTest, VerifyIgnoreExpirationWithCA) { +TEST_P(ListenerManagerImplWithRealFiltersTest, VerifyIgnoreExpirationWithCA) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: socket_address: { address: 127.0.0.1, port_value: 1234 } filter_chains: - - transport_socket: + - name: foo + transport_socket: name: tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext @@ -4922,17 +5500,17 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, VerifyIgnoreExpirationWithCA) { )EOF", Network::Address::IpVersion::v4); - EXPECT_NO_THROW(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true)); + EXPECT_NO_THROW(addOrUpdateListener(parseListenerFromV3Yaml(yaml))); } // Validate that dispatcher stats prefix is set correctly when enabled. -TEST_F(ListenerManagerImplWithDispatcherStatsTest, DispatherStatsWithCorrectPrefix) { +TEST_P(ListenerManagerImplWithDispatcherStatsTest, DispatherStatsWithCorrectPrefix) { EXPECT_CALL(*worker_, start(_, _)); EXPECT_CALL(*worker_, initializeStats(_)); manager_->startWorkers(guard_dog_, callback_.AsStdFunction()); } -TEST_F(ListenerManagerImplWithRealFiltersTest, ApiListener) { +TEST_P(ListenerManagerImplWithRealFiltersTest, ApiListener) { const std::string yaml = R"EOF( name: test_api_listener address: @@ -4958,12 +5536,12 @@ name: test_api_listener server_.server_factory_context_->cluster_manager_.initializeClusters( {"dynamic_forward_proxy_cluster"}, {}); - ASSERT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", false)); + ASSERT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", false)); EXPECT_EQ(0U, manager_->listeners().size()); ASSERT_TRUE(manager_->apiListener().has_value()); } -TEST_F(ListenerManagerImplWithRealFiltersTest, ApiListenerNotAllowedAddedViaApi) { +TEST_P(ListenerManagerImplWithRealFiltersTest, ApiListenerNotAllowedAddedViaApi) { const std::string yaml = R"EOF( name: test_api_listener address: @@ -4987,12 +5565,12 @@ name: test_api_listener cluster: dynamic_forward_proxy_cluster )EOF"; - ASSERT_FALSE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true)); + ASSERT_FALSE(addOrUpdateListener(parseListenerFromV3Yaml(yaml))); EXPECT_EQ(0U, manager_->listeners().size()); ASSERT_FALSE(manager_->apiListener().has_value()); } -TEST_F(ListenerManagerImplWithRealFiltersTest, ApiListenerOnlyOneApiListener) { +TEST_P(ListenerManagerImplWithRealFiltersTest, ApiListenerOnlyOneApiListener) { const std::string yaml = R"EOF( name: test_api_listener address: @@ -5041,20 +5619,23 @@ name: test_api_listener_2 server_.server_factory_context_->cluster_manager_.initializeClusters( {"dynamic_forward_proxy_cluster"}, {}); - ASSERT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", false)); + ASSERT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", false)); EXPECT_EQ(0U, manager_->listeners().size()); ASSERT_TRUE(manager_->apiListener().has_value()); EXPECT_EQ("test_api_listener", manager_->apiListener()->get().name()); // Only one ApiListener is added. - ASSERT_FALSE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", false)); + ASSERT_FALSE(addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", false)); EXPECT_EQ(0U, manager_->listeners().size()); // The original ApiListener is there. ASSERT_TRUE(manager_->apiListener().has_value()); EXPECT_EQ("test_api_listener", manager_->apiListener()->get().name()); } -TEST_F(ListenerManagerImplWithRealFiltersTest, AddOrUpdateInternalListener) { +TEST_P(ListenerManagerImplWithRealFiltersTest, AddOrUpdateInternalListener) { + if (use_matcher_) { + GTEST_SKIP() << "Filter chain match is auto-inserted in the config dump"; + } auto scoped_runtime = std::make_unique(); scoped_runtime->mergeValues({{"envoy.reloadable_features.internal_address", "true"}}); time_system_.setSystemTime(std::chrono::milliseconds(1001001001001)); @@ -5077,12 +5658,13 @@ name: test_internal_listener address: envoy_internal_address: server_listener_name: test_internal_listener_name -filter_chains: {} +filter_chains: +- filters: [] + name: foo )EOF"; ListenerHandle* listener_foo = expectListenerCreate(false, true); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "version1", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "version1", true)); checkStats(__LINE__, 1, 0, 0, 0, 1, 0, 0); EXPECT_CALL(*lds_api, versionInfo()).WillOnce(Return("version1")); checkConfigDump(R"EOF( @@ -5098,14 +5680,16 @@ version_info: version1 address: envoy_internal_address: server_listener_name: test_internal_listener_name - filter_chains: {} + filter_chains: + - filters: [] + name: foo last_updated: seconds: 1001001001 nanos: 1000000 )EOF"); // Update duplicate should be a NOP. - EXPECT_FALSE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_FALSE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); checkStats(__LINE__, 1, 0, 0, 0, 1, 0, 0); // Update foo listener. Should share socket. @@ -5114,7 +5698,9 @@ name: test_internal_listener address: envoy_internal_address: server_listener_name: test_internal_listener_name -filter_chains: {} +filter_chains: +- filters: [] + name: foo per_connection_buffer_limit_bytes: 10 )EOF"; @@ -5122,8 +5708,8 @@ per_connection_buffer_limit_bytes: 10 ListenerHandle* listener_foo_update1 = expectListenerCreate(false, true); EXPECT_CALL(*listener_foo, onDestroy()); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml), - "version2", true)); + EXPECT_TRUE( + addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml), "version2", true)); checkStats(__LINE__, 1, 1, 0, 0, 1, 0, 0); EXPECT_CALL(*lds_api, versionInfo()).WillOnce(Return("version2")); checkConfigDump(R"EOF( @@ -5139,7 +5725,9 @@ per_connection_buffer_limit_bytes: 10 address: envoy_internal_address: server_listener_name: test_internal_listener_name - filter_chains: {} + filter_chains: + - filters: [] + name: foo per_connection_buffer_limit_bytes: 10 last_updated: seconds: 2002002002 @@ -5169,8 +5757,7 @@ per_connection_buffer_limit_bytes: 10 .value()); // Update duplicate should be a NOP. - EXPECT_FALSE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml), "", true)); + EXPECT_FALSE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml))); checkStats(__LINE__, 1, 1, 0, 0, 1, 0, 0); time_system_.setSystemTime(std::chrono::milliseconds(3003003003003)); @@ -5181,8 +5768,7 @@ per_connection_buffer_limit_bytes: 10 EXPECT_CALL(*worker_, addListener(_, _, _, _)); EXPECT_CALL(*worker_, stopListener(_, _)); EXPECT_CALL(*listener_foo_update1->drain_manager_, startDrainSequence(_)); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "version3", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "version3", true)); worker_->callAddCompletion(); checkStats(__LINE__, 1, 2, 0, 0, 1, 1, 0); EXPECT_CALL(*lds_api, versionInfo()).WillOnce(Return("version3")); @@ -5199,7 +5785,9 @@ per_connection_buffer_limit_bytes: 10 address: envoy_internal_address: server_listener_name: test_internal_listener_name - filter_chains: {} + filter_chains: + - filters: [] + name: foo last_updated: seconds: 3003003003 nanos: 3000000 @@ -5211,7 +5799,9 @@ per_connection_buffer_limit_bytes: 10 address: envoy_internal_address: server_listener_name: test_internal_listener_name - filter_chains: {} + filter_chains: + - filters: [] + name: foo per_connection_buffer_limit_bytes: 10 last_updated: seconds: 2002002002 @@ -5233,14 +5823,15 @@ per_connection_buffer_limit_bytes: 10 address: envoy_internal_address: server_listener_name: test_internal_listener_bar - filter_chains: {} + filter_chains: + - filters: [] + name: foo internal_listener: {} )EOF"; ListenerHandle* listener_bar = expectListenerCreate(false, true); EXPECT_CALL(*worker_, addListener(_, _, _, _)); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_bar_yaml), "version4", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_bar_yaml), "version4", true)); EXPECT_EQ(2UL, manager_->listeners().size()); worker_->callAddCompletion(); checkStats(__LINE__, 2, 2, 0, 0, 2, 0, 0); @@ -5253,14 +5844,15 @@ per_connection_buffer_limit_bytes: 10 address: envoy_internal_address: server_listener_name: test_internal_listener_baz - filter_chains: {} + filter_chains: + - filters: [] + name: foo internal_listener: {} )EOF"; ListenerHandle* listener_baz = expectListenerCreate(true, true); EXPECT_CALL(listener_baz->target_, initialize()); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_baz_yaml), "version5", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_baz_yaml), "version5", true)); EXPECT_EQ(2UL, manager_->listeners().size()); checkStats(__LINE__, 3, 2, 0, 1, 2, 0, 0); EXPECT_CALL(*lds_api, versionInfo()).WillOnce(Return("version5")); @@ -5276,7 +5868,9 @@ per_connection_buffer_limit_bytes: 10 address: envoy_internal_address: server_listener_name: test_internal_listener_name - filter_chains: {} + filter_chains: + - filters: [] + name: foo last_updated: seconds: 3003003003 nanos: 3000000 @@ -5289,7 +5883,9 @@ per_connection_buffer_limit_bytes: 10 address: envoy_internal_address: server_listener_name: test_internal_listener_bar - filter_chains: {} + filter_chains: + - filters: [] + name: foo internal_listener: {} last_updated: seconds: 4004004004 @@ -5303,7 +5899,9 @@ per_connection_buffer_limit_bytes: 10 address: envoy_internal_address: server_listener_name: test_internal_listener_baz - filter_chains: {} + filter_chains: + - filters: [] + name: foo internal_listener: {} last_updated: seconds: 5005005005 @@ -5311,7 +5909,7 @@ per_connection_buffer_limit_bytes: 10 )EOF"); // Update a duplicate baz that is currently warming. - EXPECT_FALSE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_baz_yaml), "", true)); + EXPECT_FALSE(addOrUpdateListener(parseListenerFromV3Yaml(listener_baz_yaml))); checkStats(__LINE__, 3, 2, 0, 1, 2, 0, 0); // Update baz while it is warming. @@ -5324,6 +5922,8 @@ per_connection_buffer_limit_bytes: 10 filter_chains: - filters: - name: fake + typed_config: {} + name: foo )EOF"; ListenerHandle* listener_baz_update1 = expectListenerCreate(true, true); @@ -5332,8 +5932,7 @@ per_connection_buffer_limit_bytes: 10 listener_baz->target_.ready(); })); EXPECT_CALL(listener_baz_update1->target_, initialize()); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_baz_update1_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_baz_update1_yaml))); EXPECT_EQ(2UL, manager_->listeners().size()); checkStats(__LINE__, 3, 3, 0, 1, 2, 0, 0); @@ -5349,7 +5948,7 @@ per_connection_buffer_limit_bytes: 10 EXPECT_CALL(*listener_baz_update1, onDestroy()); } -TEST_F(ListenerManagerImplTest, StopInplaceWarmingListener) { +TEST_P(ListenerManagerImplTest, StopInplaceWarmingListener) { InSequence s; EXPECT_CALL(*worker_, start(_, _)); @@ -5370,7 +5969,7 @@ traffic_direction: INBOUND ListenerHandle* listener_foo = expectListenerCreate(true, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(listener_foo->target_, initialize()); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); EXPECT_EQ(0, server_.stats_store_.counter("listener_manager.listener_in_place_updated").value()); checkStats(__LINE__, 1, 0, 0, 1, 0, 0, 0); @@ -5397,8 +5996,7 @@ traffic_direction: INBOUND ListenerHandle* listener_foo_update1 = expectListenerOverridden(true); EXPECT_CALL(*listener_factory_.socket_, duplicate()); EXPECT_CALL(listener_foo_update1->target_, initialize()); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml))); EXPECT_EQ(1, server_.stats_store_.counter("listener_manager.listener_in_place_updated").value()); EXPECT_EQ(1UL, manager_->listeners().size()); @@ -5412,7 +6010,7 @@ traffic_direction: INBOUND EXPECT_EQ(1, server_.stats_store_.counter("listener_manager.listener_stopped").value()); } -TEST_F(ListenerManagerImplTest, RemoveInplaceUpdatingListener) { +TEST_P(ListenerManagerImplTest, RemoveInplaceUpdatingListener) { InSequence s; EXPECT_CALL(*worker_, start(_, _)); @@ -5433,7 +6031,7 @@ traffic_direction: INBOUND ListenerHandle* listener_foo = expectListenerCreate(true, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(listener_foo->target_, initialize()); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); EXPECT_EQ(0, server_.stats_store_.counter("listener_manager.listener_in_place_updated").value()); checkStats(__LINE__, 1, 0, 0, 1, 0, 0, 0); @@ -5459,8 +6057,7 @@ traffic_direction: INBOUND ListenerHandle* listener_foo_update1 = expectListenerOverridden(true); EXPECT_CALL(*listener_factory_.socket_, duplicate()); EXPECT_CALL(listener_foo_update1->target_, initialize()); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml))); EXPECT_EQ(1, server_.stats_store_.counter("listener_manager.listener_in_place_updated").value()); EXPECT_EQ(1UL, manager_->listeners().size()); @@ -5482,7 +6079,7 @@ traffic_direction: INBOUND checkStats(__LINE__, 1, 1, 1, 0, 0, 0, 0); } -TEST_F(ListenerManagerImplTest, UpdateInplaceWarmingListener) { +TEST_P(ListenerManagerImplTest, UpdateInplaceWarmingListener) { InSequence s; EXPECT_CALL(*worker_, start(_, _)); @@ -5503,7 +6100,7 @@ traffic_direction: INBOUND ListenerHandle* listener_foo = expectListenerCreate(true, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(listener_foo->target_, initialize()); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); EXPECT_EQ(0, server_.stats_store_.counter("listener_manager.listener_in_place_updated").value()); checkStats(__LINE__, 1, 0, 0, 1, 0, 0, 0); @@ -5529,8 +6126,7 @@ traffic_direction: INBOUND ListenerHandle* listener_foo_update1 = expectListenerOverridden(true); EXPECT_CALL(*listener_factory_.socket_, duplicate()); EXPECT_CALL(listener_foo_update1->target_, initialize()); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml))); EXPECT_EQ(1, server_.stats_store_.counter("listener_manager.listener_in_place_updated").value()); EXPECT_EQ(1UL, manager_->listeners().size()); @@ -5546,7 +6142,7 @@ traffic_direction: INBOUND EXPECT_CALL(*listener_foo_update1, onDestroy()); } -TEST_F(ListenerManagerImplForInPlaceFilterChainUpdateTest, RemoveTheInplaceUpdatingListener) { +TEST_P(ListenerManagerImplForInPlaceFilterChainUpdateTest, RemoveTheInplaceUpdatingListener) { InSequence s; EXPECT_CALL(*worker_, start(_, _)); @@ -5567,7 +6163,7 @@ traffic_direction: INBOUND ListenerHandle* listener_foo = expectListenerCreate(true, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(listener_foo->target_, initialize()); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); checkStats(__LINE__, 1, 0, 0, 1, 0, 0, 0); EXPECT_CALL(*worker_, addListener(_, _, _, _)); listener_foo->target_.ready(); @@ -5593,7 +6189,7 @@ traffic_direction: INBOUND EXPECT_CALL(*listener_factory_.socket_, duplicate()) .WillOnce(Return(ByMove(std::unique_ptr(duplicated_socket)))); EXPECT_CALL(listener_foo_update1->target_, initialize()); - EXPECT_TRUE(manager_->addOrUpdateListener(listener_foo_update1_proto, "", true)); + EXPECT_TRUE(addOrUpdateListener(listener_foo_update1_proto)); EXPECT_EQ(1UL, manager_->listeners().size()); EXPECT_EQ(1, server_.stats_store_.counter("listener_manager.listener_in_place_updated").value()); checkStats(__LINE__, 1, 1, 0, 1, 1, 0, 0); @@ -5632,7 +6228,7 @@ traffic_direction: INBOUND checkStats(__LINE__, 1, 2, 1, 0, 0, 0, 0); } -TEST_F(ListenerManagerImplTest, DrainageDuringInplaceUpdate) { +TEST_P(ListenerManagerImplTest, DrainageDuringInplaceUpdate) { InSequence s; EXPECT_CALL(*worker_, start(_, _)); @@ -5653,7 +6249,7 @@ traffic_direction: INBOUND ListenerHandle* listener_foo = expectListenerCreate(true, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(listener_foo->target_, initialize()); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); checkStats(__LINE__, 1, 0, 0, 1, 0, 0, 0); EXPECT_CALL(*worker_, addListener(_, _, _, _)); listener_foo->target_.ready(); @@ -5677,8 +6273,7 @@ traffic_direction: INBOUND ListenerHandle* listener_foo_update1 = expectListenerOverridden(true); EXPECT_CALL(*listener_factory_.socket_, duplicate()); EXPECT_CALL(listener_foo_update1->target_, initialize()); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml))); EXPECT_EQ(1UL, manager_->listeners().size()); EXPECT_EQ(1, server_.stats_store_.counter("listener_manager.listener_in_place_updated").value()); checkStats(__LINE__, 1, 1, 0, 1, 1, 0, 0); @@ -5703,7 +6298,7 @@ traffic_direction: INBOUND EXPECT_CALL(*listener_foo_update1, onDestroy()); } -TEST_F(ListenerManagerImplTest, ListenSocketFactoryIsClonedFromListenerDrainingFilterChain) { +TEST_P(ListenerManagerImplTest, ListenSocketFactoryIsClonedFromListenerDrainingFilterChain) { InSequence s; EXPECT_CALL(*worker_, start(_, _)); @@ -5724,7 +6319,7 @@ traffic_direction: INBOUND ListenerHandle* listener_foo = expectListenerCreate(true, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); EXPECT_CALL(listener_foo->target_, initialize()); - EXPECT_TRUE(manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml))); checkStats(__LINE__, 1, 0, 0, 1, 0, 0, 0); EXPECT_CALL(*worker_, addListener(_, _, _, _)); listener_foo->target_.ready(); @@ -5748,8 +6343,7 @@ traffic_direction: INBOUND ListenerHandle* listener_foo_update1 = expectListenerOverridden(true, listener_foo); EXPECT_CALL(*listener_factory_.socket_, duplicate()); EXPECT_CALL(listener_foo_update1->target_, initialize()); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml), "", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml))); EXPECT_EQ(1UL, manager_->listeners().size()); EXPECT_EQ(1, server_.stats_store_.counter("listener_manager.listener_in_place_updated").value()); checkStats(__LINE__, 1, 1, 0, 1, 1, 0, 0); @@ -5791,8 +6385,7 @@ traffic_direction: INBOUND EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, _, _, _)).Times(0); EXPECT_CALL(*listener_factory_.socket_, duplicate()); EXPECT_CALL(listener_foo_expect_reuse_socket->target_, initialize()); - EXPECT_TRUE( - manager_->addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "version1", true)); + EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_yaml), "version1", true)); EXPECT_CALL(*listener_foo, onDestroy()); EXPECT_CALL(*listener_foo_expect_reuse_socket, onDestroy()); @@ -5842,6 +6435,27 @@ TEST(ListenerMessageUtilTest, ListenerDefaultFilterChainChangeIsAlwaysFilterChai *listener2.mutable_default_filter_chain() = default_filter_chain_2; EXPECT_TRUE(Server::ListenerMessageUtil::filterChainOnlyChange(listener1, listener2)); } + { + listener1.clear_default_filter_chain(); + listener2.clear_default_filter_chain(); + const std::string filter_chain_matcher = R"EOF( + matcher_tree: + input: + name: port + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.DestinationPortInput + exact_match_map: + map: + "10000": + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF"; + TestUtility::loadFromYaml(filter_chain_matcher, *listener2.mutable_filter_chain_matcher()); + EXPECT_TRUE(Server::ListenerMessageUtil::filterChainOnlyChange(listener1, listener2)); + } } TEST(ListenerMessageUtilTest, ListenerMessageHaveDifferentFilterChainsAreEquivalent) { @@ -5858,12 +6472,12 @@ TEST(ListenerMessageUtilTest, ListenerMessageHaveDifferentFilterChainsAreEquival EXPECT_TRUE(Server::ListenerMessageUtil::filterChainOnlyChange(listener1, listener2)); } -TEST_F(ListenerManagerImplForInPlaceFilterChainUpdateTest, TraditionalUpdateIfWorkerNotStarted) { +TEST_P(ListenerManagerImplForInPlaceFilterChainUpdateTest, TraditionalUpdateIfWorkerNotStarted) { // Worker is not started yet. auto listener_proto = createDefaultListener(); ListenerHandle* listener_foo = expectListenerCreate(false, true); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); - manager_->addOrUpdateListener(listener_proto, "", true); + addOrUpdateListener(listener_proto); EXPECT_EQ(1u, manager_->listeners().size()); // Mutate the listener message as filter chain change only. @@ -5876,14 +6490,14 @@ TEST_F(ListenerManagerImplForInPlaceFilterChainUpdateTest, TraditionalUpdateIfWo EXPECT_CALL(*listener_foo, onDestroy()); ListenerHandle* listener_foo_update1 = expectListenerCreate(false, true); EXPECT_CALL(*listener_factory_.socket_, duplicate()); - manager_->addOrUpdateListener(new_listener_proto, "", true); + addOrUpdateListener(new_listener_proto); EXPECT_CALL(*listener_foo_update1, onDestroy()); EXPECT_EQ(0, server_.stats_store_.counter("listener_manager.listener_in_place_updated").value()); } // This case verifies that listeners that share port but do not share socket type (TCP vs. UDP) // do not share a listener. -TEST_F(ListenerManagerImplForInPlaceFilterChainUpdateTest, TraditionalUpdateIfDifferentSocketType) { +TEST_P(ListenerManagerImplForInPlaceFilterChainUpdateTest, TraditionalUpdateIfDifferentSocketType) { EXPECT_CALL(*worker_, start(_, _)); manager_->startWorkers(guard_dog_, callback_.AsStdFunction()); @@ -5899,8 +6513,7 @@ TEST_F(ListenerManagerImplForInPlaceFilterChainUpdateTest, TraditionalUpdateIfDi EXPECT_CALL(server_.validation_context_, staticValidationVisitor()).Times(0); EXPECT_CALL(server_.validation_context_, dynamicValidationVisitor()); EXPECT_CALL(listener_factory_, createDrainManager_(_)); - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(new_listener_proto, "", true), - EnvoyException, + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(new_listener_proto), EnvoyException, "error adding listener '127.0.0.1:1234': 1 filter chain(s) specified " "for connection-less UDP listener."); @@ -5909,7 +6522,7 @@ TEST_F(ListenerManagerImplForInPlaceFilterChainUpdateTest, TraditionalUpdateIfDi EXPECT_EQ(0, server_.stats_store_.counter("listener_manager.listener_in_place_updated").value()); } -TEST_F(ListenerManagerImplForInPlaceFilterChainUpdateTest, +TEST_P(ListenerManagerImplForInPlaceFilterChainUpdateTest, DEPRECATED_FEATURE_TEST(TraditionalUpdateIfImplicitProxyProtocolChanges)) { EXPECT_CALL(*worker_, start(_, _)); manager_->startWorkers(guard_dog_, callback_.AsStdFunction()); @@ -5931,7 +6544,7 @@ TEST_F(ListenerManagerImplForInPlaceFilterChainUpdateTest, EXPECT_EQ(0, server_.stats_store_.counter("listener_manager.listener_in_place_updated").value()); } -TEST_F(ListenerManagerImplForInPlaceFilterChainUpdateTest, TraditionalUpdateOnZeroFilterChain) { +TEST_P(ListenerManagerImplForInPlaceFilterChainUpdateTest, TraditionalUpdateOnZeroFilterChain) { EXPECT_CALL(*worker_, start(_, _)); manager_->startWorkers(guard_dog_, callback_.AsStdFunction()); @@ -5945,8 +6558,7 @@ TEST_F(ListenerManagerImplForInPlaceFilterChainUpdateTest, TraditionalUpdateOnZe EXPECT_CALL(server_.validation_context_, staticValidationVisitor()).Times(0); EXPECT_CALL(server_.validation_context_, dynamicValidationVisitor()); EXPECT_CALL(listener_factory_, createDrainManager_(_)); - EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(new_listener_proto, "", true), - EnvoyException, + EXPECT_THROW_WITH_MESSAGE(addOrUpdateListener(new_listener_proto), EnvoyException, "error adding listener '127.0.0.1:1234': no filter chains specified"); expectRemove(listener_proto, listener_foo, *listener_factory_.socket_); @@ -5954,7 +6566,7 @@ TEST_F(ListenerManagerImplForInPlaceFilterChainUpdateTest, TraditionalUpdateOnZe EXPECT_EQ(0, server_.stats_store_.counter("listener_manager.listener_in_place_updated").value()); } -TEST_F(ListenerManagerImplForInPlaceFilterChainUpdateTest, +TEST_P(ListenerManagerImplForInPlaceFilterChainUpdateTest, TraditionalUpdateIfListenerConfigHasUpdateOtherThanFilterChain) { EXPECT_CALL(*worker_, start(_, _)); manager_->startWorkers(guard_dog_, callback_.AsStdFunction()); @@ -5979,7 +6591,7 @@ TEST_F(ListenerManagerImplForInPlaceFilterChainUpdateTest, // This test verifies that on default initialization the UDP Packet Writer // is initialized in passthrough mode. (i.e. by using UdpDefaultWriter). -TEST_F(ListenerManagerImplTest, UdpDefaultWriterConfig) { +TEST_P(ListenerManagerImplTest, UdpDefaultWriterConfig) { const envoy::config::listener::v3::Listener listener = parseListenerFromV3Yaml(R"EOF( address: socket_address: @@ -5987,7 +6599,7 @@ TEST_F(ListenerManagerImplTest, UdpDefaultWriterConfig) { protocol: UDP port_value: 1234 )EOF"); - manager_->addOrUpdateListener(listener, "", true); + addOrUpdateListener(listener); EXPECT_EQ(1U, manager_->listeners().size()); Network::SocketSharedPtr listen_socket = manager_->listeners().front().get().listenSocketFactory().getListenSocket(0); @@ -6002,7 +6614,7 @@ TEST_F(ListenerManagerImplTest, UdpDefaultWriterConfig) { EXPECT_FALSE(udp_packet_writer->isBatchMode()); } -TEST_F(ListenerManagerImplTest, TcpBacklogCustomConfig) { +TEST_P(ListenerManagerImplTest, TcpBacklogCustomConfig) { const std::string yaml = TestEnvironment::substitute(R"EOF( name: TcpBacklogConfigListener address: @@ -6014,12 +6626,12 @@ TEST_F(ListenerManagerImplTest, TcpBacklogCustomConfig) { Network::Address::IpVersion::v4); EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, _, _, _)); - manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + addOrUpdateListener(parseListenerFromV3Yaml(yaml)); EXPECT_EQ(1U, manager_->listeners().size()); EXPECT_EQ(100U, manager_->listeners().back().get().tcpBacklogSize()); } -TEST_F(ListenerManagerImplTest, WorkersStartedCallbackCalled) { +TEST_P(ListenerManagerImplTest, WorkersStartedCallbackCalled) { InSequence s; EXPECT_CALL(*worker_, start(_, _)); @@ -6070,6 +6682,14 @@ TEST(ListenerEnableReusePortTest, All) { } } +INSTANTIATE_TEST_SUITE_P(Matcher, ListenerManagerImplTest, ::testing::Values(false)); +INSTANTIATE_TEST_SUITE_P(Matcher, ListenerManagerImplWithRealFiltersTest, + ::testing::Values(false, true)); +INSTANTIATE_TEST_SUITE_P(Matcher, ListenerManagerImplForInPlaceFilterChainUpdateTest, + ::testing::Values(false)); +INSTANTIATE_TEST_SUITE_P(Matcher, ListenerManagerImplWithDispatcherStatsTest, + ::testing::Values(false)); + } // namespace } // namespace Server } // namespace Envoy diff --git a/test/server/listener_manager_impl_test.h b/test/server/listener_manager_impl_test.h index 42487dc765981..8adb7e7a92073 100644 --- a/test/server/listener_manager_impl_test.h +++ b/test/server/listener_manager_impl_test.h @@ -52,7 +52,7 @@ class ListenerHandle { Configuration::FactoryContext* context_{}; }; -class ListenerManagerImplTest : public testing::Test { +class ListenerManagerImplTest : public testing::TestWithParam { public: // reuse_port is the default on Linux for TCP. On other platforms even if set it is disabled // and the user is warned. For UDP it's always the default even if not effective. @@ -64,7 +64,8 @@ class ListenerManagerImplTest : public testing::Test { #endif protected: - ListenerManagerImplTest() : api_(Api::createApiForTest(server_.api_.random_)) {} + ListenerManagerImplTest() + : api_(Api::createApiForTest(server_.api_.random_)), use_matcher_(GetParam()) {} void SetUp() override { ON_CALL(server_, api()).WillByDefault(ReturnRef(*api_)); @@ -296,12 +297,43 @@ class ListenerManagerImplTest : public testing::Test { server_.admin_.config_tracker_.config_tracker_callbacks_["listeners"](name_matcher); const auto& listeners_config_dump = dynamic_cast(*message_ptr); - envoy::admin::v3::ListenersConfigDump expected_listeners_config_dump; TestUtility::loadFromYaml(expected_dump_yaml, expected_listeners_config_dump); EXPECT_EQ(expected_listeners_config_dump.DebugString(), listeners_config_dump.DebugString()); } + bool addOrUpdateListener(const envoy::config::listener::v3::Listener& config, + const std::string& version_info = "", bool added_via_api = true) { + // Automatically inject a matcher that always matches "foo" if not present. + envoy::config::listener::v3::Listener listener; + listener.MergeFrom(config); + if (use_matcher_ && !listener.has_filter_chain_matcher()) { + const std::string filter_chain_matcher = R"EOF( + matcher_tree: + input: + name: port + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.DestinationPortInput + exact_match_map: + map: + "10000": + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + on_no_match: + action: + name: foo + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF"; + TestUtility::loadFromYaml(filter_chain_matcher, *listener.mutable_filter_chain_matcher()); + } + return manager_->addOrUpdateListener(listener, version_info, added_via_api); + } + NiceMock os_sys_calls_; TestThreadsafeSingletonInjector os_calls_{&os_sys_calls_}; Api::OsSysCallsImpl os_sys_calls_actual_; @@ -329,7 +361,8 @@ class ListenerManagerImplTest : public testing::Test { uint64_t listener_tag_{1}; bool enable_dispatcher_stats_{false}; NiceMock> callback_; + // Test parameter indicating whether the unified filter chain matcher is enabled. + bool use_matcher_; }; - } // namespace Server } // namespace Envoy