Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions docs/root/version_history/current.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ Minor Behavior Changes
* http: fixed the 100-continue response path to properly handle upstream failure by sending 5xx responses. This behavior can be temporarily reverted by setting `envoy.reloadable_features.allow_500_after_100` to false.
* http: the per-stream FilterState maintained by the HTTP connection manager will now provide read/write access to the downstream connection FilterState. As such, code that relies on interacting with this might
see a change in behavior.
* logging: add fine-grain logging for file level log control with logger management at administration interface. It can be enabled by option `--enable-fine-grain-logging`.
* logging: change default log format to `"[%Y-%m-%d %T.%e][%t][%l][%n] [%g:%#] %v"` and default value of :option:`--log-format-prefix-with-location` to `0`.
* logging: added fine-grain logging for file level log control with logger management at administration interface. It can be enabled by option `--enable-fine-grain-logging`.
* logging: changed default log format to `"[%Y-%m-%d %T.%e][%t][%l][%n] [%g:%#] %v"` and default value of :option:`--log-format-prefix-with-location` to `0`.
* logging: nghttp2 log messages no longer appear at trace level unless `ENVOY_NGHTTP2_TRACE` is set
in the environment.
* router: added transport failure reason to response body when upstream reset happens. After this change, the response body will be of the form `upstream connect error or disconnect/reset before headers. reset reason:{}, transport failure reason:{}`.This behavior may be reverted by setting runtime feature `envoy.reloadable_features.http_transport_failure_reason_in_body` to false.
Expand All @@ -47,6 +47,7 @@ Bug Fixes
* grpc-web: fixed an issue with failing HTTP/2 requests on some browsers. Notably, WebKit-based browsers (https://bugs.webkit.org/show_bug.cgi?id=210108), Internet Explorer 11, and Edge (pre-Chromium).
* http: made the HeaderValues::prefix() method const.
* jwt_authn: supports jwt payload without "iss" field.
* listener: fixed crash at listener inplace update when connetion load balancer is set.
* rocketmq_proxy network-level filter: fixed an issue involving incorrect header lengths. In debug mode it causes crash and in release mode it causes underflow.
* thrift_proxy: fixed crashing bug on request overflow.
* udp_proxy: fixed a crash due to UDP packets being processed after listener removal.
Expand Down
2 changes: 1 addition & 1 deletion include/envoy/network/connection_balancer.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class ConnectionBalancer {
pickTargetHandler(BalancedConnectionHandler& current_handler) PURE;
};

using ConnectionBalancerPtr = std::unique_ptr<ConnectionBalancer>;
using ConnectionBalancerSharedPtr = std::shared_ptr<ConnectionBalancer>;

} // namespace Network
} // namespace Envoy
1 change: 1 addition & 0 deletions source/server/connection_handler_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ ConnectionHandlerImpl::ActiveTcpListener::ActiveTcpListener(ConnectionHandlerImp
void ConnectionHandlerImpl::ActiveTcpListener::updateListenerConfig(
Network::ListenerConfig& config) {
ENVOY_LOG(trace, "replacing listener ", config_->listenerTag(), " by ", config.listenerTag());
ASSERT(&config_->connectionBalancer() == &config.connectionBalancer());
config_ = &config;
}

Expand Down
16 changes: 10 additions & 6 deletions source/server/listener_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ ListenerImpl::ListenerImpl(ListenerImpl& origin,
listener_filters_timeout_(
PROTOBUF_GET_MS_OR_DEFAULT(config, listener_filters_timeout, 15000)),
continue_on_listener_filters_timeout_(config.continue_on_listener_filters_timeout()),
connection_balancer_(origin.connection_balancer_),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mark

listener_factory_context_(std::make_shared<PerListenerFactoryContextImpl>(
origin.listener_factory_context_->listener_factory_context_base_, this, *this)),
filter_chain_manager_(address_, origin.listener_factory_context_->parentFactoryContext(),
Expand Down Expand Up @@ -488,12 +489,15 @@ void ListenerImpl::buildFilterChains() {

void ListenerImpl::buildSocketOptions() {
// TCP specific setup.
if (config_.has_connection_balance_config()) {
// Currently exact balance is the only supported type and there are no options.
ASSERT(config_.connection_balance_config().has_exact_balance());
connection_balancer_ = std::make_unique<Network::ExactConnectionBalancerImpl>();
} else {
connection_balancer_ = std::make_unique<Network::NopConnectionBalancerImpl>();
if (connection_balancer_ == nullptr) {
// Not in place listener update.
if (config_.has_connection_balance_config()) {
// Currently exact balance is the only supported type and there are no options.
ASSERT(config_.connection_balance_config().has_exact_balance());
connection_balancer_ = std::make_shared<Network::ExactConnectionBalancerImpl>();
} else {
connection_balancer_ = std::make_shared<Network::NopConnectionBalancerImpl>();
}
}

if (config_.has_tcp_fast_open_queue_length()) {
Expand Down
2 changes: 1 addition & 1 deletion source/server/listener_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ class ListenerImpl final : public Network::ListenerConfig,
const bool continue_on_listener_filters_timeout_;
Network::ActiveUdpListenerFactoryPtr udp_listener_factory_;
Network::UdpPacketWriterFactoryPtr udp_writer_factory_;
Network::ConnectionBalancerPtr connection_balancer_;
Network::ConnectionBalancerSharedPtr connection_balancer_;
std::shared_ptr<PerListenerFactoryContextImpl> listener_factory_context_;
FilterChainManagerImpl filter_chain_manager_;

Expand Down
39 changes: 38 additions & 1 deletion test/integration/xds_integration_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,13 @@ class LdsInplaceUpdateHttpIntegrationTest
std::string tls_inspector_config = ConfigHelper::tlsInspectorFilter();
config_helper_.addListenerFilter(tls_inspector_config);
config_helper_.addSslConfig();
config_helper_.addConfigModifier([](envoy::config::bootstrap::v3::Bootstrap& bootstrap) {
config_helper_.addConfigModifier([this](envoy::config::bootstrap::v3::Bootstrap& bootstrap) {
if (!use_default_balancer_) {
bootstrap.mutable_static_resources()
->mutable_listeners(0)
->mutable_connection_balance_config()
->mutable_exact_balance();
}
auto* filter_chain_0 =
bootstrap.mutable_static_resources()->mutable_listeners(0)->mutable_filter_chains(0);
*filter_chain_0->mutable_filter_chain_match()->mutable_application_protocols()->Add() =
Expand Down Expand Up @@ -356,10 +362,17 @@ class LdsInplaceUpdateHttpIntegrationTest
}
}

void expectConnenctionServed(std::string alpn = "alpn0") {
auto codec_client_after_config_update = createHttpCodec(alpn);
expectResponseHeaderConnectionClose(*codec_client_after_config_update, false);
codec_client_after_config_update->close();
}

std::unique_ptr<Ssl::ContextManager> context_manager_;
Network::TransportSocketFactoryPtr context_;
testing::NiceMock<Secret::MockSecretManager> secret_manager_;
Network::Address::InstanceConstSharedPtr address_;
bool use_default_balancer_{false};
};

// Verify that http response on filter chain 0 has "Connection: close" header when filter chain 0
Expand Down Expand Up @@ -388,6 +401,7 @@ TEST_P(LdsInplaceUpdateHttpIntegrationTest, ReloadConfigDeletingFilterChain) {
expectResponseHeaderConnectionClose(*codec_client_1, true);
test_server_->waitForGaugeGe("listener_manager.total_filter_chains_draining", 0);
expectResponseHeaderConnectionClose(*codec_client_0, false);
expectConnenctionServed();
}

// Verify that http clients of filter chain 0 survives if new listener config adds new filter
Expand Down Expand Up @@ -416,6 +430,29 @@ TEST_P(LdsInplaceUpdateHttpIntegrationTest, ReloadConfigAddingFilterChain) {
Cleanup cleanup2([c2 = codec_client_2.get()]() { c2->close(); });
expectResponseHeaderConnectionClose(*codec_client_2, false);
expectResponseHeaderConnectionClose(*codec_client_0, false);
expectConnenctionServed();
}

// Verify that balancer is inherited. Test only default balancer because ExactConnectionBalancer
// is verified in filter chain add and delete test case.
TEST_P(LdsInplaceUpdateHttpIntegrationTest, OverlappingFilterChainServesNewConnection) {
use_default_balancer_ = true;
initialize();

auto codec_client_0 = createHttpCodec("alpn0");
Cleanup cleanup([c0 = codec_client_0.get()]() { c0->close(); });
ConfigHelper new_config_helper(version_, *api_,
MessageUtil::getJsonStringFromMessage(config_helper_.bootstrap()));
new_config_helper.addConfigModifier(
[&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void {
auto* listener = bootstrap.mutable_static_resources()->mutable_listeners(0);
listener->mutable_filter_chains()->RemoveLast();
});

new_config_helper.setLds("1");
test_server_->waitForCounterGe("listener_manager.listener_in_place_updated", 1);
expectResponseHeaderConnectionClose(*codec_client_0, false);
expectConnenctionServed();
}

INSTANTIATE_TEST_SUITE_P(IpVersions, LdsInplaceUpdateHttpIntegrationTest,
Expand Down
44 changes: 29 additions & 15 deletions test/server/connection_handler_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,17 @@ class ConnectionHandlerTest : public testing::Test, protected Logger::Loggable<L
Network::ListenSocketFactorySharedPtr socket_factory,
std::shared_ptr<AccessLog::MockInstance> access_log,
std::shared_ptr<NiceMock<Network::MockFilterChainManager>> filter_chain_manager = nullptr,
uint32_t tcp_backlog_size = ENVOY_TCP_BACKLOG_SIZE)
uint32_t tcp_backlog_size = ENVOY_TCP_BACKLOG_SIZE,
Network::ConnectionBalancerSharedPtr connection_balancer = nullptr)
: parent_(parent), socket_(std::make_shared<NiceMock<Network::MockListenSocket>>()),
socket_factory_(std::move(socket_factory)), tag_(tag), bind_to_port_(bind_to_port),
tcp_backlog_size_(tcp_backlog_size),
hand_off_restored_destination_connections_(hand_off_restored_destination_connections),
name_(name), listener_filters_timeout_(listener_filters_timeout),
continue_on_listener_filters_timeout_(continue_on_listener_filters_timeout),
connection_balancer_(std::make_unique<Network::NopConnectionBalancerImpl>()),
connection_balancer_(connection_balancer == nullptr
? std::make_shared<Network::NopConnectionBalancerImpl>()
: connection_balancer),
access_logs_({access_log}), inline_filter_chain_manager_(filter_chain_manager),
init_manager_(nullptr) {
envoy::config::listener::v3::UdpListenerConfig dummy;
Expand Down Expand Up @@ -135,7 +138,7 @@ class ConnectionHandlerTest : public testing::Test, protected Logger::Loggable<L
const bool continue_on_listener_filters_timeout_;
std::unique_ptr<Network::ActiveUdpListenerFactory> udp_listener_factory_;
std::unique_ptr<Network::UdpPacketWriterFactory> udp_writer_factory_;
Network::ConnectionBalancerPtr connection_balancer_;
Network::ConnectionBalancerSharedPtr connection_balancer_;
BasicResourceLimitImpl open_connections_;
const std::vector<AccessLog::InstanceSharedPtr> access_logs_;
std::shared_ptr<NiceMock<Network::MockFilterChainManager>> inline_filter_chain_manager_;
Expand Down Expand Up @@ -182,7 +185,7 @@ class ConnectionHandlerTest : public testing::Test, protected Logger::Loggable<L
uint64_t tag, bool bind_to_port, bool hand_off_restored_destination_connections,
const std::string& name, Network::Listener* listener,
Network::TcpListenerCallbacks** listener_callbacks = nullptr,
Network::MockConnectionBalancer* connection_balancer = nullptr,
std::shared_ptr<Network::MockConnectionBalancer> connection_balancer = nullptr,
Network::BalancedConnectionHandler** balanced_connection_handler = nullptr,
Network::Socket::Type socket_type = Network::Socket::Type::Stream,
std::chrono::milliseconds listener_filters_timeout = std::chrono::milliseconds(15000),
Expand All @@ -193,8 +196,9 @@ class ConnectionHandlerTest : public testing::Test, protected Logger::Loggable<L
listeners_.emplace_back(std::make_unique<TestListener>(
*this, tag, bind_to_port, hand_off_restored_destination_connections, name, socket_type,
listener_filters_timeout, continue_on_listener_filters_timeout, socket_factory_,
access_log_, overridden_filter_chain_manager, tcp_backlog_size));
access_log_, overridden_filter_chain_manager, tcp_backlog_size, connection_balancer));
EXPECT_CALL(*socket_factory_, socketType()).WillOnce(Return(socket_type));

if (listener == nullptr) {
// Expecting listener config in place update.
// If so, dispatcher would not create new network listener.
Expand All @@ -219,12 +223,11 @@ class ConnectionHandlerTest : public testing::Test, protected Logger::Loggable<L
}));
}

if (connection_balancer != nullptr) {
listeners_.back()->connection_balancer_.reset(connection_balancer);
ASSERT(balanced_connection_handler != nullptr);
if (balanced_connection_handler != nullptr) {
EXPECT_CALL(*connection_balancer, registerHandler(_))
.WillOnce(SaveArgAddress(balanced_connection_handler));
}

return listeners_.back().get();
}

Expand Down Expand Up @@ -257,7 +260,7 @@ TEST_F(ConnectionHandlerTest, RemoveListenerDuringRebalance) {

Network::TcpListenerCallbacks* listener_callbacks;
auto listener = new NiceMock<Network::MockListener>();
Network::MockConnectionBalancer* connection_balancer = new Network::MockConnectionBalancer();
auto connection_balancer = std::make_shared<Network::MockConnectionBalancer>();
Network::BalancedConnectionHandler* current_handler;
TestListener* test_listener =
addListener(1, true, false, "test_listener", listener, &listener_callbacks,
Expand Down Expand Up @@ -988,9 +991,14 @@ TEST_F(ConnectionHandlerTest, TcpListenerInplaceUpdate) {
uint64_t old_listener_tag = 1;
uint64_t new_listener_tag = 2;
Network::TcpListenerCallbacks* old_listener_callbacks;
Network::BalancedConnectionHandler* current_handler;

auto old_listener = new NiceMock<Network::MockListener>();
TestListener* old_test_listener = addListener(old_listener_tag, true, false, "test_listener",
old_listener, &old_listener_callbacks);
auto mock_connection_balancer = std::make_shared<Network::MockConnectionBalancer>();

TestListener* old_test_listener =
addListener(old_listener_tag, true, false, "test_listener", old_listener,
&old_listener_callbacks, mock_connection_balancer, &current_handler);
EXPECT_CALL(*socket_factory_, localAddress()).WillOnce(ReturnRef(local_address_));
handler_->addListener(absl::nullopt, *old_test_listener);
ASSERT_NE(old_test_listener, nullptr);
Expand All @@ -999,19 +1007,25 @@ TEST_F(ConnectionHandlerTest, TcpListenerInplaceUpdate) {

auto overridden_filter_chain_manager =
std::make_shared<NiceMock<Network::MockFilterChainManager>>();
TestListener* new_test_listener =
addListener(new_listener_tag, true, false, "test_listener", /* Network::Listener */ nullptr,
&new_listener_callbacks, nullptr, nullptr, Network::Socket::Type::Stream,
std::chrono::milliseconds(15000), false, overridden_filter_chain_manager);
TestListener* new_test_listener = addListener(
new_listener_tag, true, false, "test_listener", /* Network::Listener */ nullptr,
&new_listener_callbacks, mock_connection_balancer, nullptr, Network::Socket::Type::Stream,
std::chrono::milliseconds(15000), false, overridden_filter_chain_manager);
handler_->addListener(old_listener_tag, *new_test_listener);
ASSERT_EQ(new_listener_callbacks, nullptr)
<< "new listener should be inplace added and callback should not change";

Network::MockConnectionSocket* connection = new NiceMock<Network::MockConnectionSocket>();
current_handler->incNumConnections();

EXPECT_CALL(*mock_connection_balancer, pickTargetHandler(_))
.WillOnce(ReturnRef(*current_handler));
EXPECT_CALL(manager_, findFilterChain(_)).Times(0);
EXPECT_CALL(*overridden_filter_chain_manager, findFilterChain(_)).WillOnce(Return(nullptr));
EXPECT_CALL(*access_log_, log(_, _, _, _)).Times(1);
EXPECT_CALL(*mock_connection_balancer, unregisterHandler(_));
old_listener_callbacks->onAccept(Network::ConnectionSocketPtr{connection});
EXPECT_EQ(0UL, handler_->numConnections());
EXPECT_CALL(*old_listener, onDestroy());
}

Expand Down