From 3a914cf0c575753ae05ce372690066e57a91884c Mon Sep 17 00:00:00 2001 From: Xie Zhihao Date: Fri, 25 Feb 2022 14:24:33 +0800 Subject: [PATCH 1/7] matching: UDP support for network input types Signed-off-by: Xie Zhihao --- envoy/network/filter.h | 20 ++++- source/common/network/matching/data_impl.h | 22 +++++ source/common/network/matching/inputs.cc | 24 +++--- source/common/network/matching/inputs.h | 67 ++++++++------ test/common/network/matching/inputs_test.cc | 96 +++++++++++++++++++++ 5 files changed, 190 insertions(+), 39 deletions(-) diff --git a/envoy/network/filter.h b/envoy/network/filter.h index a41a76cad45ab..c2782f2993d6c 100644 --- a/envoy/network/filter.h +++ b/envoy/network/filter.h @@ -520,16 +520,30 @@ class FilterChainFactory { }; /** - * Network filter matching context data for unified matchers. + * Filter matching context data for unified matchers. */ -class MatchingData { +class MatchingDataBase { public: static absl::string_view name() { return "network"; } - virtual ~MatchingData() = default; + virtual ~MatchingDataBase() = default; + + virtual const Address::InstanceConstSharedPtr& localAddress() const PURE; + virtual const Address::InstanceConstSharedPtr& remoteAddress() const PURE; +}; +/** + * Network filter matching context data for unified matchers. + */ +class MatchingData : public MatchingDataBase { +public: virtual const ConnectionSocket& socket() const PURE; }; +/** + * UDP listener filter matching context data for unified matchers. + */ +class UdpMatchingData : public MatchingDataBase {}; + } // namespace Network } // namespace Envoy diff --git a/source/common/network/matching/data_impl.h b/source/common/network/matching/data_impl.h index c8fd65b29f262..ff506dda908f6 100644 --- a/source/common/network/matching/data_impl.h +++ b/source/common/network/matching/data_impl.h @@ -13,12 +13,34 @@ namespace Matching { class MatchingDataImpl : public MatchingData { public: explicit MatchingDataImpl(const ConnectionSocket& socket) : socket_(socket) {} + const Address::InstanceConstSharedPtr& localAddress() const override { + return socket_.connectionInfoProvider().localAddress(); + } + const Address::InstanceConstSharedPtr& remoteAddress() const override { + return socket_.connectionInfoProvider().remoteAddress(); + } const ConnectionSocket& socket() const override { return socket_; } private: const ConnectionSocket& socket_; }; +/** + * Implementation of Network::UdpMatchingData, providing UDP data to the match tree. + */ +class UdpMatchingDataImpl : public UdpMatchingData { +public: + explicit UdpMatchingDataImpl(const Address::InstanceConstSharedPtr& local_address, + const Address::InstanceConstSharedPtr& remote_address) + : local_address_(local_address), remote_address_(remote_address) {} + const Address::InstanceConstSharedPtr& localAddress() const override { return local_address_; } + const Address::InstanceConstSharedPtr& remoteAddress() const override { return remote_address_; } + +private: + const Address::InstanceConstSharedPtr& local_address_; + const Address::InstanceConstSharedPtr& remote_address_; +}; + } // namespace Matching } // namespace Network } // namespace Envoy diff --git a/source/common/network/matching/inputs.cc b/source/common/network/matching/inputs.cc index deb64a6b40357..7550ca8235d29 100644 --- a/source/common/network/matching/inputs.cc +++ b/source/common/network/matching/inputs.cc @@ -10,8 +10,8 @@ namespace Envoy { namespace Network { namespace Matching { -Matcher::DataInputGetResult DestinationIPInput::get(const MatchingData& data) const { - const auto& address = data.socket().connectionInfoProvider().localAddress(); +Matcher::DataInputGetResult DestinationIPInput::get(const MatchingDataBase& data) const { + const auto& address = data.localAddress(); if (address->type() != Network::Address::Type::Ip) { return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; } @@ -19,8 +19,8 @@ Matcher::DataInputGetResult DestinationIPInput::get(const MatchingData& data) co address->ip()->addressAsString()}; } -Matcher::DataInputGetResult DestinationPortInput::get(const MatchingData& data) const { - const auto& address = data.socket().connectionInfoProvider().localAddress(); +Matcher::DataInputGetResult DestinationPortInput::get(const MatchingDataBase& data) const { + const auto& address = data.localAddress(); if (address->type() != Network::Address::Type::Ip) { return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; } @@ -28,8 +28,8 @@ Matcher::DataInputGetResult DestinationPortInput::get(const MatchingData& data) absl::StrCat(address->ip()->port())}; } -Matcher::DataInputGetResult SourceIPInput::get(const MatchingData& data) const { - const auto& address = data.socket().connectionInfoProvider().remoteAddress(); +Matcher::DataInputGetResult SourceIPInput::get(const MatchingDataBase& data) const { + const auto& address = data.remoteAddress(); if (address->type() != Network::Address::Type::Ip) { return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; } @@ -37,8 +37,8 @@ Matcher::DataInputGetResult SourceIPInput::get(const MatchingData& data) const { address->ip()->addressAsString()}; } -Matcher::DataInputGetResult SourcePortInput::get(const MatchingData& data) const { - const auto& address = data.socket().connectionInfoProvider().remoteAddress(); +Matcher::DataInputGetResult SourcePortInput::get(const MatchingDataBase& data) const { + const auto& address = data.remoteAddress(); if (address->type() != Network::Address::Type::Ip) { return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; } @@ -90,10 +90,10 @@ Matcher::DataInputGetResult ApplicationProtocolInput::get(const MatchingData& da return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; } -REGISTER_FACTORY(DestinationIPInputFactory, Matcher::DataInputFactory); -REGISTER_FACTORY(DestinationPortInputFactory, Matcher::DataInputFactory); -REGISTER_FACTORY(SourceIPInputFactory, Matcher::DataInputFactory); -REGISTER_FACTORY(SourcePortInputFactory, Matcher::DataInputFactory); +REGISTER_FACTORY(DestinationIPInputFactory, Matcher::DataInputFactory); +REGISTER_FACTORY(DestinationPortInputFactory, Matcher::DataInputFactory); +REGISTER_FACTORY(SourceIPInputFactory, Matcher::DataInputFactory); +REGISTER_FACTORY(SourcePortInputFactory, Matcher::DataInputFactory); REGISTER_FACTORY(DirectSourceIPInputFactory, Matcher::DataInputFactory); REGISTER_FACTORY(SourceTypeInputFactory, Matcher::DataInputFactory); REGISTER_FACTORY(ServerNameInputFactory, Matcher::DataInputFactory); diff --git a/source/common/network/matching/inputs.h b/source/common/network/matching/inputs.h index 20bb872e36edf..89a24e4d76bc3 100644 --- a/source/common/network/matching/inputs.h +++ b/source/common/network/matching/inputs.h @@ -10,14 +10,14 @@ namespace Network { namespace Matching { template -class BaseFactory : public Matcher::DataInputFactory { +class BaseFactory : public Matcher::DataInputFactory { protected: explicit BaseFactory(const std::string& name) : name_(name) {} public: std::string name() const override { return name_; } - Matcher::DataInputFactoryCb + Matcher::DataInputFactoryCb createDataInputFactoryCb(const Protobuf::Message&, ProtobufMessage::ValidationVisitor&) override { return []() { return std::make_unique(); }; }; @@ -29,9 +29,9 @@ class BaseFactory : public Matcher::DataInputFactory { const std::string name_; }; -class DestinationIPInput : public Matcher::DataInput { +class DestinationIPInput : public Matcher::DataInput { public: - Matcher::DataInputGetResult get(const MatchingData& data) const override; + Matcher::DataInputGetResult get(const MatchingDataBase& data) const override; }; class DestinationIPInputFactory @@ -42,9 +42,9 @@ class DestinationIPInputFactory DestinationIPInputFactory() : BaseFactory("destination-ip") {} }; -class DestinationPortInput : public Matcher::DataInput { +class DestinationPortInput : public Matcher::DataInput { public: - Matcher::DataInputGetResult get(const MatchingData& data) const override; + Matcher::DataInputGetResult get(const MatchingDataBase& data) const override; }; class DestinationPortInputFactory @@ -55,9 +55,9 @@ class DestinationPortInputFactory DestinationPortInputFactory() : BaseFactory("destination-port") {} }; -class SourceIPInput : public Matcher::DataInput { +class SourceIPInput : public Matcher::DataInput { public: - Matcher::DataInputGetResult get(const MatchingData& data) const override; + Matcher::DataInputGetResult get(const MatchingDataBase& data) const override; }; class SourceIPInputFactory @@ -67,9 +67,9 @@ class SourceIPInputFactory SourceIPInputFactory() : BaseFactory("source-ip") {} }; -class SourcePortInput : public Matcher::DataInput { +class SourcePortInput : public Matcher::DataInput { public: - Matcher::DataInputGetResult get(const MatchingData& data) const override; + Matcher::DataInputGetResult get(const MatchingDataBase& data) const override; }; class SourcePortInputFactory @@ -79,17 +79,36 @@ class SourcePortInputFactory SourcePortInputFactory() : BaseFactory("source-port") {} }; +template +class Factory : public Matcher::DataInputFactory { +protected: + explicit Factory(const std::string& name) : name_(name) {} + +public: + std::string name() const override { return name_; } + + Matcher::DataInputFactoryCb + createDataInputFactoryCb(const Protobuf::Message&, ProtobufMessage::ValidationVisitor&) override { + return []() { return std::make_unique(); }; + }; + ProtobufTypes::MessagePtr createEmptyConfigProto() override { + return std::make_unique(); + } + +private: + const std::string name_; +}; + class DirectSourceIPInput : public Matcher::DataInput { public: Matcher::DataInputGetResult get(const MatchingData& data) const override; }; class DirectSourceIPInputFactory - : public BaseFactory< - DirectSourceIPInput, - envoy::extensions::matching::common_inputs::network::v3::DirectSourceIPInput> { + : public Factory { public: - DirectSourceIPInputFactory() : BaseFactory("direct-source-ip") {} + DirectSourceIPInputFactory() : Factory("direct-source-ip") {} }; class SourceTypeInput : public Matcher::DataInput { @@ -98,10 +117,10 @@ class SourceTypeInput : public Matcher::DataInput { }; class SourceTypeInputFactory - : public BaseFactory { + : public Factory { public: - SourceTypeInputFactory() : BaseFactory("source-type") {} + SourceTypeInputFactory() : Factory("source-type") {} }; class ServerNameInput : public Matcher::DataInput { @@ -110,10 +129,10 @@ class ServerNameInput : public Matcher::DataInput { }; class ServerNameInputFactory - : public BaseFactory { + : public Factory { public: - ServerNameInputFactory() : BaseFactory("server-name") {} + ServerNameInputFactory() : Factory("server-name") {} }; class TransportProtocolInput : public Matcher::DataInput { @@ -122,11 +141,11 @@ class TransportProtocolInput : public Matcher::DataInput { }; class TransportProtocolInputFactory - : public BaseFactory< + : public Factory< TransportProtocolInput, envoy::extensions::matching::common_inputs::network::v3::TransportProtocolInput> { public: - TransportProtocolInputFactory() : BaseFactory("transport-protocol") {} + TransportProtocolInputFactory() : Factory("transport-protocol") {} }; class ApplicationProtocolInput : public Matcher::DataInput { @@ -135,11 +154,11 @@ class ApplicationProtocolInput : public Matcher::DataInput { }; class ApplicationProtocolInputFactory - : public BaseFactory< + : public Factory< ApplicationProtocolInput, envoy::extensions::matching::common_inputs::network::v3::ApplicationProtocolInput> { public: - ApplicationProtocolInputFactory() : BaseFactory("application-protocol") {} + ApplicationProtocolInputFactory() : Factory("application-protocol") {} }; } // namespace Matching diff --git a/test/common/network/matching/inputs_test.cc b/test/common/network/matching/inputs_test.cc index 45ab24cfdbfee..84200e6784511 100644 --- a/test/common/network/matching/inputs_test.cc +++ b/test/common/network/matching/inputs_test.cc @@ -233,6 +233,102 @@ TEST(MatchingData, ApplicationProtocolInput) { } } +TEST(UdpMatchingData, DestinationIPInput) { + DestinationIPInput input; + Address::InstanceConstSharedPtr ip = + std::make_shared("127.0.0.1", 8080); + Address::InstanceConstSharedPtr pipe = + std::make_shared("/pipe/path"); + + { + UdpMatchingDataImpl data(ip, ip); + const auto result = input.get(data); + EXPECT_EQ(result.data_availability_, + Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); + EXPECT_EQ(result.data_, "127.0.0.1"); + } + + { + UdpMatchingDataImpl data(pipe, ip); + const auto result = input.get(data); + EXPECT_EQ(result.data_availability_, + Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); + EXPECT_EQ(result.data_, absl::nullopt); + } +} + +TEST(UdpMatchingData, DestinationPortInput) { + DestinationPortInput input; + Address::InstanceConstSharedPtr ip = + std::make_shared("127.0.0.1", 8080); + Address::InstanceConstSharedPtr pipe = + std::make_shared("/pipe/path"); + + { + UdpMatchingDataImpl data(ip, ip); + const auto result = input.get(data); + EXPECT_EQ(result.data_availability_, + Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); + EXPECT_EQ(result.data_, "8080"); + } + + { + UdpMatchingDataImpl data(pipe, ip); + const auto result = input.get(data); + EXPECT_EQ(result.data_availability_, + Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); + EXPECT_EQ(result.data_, absl::nullopt); + } +} + +TEST(UdpMatchingData, SourceIPInput) { + SourceIPInput input; + Address::InstanceConstSharedPtr ip = + std::make_shared("127.0.0.1", 8080); + Address::InstanceConstSharedPtr pipe = + std::make_shared("/pipe/path"); + + { + UdpMatchingDataImpl data(ip, ip); + const auto result = input.get(data); + EXPECT_EQ(result.data_availability_, + Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); + EXPECT_EQ(result.data_, "127.0.0.1"); + } + + { + UdpMatchingDataImpl data(ip, pipe); + const auto result = input.get(data); + EXPECT_EQ(result.data_availability_, + Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); + EXPECT_EQ(result.data_, absl::nullopt); + } +} + +TEST(UdpMatchingData, SourcePortInput) { + SourcePortInput input; + Address::InstanceConstSharedPtr ip = + std::make_shared("127.0.0.1", 8080); + Address::InstanceConstSharedPtr pipe = + std::make_shared("/pipe/path"); + + { + UdpMatchingDataImpl data(ip, ip); + const auto result = input.get(data); + EXPECT_EQ(result.data_availability_, + Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); + EXPECT_EQ(result.data_, "8080"); + } + + { + UdpMatchingDataImpl data(ip, pipe); + const auto result = input.get(data); + EXPECT_EQ(result.data_availability_, + Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); + EXPECT_EQ(result.data_, absl::nullopt); + } +} + } // namespace Matching } // namespace Network } // namespace Envoy From d0865a831979ee12d86bb9ced6a347738bb76161 Mon Sep 17 00:00:00 2001 From: Xie Zhihao Date: Mon, 28 Feb 2022 09:48:15 +0800 Subject: [PATCH 2/7] Revert "matching: UDP support for network input types" This reverts commit df7971f94524ff15d1719892855e79a1d8331166. Signed-off-by: Xie Zhihao --- envoy/network/filter.h | 20 +---- source/common/network/matching/data_impl.h | 22 ----- source/common/network/matching/inputs.cc | 24 +++--- source/common/network/matching/inputs.h | 67 ++++++-------- test/common/network/matching/inputs_test.cc | 96 --------------------- 5 files changed, 39 insertions(+), 190 deletions(-) diff --git a/envoy/network/filter.h b/envoy/network/filter.h index c2782f2993d6c..a41a76cad45ab 100644 --- a/envoy/network/filter.h +++ b/envoy/network/filter.h @@ -520,30 +520,16 @@ class FilterChainFactory { }; /** - * Filter matching context data for unified matchers. + * Network filter matching context data for unified matchers. */ -class MatchingDataBase { +class MatchingData { public: static absl::string_view name() { return "network"; } - virtual ~MatchingDataBase() = default; - - virtual const Address::InstanceConstSharedPtr& localAddress() const PURE; - virtual const Address::InstanceConstSharedPtr& remoteAddress() const PURE; -}; + virtual ~MatchingData() = default; -/** - * Network filter matching context data for unified matchers. - */ -class MatchingData : public MatchingDataBase { -public: virtual const ConnectionSocket& socket() const PURE; }; -/** - * UDP listener filter matching context data for unified matchers. - */ -class UdpMatchingData : public MatchingDataBase {}; - } // namespace Network } // namespace Envoy diff --git a/source/common/network/matching/data_impl.h b/source/common/network/matching/data_impl.h index ff506dda908f6..c8fd65b29f262 100644 --- a/source/common/network/matching/data_impl.h +++ b/source/common/network/matching/data_impl.h @@ -13,34 +13,12 @@ namespace Matching { class MatchingDataImpl : public MatchingData { public: explicit MatchingDataImpl(const ConnectionSocket& socket) : socket_(socket) {} - const Address::InstanceConstSharedPtr& localAddress() const override { - return socket_.connectionInfoProvider().localAddress(); - } - const Address::InstanceConstSharedPtr& remoteAddress() const override { - return socket_.connectionInfoProvider().remoteAddress(); - } const ConnectionSocket& socket() const override { return socket_; } private: const ConnectionSocket& socket_; }; -/** - * Implementation of Network::UdpMatchingData, providing UDP data to the match tree. - */ -class UdpMatchingDataImpl : public UdpMatchingData { -public: - explicit UdpMatchingDataImpl(const Address::InstanceConstSharedPtr& local_address, - const Address::InstanceConstSharedPtr& remote_address) - : local_address_(local_address), remote_address_(remote_address) {} - const Address::InstanceConstSharedPtr& localAddress() const override { return local_address_; } - const Address::InstanceConstSharedPtr& remoteAddress() const override { return remote_address_; } - -private: - const Address::InstanceConstSharedPtr& local_address_; - const Address::InstanceConstSharedPtr& remote_address_; -}; - } // namespace Matching } // namespace Network } // namespace Envoy diff --git a/source/common/network/matching/inputs.cc b/source/common/network/matching/inputs.cc index 7550ca8235d29..deb64a6b40357 100644 --- a/source/common/network/matching/inputs.cc +++ b/source/common/network/matching/inputs.cc @@ -10,8 +10,8 @@ namespace Envoy { namespace Network { namespace Matching { -Matcher::DataInputGetResult DestinationIPInput::get(const MatchingDataBase& data) const { - const auto& address = data.localAddress(); +Matcher::DataInputGetResult DestinationIPInput::get(const MatchingData& data) const { + const auto& address = data.socket().connectionInfoProvider().localAddress(); if (address->type() != Network::Address::Type::Ip) { return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; } @@ -19,8 +19,8 @@ Matcher::DataInputGetResult DestinationIPInput::get(const MatchingDataBase& data address->ip()->addressAsString()}; } -Matcher::DataInputGetResult DestinationPortInput::get(const MatchingDataBase& data) const { - const auto& address = data.localAddress(); +Matcher::DataInputGetResult DestinationPortInput::get(const MatchingData& data) const { + const auto& address = data.socket().connectionInfoProvider().localAddress(); if (address->type() != Network::Address::Type::Ip) { return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; } @@ -28,8 +28,8 @@ Matcher::DataInputGetResult DestinationPortInput::get(const MatchingDataBase& da absl::StrCat(address->ip()->port())}; } -Matcher::DataInputGetResult SourceIPInput::get(const MatchingDataBase& data) const { - const auto& address = data.remoteAddress(); +Matcher::DataInputGetResult SourceIPInput::get(const MatchingData& data) const { + const auto& address = data.socket().connectionInfoProvider().remoteAddress(); if (address->type() != Network::Address::Type::Ip) { return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; } @@ -37,8 +37,8 @@ Matcher::DataInputGetResult SourceIPInput::get(const MatchingDataBase& data) con address->ip()->addressAsString()}; } -Matcher::DataInputGetResult SourcePortInput::get(const MatchingDataBase& data) const { - const auto& address = data.remoteAddress(); +Matcher::DataInputGetResult SourcePortInput::get(const MatchingData& data) const { + const auto& address = data.socket().connectionInfoProvider().remoteAddress(); if (address->type() != Network::Address::Type::Ip) { return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; } @@ -90,10 +90,10 @@ Matcher::DataInputGetResult ApplicationProtocolInput::get(const MatchingData& da return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; } -REGISTER_FACTORY(DestinationIPInputFactory, Matcher::DataInputFactory); -REGISTER_FACTORY(DestinationPortInputFactory, Matcher::DataInputFactory); -REGISTER_FACTORY(SourceIPInputFactory, Matcher::DataInputFactory); -REGISTER_FACTORY(SourcePortInputFactory, Matcher::DataInputFactory); +REGISTER_FACTORY(DestinationIPInputFactory, Matcher::DataInputFactory); +REGISTER_FACTORY(DestinationPortInputFactory, Matcher::DataInputFactory); +REGISTER_FACTORY(SourceIPInputFactory, Matcher::DataInputFactory); +REGISTER_FACTORY(SourcePortInputFactory, Matcher::DataInputFactory); REGISTER_FACTORY(DirectSourceIPInputFactory, Matcher::DataInputFactory); REGISTER_FACTORY(SourceTypeInputFactory, Matcher::DataInputFactory); REGISTER_FACTORY(ServerNameInputFactory, Matcher::DataInputFactory); diff --git a/source/common/network/matching/inputs.h b/source/common/network/matching/inputs.h index 89a24e4d76bc3..20bb872e36edf 100644 --- a/source/common/network/matching/inputs.h +++ b/source/common/network/matching/inputs.h @@ -10,14 +10,14 @@ namespace Network { namespace Matching { template -class BaseFactory : public Matcher::DataInputFactory { +class BaseFactory : public Matcher::DataInputFactory { protected: explicit BaseFactory(const std::string& name) : name_(name) {} public: std::string name() const override { return name_; } - Matcher::DataInputFactoryCb + Matcher::DataInputFactoryCb createDataInputFactoryCb(const Protobuf::Message&, ProtobufMessage::ValidationVisitor&) override { return []() { return std::make_unique(); }; }; @@ -29,9 +29,9 @@ class BaseFactory : public Matcher::DataInputFactory { const std::string name_; }; -class DestinationIPInput : public Matcher::DataInput { +class DestinationIPInput : public Matcher::DataInput { public: - Matcher::DataInputGetResult get(const MatchingDataBase& data) const override; + Matcher::DataInputGetResult get(const MatchingData& data) const override; }; class DestinationIPInputFactory @@ -42,9 +42,9 @@ class DestinationIPInputFactory DestinationIPInputFactory() : BaseFactory("destination-ip") {} }; -class DestinationPortInput : public Matcher::DataInput { +class DestinationPortInput : public Matcher::DataInput { public: - Matcher::DataInputGetResult get(const MatchingDataBase& data) const override; + Matcher::DataInputGetResult get(const MatchingData& data) const override; }; class DestinationPortInputFactory @@ -55,9 +55,9 @@ class DestinationPortInputFactory DestinationPortInputFactory() : BaseFactory("destination-port") {} }; -class SourceIPInput : public Matcher::DataInput { +class SourceIPInput : public Matcher::DataInput { public: - Matcher::DataInputGetResult get(const MatchingDataBase& data) const override; + Matcher::DataInputGetResult get(const MatchingData& data) const override; }; class SourceIPInputFactory @@ -67,9 +67,9 @@ class SourceIPInputFactory SourceIPInputFactory() : BaseFactory("source-ip") {} }; -class SourcePortInput : public Matcher::DataInput { +class SourcePortInput : public Matcher::DataInput { public: - Matcher::DataInputGetResult get(const MatchingDataBase& data) const override; + Matcher::DataInputGetResult get(const MatchingData& data) const override; }; class SourcePortInputFactory @@ -79,36 +79,17 @@ class SourcePortInputFactory SourcePortInputFactory() : BaseFactory("source-port") {} }; -template -class Factory : public Matcher::DataInputFactory { -protected: - explicit Factory(const std::string& name) : name_(name) {} - -public: - std::string name() const override { return name_; } - - Matcher::DataInputFactoryCb - createDataInputFactoryCb(const Protobuf::Message&, ProtobufMessage::ValidationVisitor&) override { - return []() { return std::make_unique(); }; - }; - ProtobufTypes::MessagePtr createEmptyConfigProto() override { - return std::make_unique(); - } - -private: - const std::string name_; -}; - class DirectSourceIPInput : public Matcher::DataInput { public: Matcher::DataInputGetResult get(const MatchingData& data) const override; }; class DirectSourceIPInputFactory - : public Factory { + : public BaseFactory< + DirectSourceIPInput, + envoy::extensions::matching::common_inputs::network::v3::DirectSourceIPInput> { public: - DirectSourceIPInputFactory() : Factory("direct-source-ip") {} + DirectSourceIPInputFactory() : BaseFactory("direct-source-ip") {} }; class SourceTypeInput : public Matcher::DataInput { @@ -117,10 +98,10 @@ class SourceTypeInput : public Matcher::DataInput { }; class SourceTypeInputFactory - : public Factory { + : public BaseFactory { public: - SourceTypeInputFactory() : Factory("source-type") {} + SourceTypeInputFactory() : BaseFactory("source-type") {} }; class ServerNameInput : public Matcher::DataInput { @@ -129,10 +110,10 @@ class ServerNameInput : public Matcher::DataInput { }; class ServerNameInputFactory - : public Factory { + : public BaseFactory { public: - ServerNameInputFactory() : Factory("server-name") {} + ServerNameInputFactory() : BaseFactory("server-name") {} }; class TransportProtocolInput : public Matcher::DataInput { @@ -141,11 +122,11 @@ class TransportProtocolInput : public Matcher::DataInput { }; class TransportProtocolInputFactory - : public Factory< + : public BaseFactory< TransportProtocolInput, envoy::extensions::matching::common_inputs::network::v3::TransportProtocolInput> { public: - TransportProtocolInputFactory() : Factory("transport-protocol") {} + TransportProtocolInputFactory() : BaseFactory("transport-protocol") {} }; class ApplicationProtocolInput : public Matcher::DataInput { @@ -154,11 +135,11 @@ class ApplicationProtocolInput : public Matcher::DataInput { }; class ApplicationProtocolInputFactory - : public Factory< + : public BaseFactory< ApplicationProtocolInput, envoy::extensions::matching::common_inputs::network::v3::ApplicationProtocolInput> { public: - ApplicationProtocolInputFactory() : Factory("application-protocol") {} + ApplicationProtocolInputFactory() : BaseFactory("application-protocol") {} }; } // namespace Matching diff --git a/test/common/network/matching/inputs_test.cc b/test/common/network/matching/inputs_test.cc index 84200e6784511..45ab24cfdbfee 100644 --- a/test/common/network/matching/inputs_test.cc +++ b/test/common/network/matching/inputs_test.cc @@ -233,102 +233,6 @@ TEST(MatchingData, ApplicationProtocolInput) { } } -TEST(UdpMatchingData, DestinationIPInput) { - DestinationIPInput input; - Address::InstanceConstSharedPtr ip = - std::make_shared("127.0.0.1", 8080); - Address::InstanceConstSharedPtr pipe = - std::make_shared("/pipe/path"); - - { - UdpMatchingDataImpl data(ip, ip); - const auto result = input.get(data); - EXPECT_EQ(result.data_availability_, - Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); - EXPECT_EQ(result.data_, "127.0.0.1"); - } - - { - UdpMatchingDataImpl data(pipe, ip); - const auto result = input.get(data); - EXPECT_EQ(result.data_availability_, - Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); - EXPECT_EQ(result.data_, absl::nullopt); - } -} - -TEST(UdpMatchingData, DestinationPortInput) { - DestinationPortInput input; - Address::InstanceConstSharedPtr ip = - std::make_shared("127.0.0.1", 8080); - Address::InstanceConstSharedPtr pipe = - std::make_shared("/pipe/path"); - - { - UdpMatchingDataImpl data(ip, ip); - const auto result = input.get(data); - EXPECT_EQ(result.data_availability_, - Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); - EXPECT_EQ(result.data_, "8080"); - } - - { - UdpMatchingDataImpl data(pipe, ip); - const auto result = input.get(data); - EXPECT_EQ(result.data_availability_, - Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); - EXPECT_EQ(result.data_, absl::nullopt); - } -} - -TEST(UdpMatchingData, SourceIPInput) { - SourceIPInput input; - Address::InstanceConstSharedPtr ip = - std::make_shared("127.0.0.1", 8080); - Address::InstanceConstSharedPtr pipe = - std::make_shared("/pipe/path"); - - { - UdpMatchingDataImpl data(ip, ip); - const auto result = input.get(data); - EXPECT_EQ(result.data_availability_, - Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); - EXPECT_EQ(result.data_, "127.0.0.1"); - } - - { - UdpMatchingDataImpl data(ip, pipe); - const auto result = input.get(data); - EXPECT_EQ(result.data_availability_, - Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); - EXPECT_EQ(result.data_, absl::nullopt); - } -} - -TEST(UdpMatchingData, SourcePortInput) { - SourcePortInput input; - Address::InstanceConstSharedPtr ip = - std::make_shared("127.0.0.1", 8080); - Address::InstanceConstSharedPtr pipe = - std::make_shared("/pipe/path"); - - { - UdpMatchingDataImpl data(ip, ip); - const auto result = input.get(data); - EXPECT_EQ(result.data_availability_, - Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); - EXPECT_EQ(result.data_, "8080"); - } - - { - UdpMatchingDataImpl data(ip, pipe); - const auto result = input.get(data); - EXPECT_EQ(result.data_availability_, - Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); - EXPECT_EQ(result.data_, absl::nullopt); - } -} - } // namespace Matching } // namespace Network } // namespace Envoy From d322434a660fba7267019dd39e2e74ab416161b9 Mon Sep 17 00:00:00 2001 From: Xie Zhihao Date: Mon, 28 Feb 2022 10:34:58 +0800 Subject: [PATCH 3/7] matching: UDP support for network input types Signed-off-by: Xie Zhihao --- envoy/network/filter.h | 13 +++ source/common/network/matching/data_impl.h | 16 ++++ source/common/network/matching/inputs.cc | 40 ++++++++ source/common/network/matching/inputs.h | 72 ++++++++++++++ .../extensions/common/matcher/trie_matcher.cc | 2 + .../extensions/common/matcher/trie_matcher.h | 1 + test/common/network/matching/inputs_test.cc | 96 +++++++++++++++++++ .../common/matcher/trie_matcher_test.cc | 45 +++++++++ 8 files changed, 285 insertions(+) diff --git a/envoy/network/filter.h b/envoy/network/filter.h index a41a76cad45ab..bb3ba9b458ab6 100644 --- a/envoy/network/filter.h +++ b/envoy/network/filter.h @@ -531,5 +531,18 @@ class MatchingData { virtual const ConnectionSocket& socket() const PURE; }; +/** + * UDP listener filter matching context data for unified matchers. + */ +class UdpMatchingData { +public: + static absl::string_view name() { return "network"; } + + virtual ~UdpMatchingData() = default; + + virtual const Address::InstanceConstSharedPtr& localAddress() const PURE; + virtual const Address::InstanceConstSharedPtr& remoteAddress() const PURE; +}; + } // namespace Network } // namespace Envoy diff --git a/source/common/network/matching/data_impl.h b/source/common/network/matching/data_impl.h index c8fd65b29f262..94a268fb0b862 100644 --- a/source/common/network/matching/data_impl.h +++ b/source/common/network/matching/data_impl.h @@ -19,6 +19,22 @@ class MatchingDataImpl : public MatchingData { const ConnectionSocket& socket_; }; +/** + * Implementation of Network::UdpMatchingData, providing UDP data to the match tree. + */ +class UdpMatchingDataImpl : public UdpMatchingData { +public: + explicit UdpMatchingDataImpl(const Address::InstanceConstSharedPtr& local_address, + const Address::InstanceConstSharedPtr& remote_address) + : local_address_(local_address), remote_address_(remote_address) {} + const Address::InstanceConstSharedPtr& localAddress() const override { return local_address_; } + const Address::InstanceConstSharedPtr& remoteAddress() const override { return remote_address_; } + +private: + const Address::InstanceConstSharedPtr& local_address_; + const Address::InstanceConstSharedPtr& remote_address_; +}; + } // namespace Matching } // namespace Network } // namespace Envoy diff --git a/source/common/network/matching/inputs.cc b/source/common/network/matching/inputs.cc index deb64a6b40357..33e057004011f 100644 --- a/source/common/network/matching/inputs.cc +++ b/source/common/network/matching/inputs.cc @@ -90,6 +90,42 @@ Matcher::DataInputGetResult ApplicationProtocolInput::get(const MatchingData& da return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; } +Matcher::DataInputGetResult UdpDestinationIPInput::get(const UdpMatchingData& data) const { + const auto& address = data.localAddress(); + if (address->type() != Network::Address::Type::Ip) { + return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; + } + return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, + address->ip()->addressAsString()}; +} + +Matcher::DataInputGetResult UdpDestinationPortInput::get(const UdpMatchingData& data) const { + const auto& address = data.localAddress(); + if (address->type() != Network::Address::Type::Ip) { + return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; + } + return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, + absl::StrCat(address->ip()->port())}; +} + +Matcher::DataInputGetResult UdpSourceIPInput::get(const UdpMatchingData& data) const { + const auto& address = data.remoteAddress(); + if (address->type() != Network::Address::Type::Ip) { + return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; + } + return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, + address->ip()->addressAsString()}; +} + +Matcher::DataInputGetResult UdpSourcePortInput::get(const UdpMatchingData& data) const { + const auto& address = data.remoteAddress(); + if (address->type() != Network::Address::Type::Ip) { + return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; + } + return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, + absl::StrCat(address->ip()->port())}; +} + REGISTER_FACTORY(DestinationIPInputFactory, Matcher::DataInputFactory); REGISTER_FACTORY(DestinationPortInputFactory, Matcher::DataInputFactory); REGISTER_FACTORY(SourceIPInputFactory, Matcher::DataInputFactory); @@ -99,6 +135,10 @@ REGISTER_FACTORY(SourceTypeInputFactory, Matcher::DataInputFactory REGISTER_FACTORY(ServerNameInputFactory, Matcher::DataInputFactory); REGISTER_FACTORY(TransportProtocolInputFactory, Matcher::DataInputFactory); REGISTER_FACTORY(ApplicationProtocolInputFactory, Matcher::DataInputFactory); +REGISTER_FACTORY(UdpDestinationIPInputFactory, Matcher::DataInputFactory); +REGISTER_FACTORY(UdpDestinationPortInputFactory, Matcher::DataInputFactory); +REGISTER_FACTORY(UdpSourceIPInputFactory, Matcher::DataInputFactory); +REGISTER_FACTORY(UdpSourcePortInputFactory, Matcher::DataInputFactory); } // namespace Matching } // namespace Network diff --git a/source/common/network/matching/inputs.h b/source/common/network/matching/inputs.h index 20bb872e36edf..a11fff26c49f7 100644 --- a/source/common/network/matching/inputs.h +++ b/source/common/network/matching/inputs.h @@ -142,6 +142,78 @@ class ApplicationProtocolInputFactory ApplicationProtocolInputFactory() : BaseFactory("application-protocol") {} }; +template +class UdpBaseFactory : public Matcher::DataInputFactory { +protected: + explicit UdpBaseFactory(const std::string& name) : name_(name) {} + +public: + std::string name() const override { return name_; } + + Matcher::DataInputFactoryCb + createDataInputFactoryCb(const Protobuf::Message&, ProtobufMessage::ValidationVisitor&) override { + return []() { return std::make_unique(); }; + }; + ProtobufTypes::MessagePtr createEmptyConfigProto() override { + return std::make_unique(); + } + +private: + const std::string name_; +}; + +class UdpDestinationIPInput : public Matcher::DataInput { +public: + Matcher::DataInputGetResult get(const UdpMatchingData& data) const override; +}; + +class UdpDestinationIPInputFactory + : public UdpBaseFactory< + UdpDestinationIPInput, + envoy::extensions::matching::common_inputs::network::v3::DestinationIPInput> { +public: + UdpDestinationIPInputFactory() : UdpBaseFactory("destination-ip") {} +}; + +class UdpDestinationPortInput : public Matcher::DataInput { +public: + Matcher::DataInputGetResult get(const UdpMatchingData& data) const override; +}; + +class UdpDestinationPortInputFactory + : public UdpBaseFactory< + UdpDestinationPortInput, + envoy::extensions::matching::common_inputs::network::v3::DestinationPortInput> { +public: + UdpDestinationPortInputFactory() : UdpBaseFactory("destination-port") {} +}; + +class UdpSourceIPInput : public Matcher::DataInput { +public: + Matcher::DataInputGetResult get(const UdpMatchingData& data) const override; +}; + +class UdpSourceIPInputFactory + : public UdpBaseFactory< + UdpSourceIPInput, + envoy::extensions::matching::common_inputs::network::v3::SourceIPInput> { +public: + UdpSourceIPInputFactory() : UdpBaseFactory("source-ip") {} +}; + +class UdpSourcePortInput : public Matcher::DataInput { +public: + Matcher::DataInputGetResult get(const UdpMatchingData& data) const override; +}; + +class UdpSourcePortInputFactory + : public UdpBaseFactory< + UdpSourcePortInput, + envoy::extensions::matching::common_inputs::network::v3::SourcePortInput> { +public: + UdpSourcePortInputFactory() : UdpBaseFactory("source-port") {} +}; + } // namespace Matching } // namespace Network } // namespace Envoy diff --git a/source/extensions/common/matcher/trie_matcher.cc b/source/extensions/common/matcher/trie_matcher.cc index 5f41f564f2d9d..99cfcabd30566 100644 --- a/source/extensions/common/matcher/trie_matcher.cc +++ b/source/extensions/common/matcher/trie_matcher.cc @@ -9,6 +9,8 @@ namespace Matcher { REGISTER_FACTORY(NetworkTrieMatcherFactory, ::Envoy::Matcher::CustomMatcherFactory); +REGISTER_FACTORY(UdpNetworkTrieMatcherFactory, + ::Envoy::Matcher::CustomMatcherFactory); } // namespace Matcher } // namespace Common diff --git a/source/extensions/common/matcher/trie_matcher.h b/source/extensions/common/matcher/trie_matcher.h index 6b4ea542bf8b5..5aa2d837effd2 100644 --- a/source/extensions/common/matcher/trie_matcher.h +++ b/source/extensions/common/matcher/trie_matcher.h @@ -150,6 +150,7 @@ class TrieMatcherFactoryBase : public ::Envoy::Matcher::CustomMatcherFactory {}; +class UdpNetworkTrieMatcherFactory : public TrieMatcherFactoryBase {}; } // namespace Matcher } // namespace Common diff --git a/test/common/network/matching/inputs_test.cc b/test/common/network/matching/inputs_test.cc index 45ab24cfdbfee..cb2eac4f148cf 100644 --- a/test/common/network/matching/inputs_test.cc +++ b/test/common/network/matching/inputs_test.cc @@ -233,6 +233,102 @@ TEST(MatchingData, ApplicationProtocolInput) { } } +TEST(UdpMatchingData, UdpDestinationIPInput) { + UdpDestinationIPInput input; + const Address::InstanceConstSharedPtr ip = + std::make_shared("127.0.0.1", 8080); + const Address::InstanceConstSharedPtr pipe = + std::make_shared("/pipe/path"); + + { + UdpMatchingDataImpl data(ip, ip); + const auto result = input.get(data); + EXPECT_EQ(result.data_availability_, + Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); + EXPECT_EQ(result.data_, "127.0.0.1"); + } + + { + UdpMatchingDataImpl data(pipe, ip); + const auto result = input.get(data); + EXPECT_EQ(result.data_availability_, + Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); + EXPECT_EQ(result.data_, absl::nullopt); + } +} + +TEST(UdpMatchingData, UdpDestinationPortInput) { + UdpDestinationPortInput input; + const Address::InstanceConstSharedPtr ip = + std::make_shared("127.0.0.1", 8080); + const Address::InstanceConstSharedPtr pipe = + std::make_shared("/pipe/path"); + + { + UdpMatchingDataImpl data(ip, ip); + const auto result = input.get(data); + EXPECT_EQ(result.data_availability_, + Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); + EXPECT_EQ(result.data_, "8080"); + } + + { + UdpMatchingDataImpl data(pipe, ip); + const auto result = input.get(data); + EXPECT_EQ(result.data_availability_, + Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); + EXPECT_EQ(result.data_, absl::nullopt); + } +} + +TEST(UdpMatchingData, UdpSourceIPInput) { + UdpSourceIPInput input; + const Address::InstanceConstSharedPtr ip = + std::make_shared("127.0.0.1", 8080); + const Address::InstanceConstSharedPtr pipe = + std::make_shared("/pipe/path"); + + { + UdpMatchingDataImpl data(ip, ip); + const auto result = input.get(data); + EXPECT_EQ(result.data_availability_, + Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); + EXPECT_EQ(result.data_, "127.0.0.1"); + } + + { + UdpMatchingDataImpl data(ip, pipe); + const auto result = input.get(data); + EXPECT_EQ(result.data_availability_, + Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); + EXPECT_EQ(result.data_, absl::nullopt); + } +} + +TEST(UdpMatchingData, UdpSourcePortInput) { + UdpSourcePortInput input; + const Address::InstanceConstSharedPtr ip = + std::make_shared("127.0.0.1", 8080); + const Address::InstanceConstSharedPtr pipe = + std::make_shared("/pipe/path"); + + { + UdpMatchingDataImpl data(ip, ip); + const auto result = input.get(data); + EXPECT_EQ(result.data_availability_, + Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); + EXPECT_EQ(result.data_, "8080"); + } + + { + UdpMatchingDataImpl data(ip, pipe); + const auto result = input.get(data); + EXPECT_EQ(result.data_availability_, + Matcher::DataInputGetResult::DataAvailability::AllDataAvailable); + EXPECT_EQ(result.data_, absl::nullopt); + } +} + } // namespace Matching } // namespace Network } // namespace Envoy diff --git a/test/extensions/common/matcher/trie_matcher_test.cc b/test/extensions/common/matcher/trie_matcher_test.cc index ddf41211576fb..56f7b06864c0b 100644 --- a/test/extensions/common/matcher/trie_matcher_test.cc +++ b/test/extensions/common/matcher/trie_matcher_test.cc @@ -489,6 +489,51 @@ TEST(TrieMatcherIntegrationTest, NetworkMatchingData) { EXPECT_EQ(result.on_match_->action_cb_()->getTyped().string_, "foo"); } +TEST(TrieMatcherIntegrationTest, UdpNetworkMatchingData) { + const std::string yaml = R"EOF( +matcher_tree: + input: + name: input + 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.0.0.0 + prefix_len: 2 + on_match: + action: + name: test_action + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo + )EOF"; + xds::type::matcher::v3::Matcher matcher; + MessageUtil::loadFromYaml(yaml, matcher, ProtobufMessage::getStrictValidationVisitor()); + + StringActionFactory action_factory; + Registry::InjectFactory> inject_action(action_factory); + NiceMock factory_context; + MockMatchTreeValidationVisitor validation_visitor; + EXPECT_CALL(validation_visitor, performDataInputValidation(_, _)).Times(testing::AnyNumber()); + absl::string_view context = ""; + MatchTreeFactory matcher_factory( + context, factory_context, validation_visitor); + auto match_tree = matcher_factory.create(matcher); + + Network::MockConnectionSocket socket; + Network::Address::InstanceConstSharedPtr address = + std::make_shared("192.168.0.1", 8080); + Network::Matching::UdpMatchingDataImpl data(address, address); + + const auto result = match_tree()->match(data); + EXPECT_EQ(result.match_state_, MatchState::MatchComplete); + EXPECT_EQ(result.on_match_->action_cb_()->getTyped().string_, "foo"); +} + } // namespace } // namespace Matcher } // namespace Common From 557b729e362bb68fa07c403d1a48aa93efbf142d Mon Sep 17 00:00:00 2001 From: Xie Zhihao Date: Tue, 8 Mar 2022 11:16:56 +0800 Subject: [PATCH 4/7] matching: templatize network inputs and their factories Signed-off-by: Xie Zhihao --- source/common/network/matching/inputs.cc | 100 ++++++----- source/common/network/matching/inputs.h | 181 +++++++++----------- test/common/network/matching/inputs_test.cc | 16 +- 3 files changed, 141 insertions(+), 156 deletions(-) diff --git a/source/common/network/matching/inputs.cc b/source/common/network/matching/inputs.cc index 33e057004011f..6beb60a3c6bca 100644 --- a/source/common/network/matching/inputs.cc +++ b/source/common/network/matching/inputs.cc @@ -10,7 +10,8 @@ namespace Envoy { namespace Network { namespace Matching { -Matcher::DataInputGetResult DestinationIPInput::get(const MatchingData& data) const { +template <> +Matcher::DataInputGetResult DestinationIPInput::get(const MatchingData& data) const { const auto& address = data.socket().connectionInfoProvider().localAddress(); if (address->type() != Network::Address::Type::Ip) { return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; @@ -19,7 +20,20 @@ Matcher::DataInputGetResult DestinationIPInput::get(const MatchingData& data) co address->ip()->addressAsString()}; } -Matcher::DataInputGetResult DestinationPortInput::get(const MatchingData& data) const { +template <> +Matcher::DataInputGetResult +DestinationIPInput::get(const UdpMatchingData& data) const { + const auto& address = data.localAddress(); + if (address->type() != Network::Address::Type::Ip) { + return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; + } + return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, + address->ip()->addressAsString()}; +} + +template <> +Matcher::DataInputGetResult +DestinationPortInput::get(const MatchingData& data) const { const auto& address = data.socket().connectionInfoProvider().localAddress(); if (address->type() != Network::Address::Type::Ip) { return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; @@ -28,7 +42,19 @@ Matcher::DataInputGetResult DestinationPortInput::get(const MatchingData& data) absl::StrCat(address->ip()->port())}; } -Matcher::DataInputGetResult SourceIPInput::get(const MatchingData& data) const { +template <> +Matcher::DataInputGetResult +DestinationPortInput::get(const UdpMatchingData& data) const { + const auto& address = data.localAddress(); + if (address->type() != Network::Address::Type::Ip) { + return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; + } + return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, + absl::StrCat(address->ip()->port())}; +} + +template <> +Matcher::DataInputGetResult SourceIPInput::get(const MatchingData& data) const { const auto& address = data.socket().connectionInfoProvider().remoteAddress(); if (address->type() != Network::Address::Type::Ip) { return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; @@ -37,7 +63,18 @@ Matcher::DataInputGetResult SourceIPInput::get(const MatchingData& data) const { address->ip()->addressAsString()}; } -Matcher::DataInputGetResult SourcePortInput::get(const MatchingData& data) const { +template <> +Matcher::DataInputGetResult SourceIPInput::get(const UdpMatchingData& data) const { + const auto& address = data.remoteAddress(); + if (address->type() != Network::Address::Type::Ip) { + return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; + } + return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, + address->ip()->addressAsString()}; +} + +template <> +Matcher::DataInputGetResult SourcePortInput::get(const MatchingData& data) const { const auto& address = data.socket().connectionInfoProvider().remoteAddress(); if (address->type() != Network::Address::Type::Ip) { return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; @@ -46,6 +83,17 @@ Matcher::DataInputGetResult SourcePortInput::get(const MatchingData& data) const absl::StrCat(address->ip()->port())}; } +template <> +Matcher::DataInputGetResult +SourcePortInput::get(const UdpMatchingData& data) const { + const auto& address = data.remoteAddress(); + if (address->type() != Network::Address::Type::Ip) { + return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; + } + return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, + absl::StrCat(address->ip()->port())}; +} + Matcher::DataInputGetResult DirectSourceIPInput::get(const MatchingData& data) const { const auto& address = data.socket().connectionInfoProvider().directRemoteAddress(); if (address->type() != Network::Address::Type::Ip) { @@ -90,55 +138,19 @@ Matcher::DataInputGetResult ApplicationProtocolInput::get(const MatchingData& da return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; } -Matcher::DataInputGetResult UdpDestinationIPInput::get(const UdpMatchingData& data) const { - const auto& address = data.localAddress(); - if (address->type() != Network::Address::Type::Ip) { - return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; - } - return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, - address->ip()->addressAsString()}; -} - -Matcher::DataInputGetResult UdpDestinationPortInput::get(const UdpMatchingData& data) const { - const auto& address = data.localAddress(); - if (address->type() != Network::Address::Type::Ip) { - return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; - } - return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, - absl::StrCat(address->ip()->port())}; -} - -Matcher::DataInputGetResult UdpSourceIPInput::get(const UdpMatchingData& data) const { - const auto& address = data.remoteAddress(); - if (address->type() != Network::Address::Type::Ip) { - return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; - } - return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, - address->ip()->addressAsString()}; -} - -Matcher::DataInputGetResult UdpSourcePortInput::get(const UdpMatchingData& data) const { - const auto& address = data.remoteAddress(); - if (address->type() != Network::Address::Type::Ip) { - return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt}; - } - return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, - absl::StrCat(address->ip()->port())}; -} - REGISTER_FACTORY(DestinationIPInputFactory, Matcher::DataInputFactory); +REGISTER_FACTORY(UdpDestinationIPInputFactory, Matcher::DataInputFactory); REGISTER_FACTORY(DestinationPortInputFactory, Matcher::DataInputFactory); +REGISTER_FACTORY(UdpDestinationPortInputFactory, Matcher::DataInputFactory); REGISTER_FACTORY(SourceIPInputFactory, Matcher::DataInputFactory); +REGISTER_FACTORY(UdpSourceIPInputFactory, Matcher::DataInputFactory); REGISTER_FACTORY(SourcePortInputFactory, Matcher::DataInputFactory); +REGISTER_FACTORY(UdpSourcePortInputFactory, Matcher::DataInputFactory); REGISTER_FACTORY(DirectSourceIPInputFactory, Matcher::DataInputFactory); REGISTER_FACTORY(SourceTypeInputFactory, Matcher::DataInputFactory); REGISTER_FACTORY(ServerNameInputFactory, Matcher::DataInputFactory); REGISTER_FACTORY(TransportProtocolInputFactory, Matcher::DataInputFactory); REGISTER_FACTORY(ApplicationProtocolInputFactory, Matcher::DataInputFactory); -REGISTER_FACTORY(UdpDestinationIPInputFactory, Matcher::DataInputFactory); -REGISTER_FACTORY(UdpDestinationPortInputFactory, Matcher::DataInputFactory); -REGISTER_FACTORY(UdpSourceIPInputFactory, Matcher::DataInputFactory); -REGISTER_FACTORY(UdpSourcePortInputFactory, Matcher::DataInputFactory); } // namespace Matching } // namespace Network diff --git a/source/common/network/matching/inputs.h b/source/common/network/matching/inputs.h index a11fff26c49f7..42990aa4aa838 100644 --- a/source/common/network/matching/inputs.h +++ b/source/common/network/matching/inputs.h @@ -9,15 +9,15 @@ namespace Envoy { namespace Network { namespace Matching { -template -class BaseFactory : public Matcher::DataInputFactory { +template +class BaseFactory : public Matcher::DataInputFactory { protected: explicit BaseFactory(const std::string& name) : name_(name) {} public: std::string name() const override { return name_; } - Matcher::DataInputFactoryCb + Matcher::DataInputFactoryCb createDataInputFactoryCb(const Protobuf::Message&, ProtobufMessage::ValidationVisitor&) override { return []() { return std::make_unique(); }; }; @@ -29,56 +29,96 @@ class BaseFactory : public Matcher::DataInputFactory { const std::string name_; }; -class DestinationIPInput : public Matcher::DataInput { +template +class DestinationIPInput : public Matcher::DataInput { public: - Matcher::DataInputGetResult get(const MatchingData& data) const override; + Matcher::DataInputGetResult get(const MatchingDataType& data) const override; }; -class DestinationIPInputFactory +template +class DestinationIPInputBaseFactory : public BaseFactory< - DestinationIPInput, - envoy::extensions::matching::common_inputs::network::v3::DestinationIPInput> { + DestinationIPInput, + envoy::extensions::matching::common_inputs::network::v3::DestinationIPInput, + MatchingDataType> { public: - DestinationIPInputFactory() : BaseFactory("destination-ip") {} + DestinationIPInputBaseFactory() + : BaseFactory, + envoy::extensions::matching::common_inputs::network::v3::DestinationIPInput, + MatchingDataType>("destination-ip") {} }; -class DestinationPortInput : public Matcher::DataInput { +class DestinationIPInputFactory : public DestinationIPInputBaseFactory {}; + +class UdpDestinationIPInputFactory : public DestinationIPInputBaseFactory {}; + +template +class DestinationPortInput : public Matcher::DataInput { public: - Matcher::DataInputGetResult get(const MatchingData& data) const override; + Matcher::DataInputGetResult get(const MatchingDataType& data) const override; }; -class DestinationPortInputFactory +template +class DestinationPortInputBaseFactory : public BaseFactory< - DestinationPortInput, - envoy::extensions::matching::common_inputs::network::v3::DestinationPortInput> { + DestinationPortInput, + envoy::extensions::matching::common_inputs::network::v3::DestinationPortInput, + MatchingDataType> { public: - DestinationPortInputFactory() : BaseFactory("destination-port") {} + DestinationPortInputBaseFactory() + : BaseFactory, + envoy::extensions::matching::common_inputs::network::v3::DestinationPortInput, + MatchingDataType>("destination-port") {} }; -class SourceIPInput : public Matcher::DataInput { +class DestinationPortInputFactory : public DestinationPortInputBaseFactory {}; + +class UdpDestinationPortInputFactory : public DestinationPortInputBaseFactory {}; + +template +class SourceIPInput : public Matcher::DataInput { public: - Matcher::DataInputGetResult get(const MatchingData& data) const override; + Matcher::DataInputGetResult get(const MatchingDataType& data) const override; }; -class SourceIPInputFactory - : public BaseFactory { +template +class SourceIPInputBaseFactory + : public BaseFactory, + envoy::extensions::matching::common_inputs::network::v3::SourceIPInput, + MatchingDataType> { public: - SourceIPInputFactory() : BaseFactory("source-ip") {} + SourceIPInputBaseFactory() + : BaseFactory, + envoy::extensions::matching::common_inputs::network::v3::SourceIPInput, + MatchingDataType>("source-ip") {} }; -class SourcePortInput : public Matcher::DataInput { +class SourceIPInputFactory : public SourceIPInputBaseFactory {}; + +class UdpSourceIPInputFactory : public SourceIPInputBaseFactory {}; + +template +class SourcePortInput : public Matcher::DataInput { public: - Matcher::DataInputGetResult get(const MatchingData& data) const override; + Matcher::DataInputGetResult get(const MatchingDataType& data) const override; }; -class SourcePortInputFactory - : public BaseFactory { +template +class SourcePortInputBaseFactory + : public BaseFactory, + envoy::extensions::matching::common_inputs::network::v3::SourcePortInput, + MatchingDataType> { public: - SourcePortInputFactory() : BaseFactory("source-port") {} + SourcePortInputBaseFactory() + : BaseFactory, + envoy::extensions::matching::common_inputs::network::v3::SourcePortInput, + MatchingDataType>("source-port") {} }; +class SourcePortInputFactory : public SourcePortInputBaseFactory {}; + +class UdpSourcePortInputFactory : public SourcePortInputBaseFactory {}; + class DirectSourceIPInput : public Matcher::DataInput { public: Matcher::DataInputGetResult get(const MatchingData& data) const override; @@ -87,7 +127,8 @@ class DirectSourceIPInput : public Matcher::DataInput { class DirectSourceIPInputFactory : public BaseFactory< DirectSourceIPInput, - envoy::extensions::matching::common_inputs::network::v3::DirectSourceIPInput> { + envoy::extensions::matching::common_inputs::network::v3::DirectSourceIPInput, + MatchingData> { public: DirectSourceIPInputFactory() : BaseFactory("direct-source-ip") {} }; @@ -99,7 +140,8 @@ class SourceTypeInput : public Matcher::DataInput { class SourceTypeInputFactory : public BaseFactory { + envoy::extensions::matching::common_inputs::network::v3::SourceTypeInput, + MatchingData> { public: SourceTypeInputFactory() : BaseFactory("source-type") {} }; @@ -111,7 +153,8 @@ class ServerNameInput : public Matcher::DataInput { class ServerNameInputFactory : public BaseFactory { + envoy::extensions::matching::common_inputs::network::v3::ServerNameInput, + MatchingData> { public: ServerNameInputFactory() : BaseFactory("server-name") {} }; @@ -124,7 +167,8 @@ class TransportProtocolInput : public Matcher::DataInput { class TransportProtocolInputFactory : public BaseFactory< TransportProtocolInput, - envoy::extensions::matching::common_inputs::network::v3::TransportProtocolInput> { + envoy::extensions::matching::common_inputs::network::v3::TransportProtocolInput, + MatchingData> { public: TransportProtocolInputFactory() : BaseFactory("transport-protocol") {} }; @@ -137,83 +181,12 @@ class ApplicationProtocolInput : public Matcher::DataInput { class ApplicationProtocolInputFactory : public BaseFactory< ApplicationProtocolInput, - envoy::extensions::matching::common_inputs::network::v3::ApplicationProtocolInput> { + envoy::extensions::matching::common_inputs::network::v3::ApplicationProtocolInput, + MatchingData> { public: ApplicationProtocolInputFactory() : BaseFactory("application-protocol") {} }; -template -class UdpBaseFactory : public Matcher::DataInputFactory { -protected: - explicit UdpBaseFactory(const std::string& name) : name_(name) {} - -public: - std::string name() const override { return name_; } - - Matcher::DataInputFactoryCb - createDataInputFactoryCb(const Protobuf::Message&, ProtobufMessage::ValidationVisitor&) override { - return []() { return std::make_unique(); }; - }; - ProtobufTypes::MessagePtr createEmptyConfigProto() override { - return std::make_unique(); - } - -private: - const std::string name_; -}; - -class UdpDestinationIPInput : public Matcher::DataInput { -public: - Matcher::DataInputGetResult get(const UdpMatchingData& data) const override; -}; - -class UdpDestinationIPInputFactory - : public UdpBaseFactory< - UdpDestinationIPInput, - envoy::extensions::matching::common_inputs::network::v3::DestinationIPInput> { -public: - UdpDestinationIPInputFactory() : UdpBaseFactory("destination-ip") {} -}; - -class UdpDestinationPortInput : public Matcher::DataInput { -public: - Matcher::DataInputGetResult get(const UdpMatchingData& data) const override; -}; - -class UdpDestinationPortInputFactory - : public UdpBaseFactory< - UdpDestinationPortInput, - envoy::extensions::matching::common_inputs::network::v3::DestinationPortInput> { -public: - UdpDestinationPortInputFactory() : UdpBaseFactory("destination-port") {} -}; - -class UdpSourceIPInput : public Matcher::DataInput { -public: - Matcher::DataInputGetResult get(const UdpMatchingData& data) const override; -}; - -class UdpSourceIPInputFactory - : public UdpBaseFactory< - UdpSourceIPInput, - envoy::extensions::matching::common_inputs::network::v3::SourceIPInput> { -public: - UdpSourceIPInputFactory() : UdpBaseFactory("source-ip") {} -}; - -class UdpSourcePortInput : public Matcher::DataInput { -public: - Matcher::DataInputGetResult get(const UdpMatchingData& data) const override; -}; - -class UdpSourcePortInputFactory - : public UdpBaseFactory< - UdpSourcePortInput, - envoy::extensions::matching::common_inputs::network::v3::SourcePortInput> { -public: - UdpSourcePortInputFactory() : UdpBaseFactory("source-port") {} -}; - } // namespace Matching } // namespace Network } // namespace Envoy diff --git a/test/common/network/matching/inputs_test.cc b/test/common/network/matching/inputs_test.cc index cb2eac4f148cf..91b9e377cb566 100644 --- a/test/common/network/matching/inputs_test.cc +++ b/test/common/network/matching/inputs_test.cc @@ -11,7 +11,7 @@ namespace Network { namespace Matching { TEST(MatchingData, DestinationIPInput) { - DestinationIPInput input; + DestinationIPInput input; MockConnectionSocket socket; MatchingDataImpl data(socket); @@ -35,7 +35,7 @@ TEST(MatchingData, DestinationIPInput) { } TEST(MatchingData, DestinationPortInput) { - DestinationPortInput input; + DestinationPortInput input; MockConnectionSocket socket; MatchingDataImpl data(socket); @@ -59,7 +59,7 @@ TEST(MatchingData, DestinationPortInput) { } TEST(MatchingData, SourceIPInput) { - SourceIPInput input; + SourceIPInput input; MockConnectionSocket socket; MatchingDataImpl data(socket); @@ -83,7 +83,7 @@ TEST(MatchingData, SourceIPInput) { } TEST(MatchingData, SourcePortInput) { - SourcePortInput input; + SourcePortInput input; MockConnectionSocket socket; MatchingDataImpl data(socket); @@ -234,7 +234,7 @@ TEST(MatchingData, ApplicationProtocolInput) { } TEST(UdpMatchingData, UdpDestinationIPInput) { - UdpDestinationIPInput input; + DestinationIPInput input; const Address::InstanceConstSharedPtr ip = std::make_shared("127.0.0.1", 8080); const Address::InstanceConstSharedPtr pipe = @@ -258,7 +258,7 @@ TEST(UdpMatchingData, UdpDestinationIPInput) { } TEST(UdpMatchingData, UdpDestinationPortInput) { - UdpDestinationPortInput input; + DestinationPortInput input; const Address::InstanceConstSharedPtr ip = std::make_shared("127.0.0.1", 8080); const Address::InstanceConstSharedPtr pipe = @@ -282,7 +282,7 @@ TEST(UdpMatchingData, UdpDestinationPortInput) { } TEST(UdpMatchingData, UdpSourceIPInput) { - UdpSourceIPInput input; + SourceIPInput input; const Address::InstanceConstSharedPtr ip = std::make_shared("127.0.0.1", 8080); const Address::InstanceConstSharedPtr pipe = @@ -306,7 +306,7 @@ TEST(UdpMatchingData, UdpSourceIPInput) { } TEST(UdpMatchingData, UdpSourcePortInput) { - UdpSourcePortInput input; + SourcePortInput input; const Address::InstanceConstSharedPtr ip = std::make_shared("127.0.0.1", 8080); const Address::InstanceConstSharedPtr pipe = From 6751438fc94db12f2d7390302b559a72a7d354fc Mon Sep 17 00:00:00 2001 From: Xie Zhihao Date: Mon, 14 Mar 2022 13:09:50 +0800 Subject: [PATCH 5/7] nit: remove unwanted explicit Signed-off-by: Xie Zhihao --- source/common/network/matching/data_impl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/common/network/matching/data_impl.h b/source/common/network/matching/data_impl.h index 94a268fb0b862..074dc9c9e6958 100644 --- a/source/common/network/matching/data_impl.h +++ b/source/common/network/matching/data_impl.h @@ -24,8 +24,8 @@ class MatchingDataImpl : public MatchingData { */ class UdpMatchingDataImpl : public UdpMatchingData { public: - explicit UdpMatchingDataImpl(const Address::InstanceConstSharedPtr& local_address, - const Address::InstanceConstSharedPtr& remote_address) + UdpMatchingDataImpl(const Address::InstanceConstSharedPtr& local_address, + const Address::InstanceConstSharedPtr& remote_address) : local_address_(local_address), remote_address_(remote_address) {} const Address::InstanceConstSharedPtr& localAddress() const override { return local_address_; } const Address::InstanceConstSharedPtr& remoteAddress() const override { return remote_address_; } From 536e089a9fdef84241d3fef0be16ec6d13a93ce2 Mon Sep 17 00:00:00 2001 From: Xie Zhihao Date: Mon, 14 Mar 2022 16:55:51 +0800 Subject: [PATCH 6/7] test: add integration test for network matching data Signed-off-by: Xie Zhihao --- test/common/network/matching/BUILD | 14 + .../matching/inputs_integration_test.cc | 249 ++++++++++++++++++ 2 files changed, 263 insertions(+) create mode 100644 test/common/network/matching/inputs_integration_test.cc diff --git a/test/common/network/matching/BUILD b/test/common/network/matching/BUILD index e9f3947bdab07..447d3e68099ff 100644 --- a/test/common/network/matching/BUILD +++ b/test/common/network/matching/BUILD @@ -18,3 +18,17 @@ envoy_cc_test( "//test/mocks/network:network_mocks", ], ) + +envoy_cc_test( + name = "inputs_integration_test", + srcs = ["inputs_integration_test.cc"], + deps = [ + "//source/common/network:address_lib", + "//source/common/network/matching:data_impl_lib", + "//source/common/network/matching:inputs_lib", + "//test/common/matcher:test_utility_lib", + "//test/mocks/matcher:matcher_mocks", + "//test/mocks/network:network_mocks", + "//test/mocks/server:factory_context_mocks", + ], +) diff --git a/test/common/network/matching/inputs_integration_test.cc b/test/common/network/matching/inputs_integration_test.cc new file mode 100644 index 0000000000000..5c63f6dd68d9c --- /dev/null +++ b/test/common/network/matching/inputs_integration_test.cc @@ -0,0 +1,249 @@ +#include "source/common/network/address_impl.h" +#include "source/common/network/matching/data_impl.h" +#include "source/common/network/matching/inputs.h" + +#include "test/common/matcher/test_utility.h" +#include "test/mocks/matcher/mocks.h" +#include "test/mocks/network/mocks.h" +#include "test/mocks/server/factory_context.h" + +#include "gtest/gtest.h" + +namespace Envoy { +namespace Network { +namespace Matching { + +constexpr absl::string_view yaml = R"EOF( +matcher_tree: + input: + name: input + typed_config: + "@type": type.googleapis.com/envoy.extensions.matching.common_inputs.network.v3.{} + exact_match_map: + map: + "{}": + action: + name: test_action + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: foo +)EOF"; + +class InputsIntegrationTest : public ::testing::Test { +public: + InputsIntegrationTest() + : inject_action_(action_factory_), context_(""), + matcher_factory_(context_, factory_context_, validation_visitor_) { + EXPECT_CALL(validation_visitor_, performDataInputValidation(_, _)).Times(testing::AnyNumber()); + } + + void initialize(const std::string& input, const std::string& value) { + xds::type::matcher::v3::Matcher matcher; + MessageUtil::loadFromYaml(fmt::format(std::string(yaml), input, value), matcher, + ProtobufMessage::getStrictValidationVisitor()); + + match_tree_ = matcher_factory_.create(matcher); + } + +protected: + Matcher::StringActionFactory action_factory_; + Registry::InjectFactory> inject_action_; + NiceMock factory_context_; + Matcher::MockMatchTreeValidationVisitor validation_visitor_; + absl::string_view context_; + Matcher::MatchTreeFactory matcher_factory_; + Matcher::MatchTreeFactoryCb match_tree_; +}; + +TEST_F(InputsIntegrationTest, DestinationIPInput) { + initialize("DestinationIPInput", "127.0.0.1"); + + Network::MockConnectionSocket socket; + MatchingDataImpl data(socket); + socket.connection_info_provider_->setLocalAddress( + std::make_shared("127.0.0.1", 8080)); + + const auto result = match_tree_()->match(data); + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); +} + +TEST_F(InputsIntegrationTest, DestinationPortInput) { + initialize("DestinationPortInput", "8080"); + + Network::MockConnectionSocket socket; + MatchingDataImpl data(socket); + socket.connection_info_provider_->setLocalAddress( + std::make_shared("127.0.0.1", 8080)); + + const auto result = match_tree_()->match(data); + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); +} + +TEST_F(InputsIntegrationTest, SourceIPInput) { + initialize("SourceIPInput", "127.0.0.1"); + + Network::MockConnectionSocket socket; + MatchingDataImpl data(socket); + socket.connection_info_provider_->setRemoteAddress( + std::make_shared("127.0.0.1", 8080)); + + const auto result = match_tree_()->match(data); + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); +} + +TEST_F(InputsIntegrationTest, SourcePortInput) { + initialize("SourcePortInput", "8080"); + + Network::MockConnectionSocket socket; + MatchingDataImpl data(socket); + socket.connection_info_provider_->setRemoteAddress( + std::make_shared("127.0.0.1", 8080)); + + const auto result = match_tree_()->match(data); + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); +} + +TEST_F(InputsIntegrationTest, DirectSourceIPInput) { + initialize("DirectSourceIPInput", "127.0.0.1"); + + Network::MockConnectionSocket socket; + MatchingDataImpl data(socket); + socket.connection_info_provider_->setDirectRemoteAddressForTest( + std::make_shared("127.0.0.1", 8080)); + + const auto result = match_tree_()->match(data); + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); +} + +TEST_F(InputsIntegrationTest, SourceTypeInput) { + initialize("SourceTypeInput", "local"); + + Network::MockConnectionSocket socket; + MatchingDataImpl data(socket); + socket.connection_info_provider_->setRemoteAddress( + std::make_shared("127.0.0.1", 8080)); + + const auto result = match_tree_()->match(data); + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); +} + +TEST_F(InputsIntegrationTest, ServerNameInput) { + initialize("ServerNameInput", "example.com"); + + Network::MockConnectionSocket socket; + MatchingDataImpl data(socket); + EXPECT_CALL(socket, requestedServerName).WillOnce(testing::Return("example.com")); + + const auto result = match_tree_()->match(data); + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); +} + +TEST_F(InputsIntegrationTest, TransportProtocolInput) { + initialize("TransportProtocolInput", "tls"); + + Network::MockConnectionSocket socket; + MatchingDataImpl data(socket); + EXPECT_CALL(socket, detectedTransportProtocol).WillOnce(testing::Return("tls")); + + const auto result = match_tree_()->match(data); + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); +} + +TEST_F(InputsIntegrationTest, ApplicationProtocolInput) { + initialize("ApplicationProtocolInput", "'http/1.1'"); + + Network::MockConnectionSocket socket; + MatchingDataImpl data(socket); + std::vector protocols = {"http/1.1"}; + EXPECT_CALL(socket, requestedApplicationProtocols).WillOnce(testing::ReturnRef(protocols)); + + const auto result = match_tree_()->match(data); + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); +} + +class UdpInputsIntegrationTest : public ::testing::Test { +public: + UdpInputsIntegrationTest() + : inject_action_(action_factory_), context_(""), + matcher_factory_(context_, factory_context_, validation_visitor_) { + EXPECT_CALL(validation_visitor_, performDataInputValidation(_, _)).Times(testing::AnyNumber()); + } + + void initialize(const std::string& input, const std::string& value) { + xds::type::matcher::v3::Matcher matcher; + MessageUtil::loadFromYaml(fmt::format(std::string(yaml), input, value), matcher, + ProtobufMessage::getStrictValidationVisitor()); + + match_tree_ = matcher_factory_.create(matcher); + } + +protected: + Matcher::StringActionFactory action_factory_; + Registry::InjectFactory> inject_action_; + NiceMock factory_context_; + Matcher::MockMatchTreeValidationVisitor validation_visitor_; + absl::string_view context_; + Matcher::MatchTreeFactory matcher_factory_; + Matcher::MatchTreeFactoryCb match_tree_; +}; + +TEST_F(UdpInputsIntegrationTest, DestinationIPInput) { + initialize("DestinationIPInput", "127.0.0.1"); + + const Address::InstanceConstSharedPtr ip = + std::make_shared("127.0.0.1", 8080); + UdpMatchingDataImpl data(ip, ip); + + const auto result = match_tree_()->match(data); + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); +} + +TEST_F(UdpInputsIntegrationTest, DestinationPortInput) { + initialize("DestinationPortInput", "8080"); + + const Address::InstanceConstSharedPtr ip = + std::make_shared("127.0.0.1", 8080); + UdpMatchingDataImpl data(ip, ip); + + const auto result = match_tree_()->match(data); + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); +} + +TEST_F(UdpInputsIntegrationTest, SourceIPInput) { + initialize("SourceIPInput", "127.0.0.1"); + + const Address::InstanceConstSharedPtr ip = + std::make_shared("127.0.0.1", 8080); + UdpMatchingDataImpl data(ip, ip); + + const auto result = match_tree_()->match(data); + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); +} + +TEST_F(UdpInputsIntegrationTest, SourcePortInput) { + initialize("SourcePortInput", "8080"); + + const Address::InstanceConstSharedPtr ip = + std::make_shared("127.0.0.1", 8080); + UdpMatchingDataImpl data(ip, ip); + + const auto result = match_tree_()->match(data); + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); +} + +} // namespace Matching +} // namespace Network +} // namespace Envoy From 852592853083fa9564ad215230026d6eafd3fcc7 Mon Sep 17 00:00:00 2001 From: Xie Zhihao Date: Fri, 25 Mar 2022 11:16:49 +0800 Subject: [PATCH 7/7] docs: add UDP network inputs Signed-off-by: Xie Zhihao --- .../intro/arch_overview/advanced/matching/matching_api.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/root/intro/arch_overview/advanced/matching/matching_api.rst b/docs/root/intro/arch_overview/advanced/matching/matching_api.rst index efc9d4e231a7b..a178ba64925e2 100644 --- a/docs/root/intro/arch_overview/advanced/matching/matching_api.rst +++ b/docs/root/intro/arch_overview/advanced/matching/matching_api.rst @@ -40,13 +40,16 @@ These input functions are available for matching HTTP requests: Network Input Functions *********************** -These input functions are available for matching TCP connections: +These input functions are available for matching both TCP connections and UDP datagrams: * :ref:`Destination IP `. * :ref:`Destination port `. * :ref:`Source IP `. -* :ref:`Direct source IP `. * :ref:`Source port `. + +These input functions are available for matching TCP connections: + +* :ref:`Direct source IP `. * :ref:`Source type `. * :ref:`Server name `. * :ref:`Transport protocol `.