From 80fe0ac194fdc7c587093c5486c79dcdcddd334d Mon Sep 17 00:00:00 2001 From: Braden Bassingthwaite Date: Wed, 27 Nov 2024 20:44:07 -0600 Subject: [PATCH] listener: Fix issue with listener update not supporting an addition and removal of an additional_address in the same update. Fixes #37373 Signed-off-by: Braden Bassingthwaite --- .../common/listener_manager/listener_impl.cc | 17 +++++-- .../listener_manager_impl_test.cc | 46 ++++++++++++++++++- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/source/common/listener_manager/listener_impl.cc b/source/common/listener_manager/listener_impl.cc index 2affcdc553015..621a7eb399d5c 100644 --- a/source/common/listener_manager/listener_impl.cc +++ b/source/common/listener_manager/listener_impl.cc @@ -1223,18 +1223,27 @@ bool ListenerMessageUtil::socketOptionsEqual(const envoy::config::listener::v3:: if (lhs.additional_addresses_size() != rhs.additional_addresses_size()) { return false; } - // Assume people won't change the order of additional addresses. + for (auto i = 0; i < lhs.additional_addresses_size(); i++) { + auto lhs_addr = lhs.additional_addresses(i); + auto iter = std::find_if(rhs.additional_addresses().begin(), rhs.additional_addresses().end(), + [&lhs_addr](const envoy::config::listener::v3::AdditionalAddress& addr) { + return Protobuf::util::MessageDifferencer::Equals(lhs_addr.address(), addr.address()); + }); + if (iter == rhs.additional_addresses().end()) { + return false; + } + if (lhs.additional_addresses(i).has_socket_options() != - rhs.additional_addresses(i).has_socket_options()) { + iter->has_socket_options()) { return false; } if (lhs.additional_addresses(i).has_socket_options()) { is_equal = std::equal(lhs.additional_addresses(i).socket_options().socket_options().begin(), lhs.additional_addresses(i).socket_options().socket_options().end(), - rhs.additional_addresses(i).socket_options().socket_options().begin(), - rhs.additional_addresses(i).socket_options().socket_options().end(), + iter->socket_options().socket_options().begin(), + iter->socket_options().socket_options().end(), [](const ::envoy::config::core::v3::SocketOption& option, const ::envoy::config::core::v3::SocketOption& other_option) { return Protobuf::util::MessageDifferencer::Equals(option, other_option); diff --git a/test/common/listener_manager/listener_manager_impl_test.cc b/test/common/listener_manager/listener_manager_impl_test.cc index cd7a7f658fe63..309be2e5ef521 100644 --- a/test/common/listener_manager/listener_manager_impl_test.cc +++ b/test/common/listener_manager/listener_manager_impl_test.cc @@ -400,6 +400,50 @@ name: bar addOrUpdateListener(parseListenerFromV3Yaml(yaml2)); } +#ifdef __linux__ +TEST_P(ListenerManagerImplWithRealFiltersTest, + AllowUpdateListenerWithAddAndRemoveAdditionalAddress) { + const std::string yaml1 = R"EOF( +name: foo +enable_reuse_port: true +address: + socket_address: + address: 127.0.0.1 + port_value: 8000 +additional_addresses: +- address: + socket_address: + address: 127.0.0.1 + port_value: 8001 +filter_chains: +- filters: [] + name: foo + )EOF"; + + const std::string yaml2 = R"EOF( +name: foo +enable_reuse_port: true +address: + socket_address: + address: 127.0.0.1 + port_value: 8000 +additional_addresses: +- address: + socket_address: + address: 127.0.0.1 + port_value: 8002 +filter_chains: +- filters: [] + name: foo + )EOF"; + + EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, _, _, _)).Times(2); + addOrUpdateListener(parseListenerFromV3Yaml(yaml1)); + EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, _, _, _)).Times(2); + addOrUpdateListener(parseListenerFromV3Yaml(yaml2)); +} +#endif + TEST_P(ListenerManagerImplWithRealFiltersTest, SetListenerPerConnectionBufferLimit) { const std::string yaml = R"EOF( address: @@ -2034,7 +2078,7 @@ per_connection_buffer_limit_bytes: 999 )EOF"; ListenerHandle* listener_foo_update1 = expectListenerCreate(true, true); - EXPECT_CALL(*listener_factory_.socket_, duplicate()).Times(2); + EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, _, _, _)).Times(2); EXPECT_CALL(listener_foo_update1->target_, initialize()); EXPECT_TRUE(addOrUpdateListener(parseListenerFromV3Yaml(listener_foo_update1_yaml)));