diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index e74714f832f7..ce3a0e58bc46 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -76,7 +76,7 @@ REPOSITORY_LOCATIONS = dict( urls = ["https://github.com/google/protobuf/archive/v3.5.0.tar.gz"], ), envoy_api = dict( - commit = "15dc537b6078988ac6f7de5ffec697e876a4652f", + commit = "b6925003b383f6f1213f5c62f96cd2cfd0c072be", remote = "https://github.com/envoyproxy/data-plane-api", ), grpc_httpjson_transcoding = dict( diff --git a/include/envoy/event/dispatcher.h b/include/envoy/event/dispatcher.h index 4edd5927e0b3..5f84e46f7c4e 100644 --- a/include/envoy/event/dispatcher.h +++ b/include/envoy/event/dispatcher.h @@ -102,6 +102,7 @@ class Dispatcher { */ virtual Network::ListenerPtr createListener(Network::Socket& socket, Network::ListenerCallbacks& cb, bool bind_to_port, + bool enable_tcp_fast_open, bool hand_off_restored_destination_connections) PURE; /** diff --git a/include/envoy/network/listener.h b/include/envoy/network/listener.h index 16cf4e5d481a..a2d1e3e4173a 100644 --- a/include/envoy/network/listener.h +++ b/include/envoy/network/listener.h @@ -44,6 +44,11 @@ class ListenerConfig { */ virtual bool bindToPort() PURE; + /** + * @return bool specifies whether the listener should support TCP Fast Open. + */ + virtual bool enableTcpFastOpen() PURE; + /** * @return bool if a connection should be handed off to another Listener after the original * destination address has been restored. 'true' when 'use_original_dst' flag in listener diff --git a/source/common/event/dispatcher_impl.cc b/source/common/event/dispatcher_impl.cc index b195d6ae2913..82df1a60ac50 100644 --- a/source/common/event/dispatcher_impl.cc +++ b/source/common/event/dispatcher_impl.cc @@ -109,9 +109,11 @@ Filesystem::WatcherPtr DispatcherImpl::createFilesystemWatcher() { Network::ListenerPtr DispatcherImpl::createListener(Network::Socket& socket, Network::ListenerCallbacks& cb, - bool bind_to_port, bool hand_off_restored_destination_connections) { + bool bind_to_port, bool enable_tcp_fast_open, + bool hand_off_restored_destination_connections) { ASSERT(isThreadSafe()); return Network::ListenerPtr{new Network::ListenerImpl(*this, socket, cb, bind_to_port, + enable_tcp_fast_open, hand_off_restored_destination_connections)}; } diff --git a/source/common/event/dispatcher_impl.h b/source/common/event/dispatcher_impl.h index 95d52938da44..3d10ad787e10 100644 --- a/source/common/event/dispatcher_impl.h +++ b/source/common/event/dispatcher_impl.h @@ -47,7 +47,7 @@ class DispatcherImpl : Logger::Loggable, public Dispatcher { uint32_t events) override; Filesystem::WatcherPtr createFilesystemWatcher() override; Network::ListenerPtr createListener(Network::Socket& socket, Network::ListenerCallbacks& cb, - bool bind_to_port, + bool bind_to_port, bool enable_tcp_fast_open, bool hand_off_restored_destination_connections) override; TimerPtr createTimer(TimerCb cb) override; void deferredDelete(DeferredDeletablePtr&& to_delete) override; diff --git a/source/common/network/listener_impl.cc b/source/common/network/listener_impl.cc index da70a74fffce..539e1f063eee 100644 --- a/source/common/network/listener_impl.cc +++ b/source/common/network/listener_impl.cc @@ -1,5 +1,6 @@ #include "common/network/listener_impl.h" +#include #include #include "envoy/common/exception.h" @@ -13,6 +14,16 @@ #include "event2/listener.h" +// On macOS the socket MUST be listening already for TCP_FASTOPEN to be set and backlog MUST be 1 +// (the actual value is set via the net.inet.tcp.fastopen_backlog kernel parameter. +// For Linux we default to 128, which libevent is using in +// https://github.com/libevent/libevent/blob/release-2.1.8-stable/listener.c#L176 +#if defined(__APPLE__) +#define TFO_BACKLOG 1 +#else +#define TFO_BACKLOG 128 +#endif + namespace Envoy { namespace Network { @@ -45,7 +56,8 @@ void ListenerImpl::listenCallback(evconnlistener*, evutil_socket_t fd, sockaddr* } ListenerImpl::ListenerImpl(Event::DispatcherImpl& dispatcher, Socket& socket, ListenerCallbacks& cb, - bool bind_to_port, bool hand_off_restored_destination_connections) + bool bind_to_port, bool enable_tcp_fast_open, + bool hand_off_restored_destination_connections) : local_address_(nullptr), cb_(cb), hand_off_restored_destination_connections_(hand_off_restored_destination_connections), listener_(nullptr) { @@ -66,6 +78,48 @@ ListenerImpl::ListenerImpl(Event::DispatcherImpl& dispatcher, Socket& socket, Li fmt::format("cannot listen on socket: {}", socket.localAddress()->asString())); } + // TODO: cleanup redundant setsockopt logic + if (enable_tcp_fast_open) { + int backlog = TFO_BACKLOG; + int fd = socket.fd(); + int rc = setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN, &backlog, sizeof(backlog)); + if (rc == -1) { + if (errno == ENOPROTOOPT) { + throw EnvoyException(fmt::format( + "TCP Fast Open is unsupported on listening socket fd {} : {}", fd, strerror(errno))); + } else { + throw EnvoyException( + fmt::format("Failed to enable TCP Fast Open on listening socket fd {} : {}", fd, + strerror(errno))); + } + } else { + ENVOY_LOG_MISC(debug, "Enabled TFO on listening socket fd {}.", fd); + } + } else { + int curbacklog; + int fd = socket.fd(); + socklen_t optlen = sizeof(curbacklog); + int rc = getsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN, &curbacklog, &optlen); + // curbacklog == 0 means TFO is supported and already disabled + if (rc != -1 && curbacklog != 0) { + int backlog = 0; + int rc = setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN, &backlog, sizeof(backlog)); + if (rc == -1) { + if (errno == ENOPROTOOPT) { + throw EnvoyException( + fmt::format("TCP Fast Open is unsupported on listening socket fd {} : {}", fd, + strerror(errno))); + } else { + throw EnvoyException( + fmt::format("Failed to disable TCP Fast Open on listening socket fd {} : {}", fd, + strerror(errno))); + } + } else { + ENVOY_LOG_MISC(debug, "Disabled TFO on listening socket fd {}.", fd); + } + } + } + evconnlistener_set_error_cb(listener_.get(), errorCallback); } } diff --git a/source/common/network/listener_impl.h b/source/common/network/listener_impl.h index d55ccfc623bd..555b9a9f8b5a 100644 --- a/source/common/network/listener_impl.h +++ b/source/common/network/listener_impl.h @@ -17,7 +17,8 @@ namespace Network { class ListenerImpl : public Listener { public: ListenerImpl(Event::DispatcherImpl& dispatcher, Socket& socket, ListenerCallbacks& cb, - bool bind_to_port, bool hand_off_restored_destination_connections); + bool bind_to_port, bool enable_tcp_fast_open, + bool hand_off_restored_destination_connections); protected: virtual Address::InstanceConstSharedPtr getLocalAddress(int fd); diff --git a/source/server/config_validation/dispatcher.cc b/source/server/config_validation/dispatcher.cc index 7966f746e1cb..06855c4ea2e1 100644 --- a/source/server/config_validation/dispatcher.cc +++ b/source/server/config_validation/dispatcher.cc @@ -17,7 +17,8 @@ Network::DnsResolverSharedPtr ValidationDispatcher::createDnsResolver( } Network::ListenerPtr ValidationDispatcher::createListener(Network::Socket&, - Network::ListenerCallbacks&, bool, bool) { + Network::ListenerCallbacks&, bool, bool, + bool) { NOT_IMPLEMENTED; } diff --git a/source/server/config_validation/dispatcher.h b/source/server/config_validation/dispatcher.h index 54fad3c12943..aef51eb9af57 100644 --- a/source/server/config_validation/dispatcher.h +++ b/source/server/config_validation/dispatcher.h @@ -21,7 +21,7 @@ class ValidationDispatcher : public DispatcherImpl { Network::DnsResolverSharedPtr createDnsResolver( const std::vector& resolvers) override; Network::ListenerPtr createListener(Network::Socket&, Network::ListenerCallbacks&, - bool bind_to_port, + bool bind_to_port, bool enable_tcp_fast_open, bool hand_off_restored_destination_connections) override; }; diff --git a/source/server/connection_handler_impl.cc b/source/server/connection_handler_impl.cc index 89d807e96641..70524554b97c 100644 --- a/source/server/connection_handler_impl.cc +++ b/source/server/connection_handler_impl.cc @@ -60,11 +60,11 @@ void ConnectionHandlerImpl::ActiveListener::removeConnection(ActiveConnection& c ConnectionHandlerImpl::ActiveListener::ActiveListener(ConnectionHandlerImpl& parent, Network::ListenerConfig& config) - : ActiveListener( - parent, - parent.dispatcher_.createListener(config.socket(), *this, config.bindToPort(), - config.handOffRestoredDestinationConnections()), - config) {} + : ActiveListener(parent, + parent.dispatcher_.createListener( + config.socket(), *this, config.bindToPort(), config.enableTcpFastOpen(), + config.handOffRestoredDestinationConnections()), + config) {} ConnectionHandlerImpl::ActiveListener::ActiveListener(ConnectionHandlerImpl& parent, Network::ListenerPtr&& listener, diff --git a/source/server/http/admin.h b/source/server/http/admin.h index d3fd7c3d19fd..2655924a71e1 100644 --- a/source/server/http/admin.h +++ b/source/server/http/admin.h @@ -181,6 +181,7 @@ class AdminImpl : public Admin, return parent_.transport_socket_factory_; } bool bindToPort() override { return true; } + bool enableTcpFastOpen() override { return false; } bool handOffRestoredDestinationConnections() const override { return false; } uint32_t perConnectionBufferLimitBytes() override { return 0; } Stats::Scope& listenerScope() override { return *scope_; } diff --git a/source/server/listener_manager_impl.cc b/source/server/listener_manager_impl.cc index 31f9e283d155..1f7a2d726204 100644 --- a/source/server/listener_manager_impl.cc +++ b/source/server/listener_manager_impl.cc @@ -112,6 +112,7 @@ ListenerImpl::ListenerImpl(const envoy::api::v2::Listener& config, ListenerManag listener_scope_( parent_.server_.stats().createScope(fmt::format("listener.{}.", address_->asString()))), bind_to_port_(PROTOBUF_GET_WRAPPED_OR_DEFAULT(config.deprecated_v1(), bind_to_port, true)), + enable_tcp_fast_open_(config.enable_tcp_fast_open()), hand_off_restored_destination_connections_( PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, use_original_dst, false)), per_connection_buffer_limit_bytes_( diff --git a/source/server/listener_manager_impl.h b/source/server/listener_manager_impl.h index 3b649edd6ea3..c79428917a4e 100644 --- a/source/server/listener_manager_impl.h +++ b/source/server/listener_manager_impl.h @@ -48,7 +48,6 @@ class ProdListenerComponentFactory : public ListenerComponentFactory, Configuration::ListenerFactoryContext& context) override { return createListenerFilterFactoryList_(filters, context); } - Network::SocketSharedPtr createListenSocket(Network::Address::InstanceConstSharedPtr address, bool bind_to_port) override; DrainManagerPtr createDrainManager(envoy::api::v2::Listener::DrainType drain_type) override; @@ -213,6 +212,7 @@ class ListenerImpl : public Network::ListenerConfig, Network::FilterChainFactory& filterChainFactory() override { return *this; } Network::Socket& socket() override { return *socket_; } bool bindToPort() override { return bind_to_port_; } + bool enableTcpFastOpen() override { return enable_tcp_fast_open_; } bool handOffRestoredDestinationConnections() const override { return hand_off_restored_destination_connections_; } @@ -270,6 +270,7 @@ class ListenerImpl : public Network::ListenerConfig, std::vector tls_contexts_; std::vector transport_socket_factories_; const bool bind_to_port_; + const bool enable_tcp_fast_open_; const bool hand_off_restored_destination_connections_; const uint32_t per_connection_buffer_limit_bytes_; const uint64_t listener_tag_; diff --git a/test/common/http/codec_client_test.cc b/test/common/http/codec_client_test.cc index 1aa0dc589572..3a376880f3cd 100644 --- a/test/common/http/codec_client_test.cc +++ b/test/common/http/codec_client_test.cc @@ -179,7 +179,8 @@ class CodecNetworkTest : public testing::TestWithParamcreateListener(socket_, listener_callbacks_, true, false); + upstream_listener_ = + dispatcher_->createListener(socket_, listener_callbacks_, true, false, false); Network::ClientConnectionPtr client_connection = dispatcher_->createClientConnection( socket_.localAddress(), source_address_, Network::Test::createRawBufferSocket(), nullptr); client_connection_ = client_connection.get(); diff --git a/test/common/network/connection_impl_test.cc b/test/common/network/connection_impl_test.cc index 1fdea7b15c79..ac1bedd1c27b 100644 --- a/test/common/network/connection_impl_test.cc +++ b/test/common/network/connection_impl_test.cc @@ -82,7 +82,7 @@ class ConnectionImplTest : public testing::TestWithParam { if (dispatcher_.get() == nullptr) { dispatcher_.reset(new Event::DispatcherImpl); } - listener_ = dispatcher_->createListener(socket_, listener_callbacks_, true, false); + listener_ = dispatcher_->createListener(socket_, listener_callbacks_, true, false, false); client_connection_ = dispatcher_->createClientConnection( socket_.localAddress(), source_address_, Network::Test::createRawBufferSocket(), nullptr); @@ -765,7 +765,7 @@ TEST_P(ConnectionImplTest, BindFailureTest) { new Network::Address::Ipv6Instance(address_string, 0)}; } dispatcher_.reset(new Event::DispatcherImpl); - listener_ = dispatcher_->createListener(socket_, listener_callbacks_, true, false); + listener_ = dispatcher_->createListener(socket_, listener_callbacks_, true, false, false); client_connection_ = dispatcher_->createClientConnection( socket_.localAddress(), source_address_, Network::Test::createRawBufferSocket(), nullptr); @@ -1159,7 +1159,7 @@ class ReadBufferLimitTest : public ConnectionImplTest { void readBufferLimitTest(uint32_t read_buffer_limit, uint32_t expected_chunk_size) { const uint32_t buffer_size = 256 * 1024; dispatcher_.reset(new Event::DispatcherImpl); - listener_ = dispatcher_->createListener(socket_, listener_callbacks_, true, false); + listener_ = dispatcher_->createListener(socket_, listener_callbacks_, true, false, false); client_connection_ = dispatcher_->createClientConnection( socket_.localAddress(), Network::Address::InstanceConstSharedPtr(), diff --git a/test/common/network/dns_impl_test.cc b/test/common/network/dns_impl_test.cc index fe0cf9ad2cc3..d8a42f6b5833 100644 --- a/test/common/network/dns_impl_test.cc +++ b/test/common/network/dns_impl_test.cc @@ -350,7 +350,7 @@ class DnsImplTest : public testing::TestWithParam { server_.reset(new TestDnsServer(dispatcher_)); socket_.reset( new Network::TcpListenSocket(Network::Test::getCanonicalLoopbackAddress(GetParam()), true)); - listener_ = dispatcher_.createListener(*socket_, *server_, true, false); + listener_ = dispatcher_.createListener(*socket_, *server_, true, false, false); // Point c-ares at the listener with no search domains and TCP-only. peer_.reset(new DnsResolverImplPeer(dynamic_cast(resolver_.get()))); diff --git a/test/common/network/listener_impl_test.cc b/test/common/network/listener_impl_test.cc index 2b01c6186abf..ad2cd5a052b9 100644 --- a/test/common/network/listener_impl_test.cc +++ b/test/common/network/listener_impl_test.cc @@ -28,7 +28,7 @@ static void errorCallbackTest(Address::IpVersion version) { Network::MockListenerCallbacks listener_callbacks; Network::MockConnectionHandler connection_handler; Network::ListenerPtr listener = - dispatcher.createListener(socket, listener_callbacks, true, false); + dispatcher.createListener(socket, listener_callbacks, true, false, false); Network::ClientConnectionPtr client_connection = dispatcher.createClientConnection( socket.localAddress(), Network::Address::InstanceConstSharedPtr(), @@ -62,8 +62,9 @@ TEST_P(ListenerImplDeathTest, ErrorCallback) { class TestListenerImpl : public ListenerImpl { public: TestListenerImpl(Event::DispatcherImpl& dispatcher, Socket& socket, ListenerCallbacks& cb, - bool bind_to_port, bool hand_off_restored_destination_connections) - : ListenerImpl(dispatcher, socket, cb, bind_to_port, + bool bind_to_port, bool enable_tcp_fast_open, + bool hand_off_restored_destination_connections) + : ListenerImpl(dispatcher, socket, cb, bind_to_port, enable_tcp_fast_open, hand_off_restored_destination_connections) {} MOCK_METHOD1(getLocalAddress, Address::InstanceConstSharedPtr(int fd)); @@ -90,9 +91,10 @@ TEST_P(ListenerImplTest, UseActualDst) { Network::MockListenerCallbacks listener_callbacks1; Network::MockConnectionHandler connection_handler; // Do not redirect since use_original_dst is false. - Network::TestListenerImpl listener(dispatcher, socket, listener_callbacks1, true, true); + Network::TestListenerImpl listener(dispatcher, socket, listener_callbacks1, true, false, true); Network::MockListenerCallbacks listener_callbacks2; - Network::TestListenerImpl listenerDst(dispatcher, socketDst, listener_callbacks2, false, false); + Network::TestListenerImpl listenerDst(dispatcher, socketDst, listener_callbacks2, false, false, + false); Network::ClientConnectionPtr client_connection = dispatcher.createClientConnection( socket.localAddress(), Network::Address::InstanceConstSharedPtr(), @@ -126,7 +128,7 @@ TEST_P(ListenerImplTest, WildcardListenerUseActualDst) { Network::MockListenerCallbacks listener_callbacks; Network::MockConnectionHandler connection_handler; // Do not redirect since use_original_dst is false. - Network::TestListenerImpl listener(dispatcher, socket, listener_callbacks, true, true); + Network::TestListenerImpl listener(dispatcher, socket, listener_callbacks, true, false, true); auto local_dst_address = Network::Utility::getAddressWithPort( *Network::Test::getCanonicalLoopbackAddress(version_), socket.localAddress()->ip()->port()); @@ -168,7 +170,7 @@ TEST_P(ListenerImplTest, WildcardListenerIpv4Compat) { ASSERT_TRUE(socket.localAddress()->ip()->isAnyAddress()); // Do not redirect since use_original_dst is false. - Network::TestListenerImpl listener(dispatcher, socket, listener_callbacks, true, true); + Network::TestListenerImpl listener(dispatcher, socket, listener_callbacks, true, false, true); auto listener_address = Network::Utility::getAddressWithPort( *Network::Test::getCanonicalLoopbackAddress(version_), socket.localAddress()->ip()->port()); diff --git a/test/common/network/proxy_protocol_test.cc b/test/common/network/proxy_protocol_test.cc index d0b179a48c18..d235e0c106da 100644 --- a/test/common/network/proxy_protocol_test.cc +++ b/test/common/network/proxy_protocol_test.cc @@ -56,6 +56,7 @@ class ProxyProtocolTest : public testing::TestWithParam, return transport_socket_factory_; } bool bindToPort() override { return true; } + bool enableTcpFastOpen() override { return false; } bool handOffRestoredDestinationConnections() const override { return false; } uint32_t perConnectionBufferLimitBytes() override { return 0; } Stats::Scope& listenerScope() override { return stats_store_; } @@ -348,6 +349,7 @@ class WildcardProxyProtocolTest : public testing::TestWithParam callbacks; Network::MockConnectionHandler connection_handler; - Network::ListenerPtr listener = dispatcher.createListener(socket, callbacks, true, false); + Network::ListenerPtr listener = dispatcher.createListener(socket, callbacks, true, false, false); ClientContextConfigImpl client_ctx_config(client_ctx_proto); ClientSslSocketFactory client_ssl_socket_factory(client_ctx_config, manager, stats_store); @@ -738,7 +738,7 @@ TEST_P(SslSocketTest, FlushCloseDuringHandshake) { Network::TcpListenSocket socket(Network::Test::getCanonicalLoopbackAddress(GetParam()), true); Network::MockListenerCallbacks callbacks; Network::MockConnectionHandler connection_handler; - Network::ListenerPtr listener = dispatcher.createListener(socket, callbacks, true, false); + Network::ListenerPtr listener = dispatcher.createListener(socket, callbacks, true, false, false); Network::ClientConnectionPtr client_connection = dispatcher.createClientConnection( socket.localAddress(), Network::Address::InstanceConstSharedPtr(), @@ -796,7 +796,7 @@ TEST_P(SslSocketTest, HalfClose) { Network::MockListenerCallbacks listener_callbacks; Network::MockConnectionHandler connection_handler; Network::ListenerPtr listener = - dispatcher.createListener(socket, listener_callbacks, true, false); + dispatcher.createListener(socket, listener_callbacks, true, false, false); std::shared_ptr server_read_filter(new Network::MockReadFilter()); std::shared_ptr client_read_filter(new Network::MockReadFilter()); @@ -877,7 +877,7 @@ TEST_P(SslSocketTest, ClientAuthMultipleCAs) { Network::TcpListenSocket socket(Network::Test::getCanonicalLoopbackAddress(GetParam()), true); Network::MockListenerCallbacks callbacks; Network::MockConnectionHandler connection_handler; - Network::ListenerPtr listener = dispatcher.createListener(socket, callbacks, true, false); + Network::ListenerPtr listener = dispatcher.createListener(socket, callbacks, true, false, false); std::string client_ctx_json = R"EOF( { @@ -958,8 +958,10 @@ void testTicketSessionResumption(const std::string& server_ctx_json1, Network::TcpListenSocket socket2(Network::Test::getCanonicalLoopbackAddress(ip_version), true); NiceMock callbacks; Network::MockConnectionHandler connection_handler; - Network::ListenerPtr listener1 = dispatcher.createListener(socket1, callbacks, true, false); - Network::ListenerPtr listener2 = dispatcher.createListener(socket2, callbacks, true, false); + Network::ListenerPtr listener1 = + dispatcher.createListener(socket1, callbacks, true, false, false); + Network::ListenerPtr listener2 = + dispatcher.createListener(socket2, callbacks, true, false, false); Json::ObjectSharedPtr client_ctx_loader = TestEnvironment::jsonLoadFromString(client_ctx_json); ClientContextConfigImpl client_ctx_config(*client_ctx_loader); @@ -1280,8 +1282,9 @@ TEST_P(SslSocketTest, ClientAuthCrossListenerSessionResumption) { Network::TcpListenSocket socket2(Network::Test::getCanonicalLoopbackAddress(GetParam()), true); Network::MockListenerCallbacks callbacks; Network::MockConnectionHandler connection_handler; - Network::ListenerPtr listener = dispatcher.createListener(socket, callbacks, true, false); - Network::ListenerPtr listener2 = dispatcher.createListener(socket2, callbacks, true, false); + Network::ListenerPtr listener = dispatcher.createListener(socket, callbacks, true, false, false); + Network::ListenerPtr listener2 = + dispatcher.createListener(socket2, callbacks, true, false, false); std::string client_ctx_json = R"EOF( { @@ -1386,7 +1389,7 @@ TEST_P(SslSocketTest, SslError) { Network::TcpListenSocket socket(Network::Test::getCanonicalLoopbackAddress(GetParam()), true); Network::MockListenerCallbacks callbacks; Network::MockConnectionHandler connection_handler; - Network::ListenerPtr listener = dispatcher.createListener(socket, callbacks, true, false); + Network::ListenerPtr listener = dispatcher.createListener(socket, callbacks, true, false, false); Network::ClientConnectionPtr client_connection = dispatcher.createClientConnection( socket.localAddress(), Network::Address::InstanceConstSharedPtr(), @@ -2021,7 +2024,7 @@ class SslReadBufferLimitTest : public SslCertsTest, server_ssl_socket_factory_.reset( new ServerSslSocketFactory(*server_ctx_config_, "", {}, true, *manager_, stats_store_)); - listener_ = dispatcher_->createListener(socket_, listener_callbacks_, true, false); + listener_ = dispatcher_->createListener(socket_, listener_callbacks_, true, false, false); client_ctx_loader_ = TestEnvironment::jsonLoadFromString(client_ctx_json_); client_ctx_config_.reset(new ClientContextConfigImpl(*client_ctx_loader_)); diff --git a/test/integration/fake_upstream.h b/test/integration/fake_upstream.h index bf9e59be4f99..4b260a53ed46 100644 --- a/test/integration/fake_upstream.h +++ b/test/integration/fake_upstream.h @@ -331,6 +331,7 @@ class FakeUpstream : Logger::Loggable, public Network::Filt return *parent_.transport_socket_factory_; } bool bindToPort() override { return true; } + bool enableTcpFastOpen() override { return false; } bool handOffRestoredDestinationConnections() const override { return false; } uint32_t perConnectionBufferLimitBytes() override { return 0; } Stats::Scope& listenerScope() override { return parent_.stats_store_; } diff --git a/test/mocks/event/mocks.h b/test/mocks/event/mocks.h index bf21591b80ba..809ff775e86a 100644 --- a/test/mocks/event/mocks.h +++ b/test/mocks/event/mocks.h @@ -54,10 +54,10 @@ class MockDispatcher : public Dispatcher { } Network::ListenerPtr createListener(Network::Socket& socket, Network::ListenerCallbacks& cb, - bool bind_to_port, + bool bind_to_port, bool enable_tcp_fast_open, bool hand_off_restored_destination_connections) override { - return Network::ListenerPtr{ - createListener_(socket, cb, bind_to_port, hand_off_restored_destination_connections)}; + return Network::ListenerPtr{createListener_(socket, cb, bind_to_port, enable_tcp_fast_open, + hand_off_restored_destination_connections)}; } TimerPtr createTimer(TimerCb cb) override { return TimerPtr{createTimer_(cb)}; } @@ -90,9 +90,9 @@ class MockDispatcher : public Dispatcher { MOCK_METHOD4(createFileEvent_, FileEvent*(int fd, FileReadyCb cb, FileTriggerType trigger, uint32_t events)); MOCK_METHOD0(createFilesystemWatcher_, Filesystem::Watcher*()); - MOCK_METHOD4(createListener_, + MOCK_METHOD5(createListener_, Network::Listener*(Network::Socket& socket, Network::ListenerCallbacks& cb, - bool bind_to_port, + bool bind_to_port, bool enable_tcp_fast_open, bool hand_off_restored_destination_connections)); MOCK_METHOD1(createTimer_, Timer*(TimerCb cb)); MOCK_METHOD1(deferredDelete_, void(DeferredDeletablePtr& to_delete)); diff --git a/test/mocks/network/mocks.h b/test/mocks/network/mocks.h index a8a861112d89..446a0df994aa 100644 --- a/test/mocks/network/mocks.h +++ b/test/mocks/network/mocks.h @@ -304,6 +304,7 @@ class MockListenerConfig : public ListenerConfig { MOCK_METHOD0(socket, Socket&()); MOCK_METHOD0(transportSocketFactory, TransportSocketFactory&()); MOCK_METHOD0(bindToPort, bool()); + MOCK_METHOD0(enableTcpFastOpen, bool()); MOCK_CONST_METHOD0(handOffRestoredDestinationConnections, bool()); MOCK_METHOD0(perConnectionBufferLimitBytes, uint32_t()); MOCK_METHOD0(listenerScope, Stats::Scope&()); diff --git a/test/server/connection_handler_test.cc b/test/server/connection_handler_test.cc index e9b95e6c01e5..a5861df0e592 100644 --- a/test/server/connection_handler_test.cc +++ b/test/server/connection_handler_test.cc @@ -30,8 +30,10 @@ class ConnectionHandlerTest : public testing::Test, protected Logger::Loggable { public: TestListener(ConnectionHandlerTest& parent, uint64_t tag, bool bind_to_port, - bool hand_off_restored_destination_connections, const std::string& name) + bool enable_tcp_fast_open, bool hand_off_restored_destination_connections, + const std::string& name) : parent_(parent), tag_(tag), bind_to_port_(bind_to_port), + enable_tcp_fast_open_(enable_tcp_fast_open), hand_off_restored_destination_connections_(hand_off_restored_destination_connections), name_(name) {} @@ -41,6 +43,7 @@ class ConnectionHandlerTest : public testing::Test, protected Logger::Loggable TestListenerPtr; - TestListener* addListener(uint64_t tag, bool bind_to_port, + TestListener* addListener(uint64_t tag, bool bind_to_port, bool enable_tcp_fast_open, bool hand_off_restored_destination_connections, const std::string& name) { - TestListener* listener = - new TestListener(*this, tag, bind_to_port, hand_off_restored_destination_connections, name); + TestListener* listener = new TestListener(*this, tag, bind_to_port, enable_tcp_fast_open, + hand_off_restored_destination_connections, name); listener->moveIntoListBack(TestListenerPtr{listener}, listeners_); return listener; } @@ -81,14 +85,14 @@ TEST_F(ConnectionHandlerTest, RemoveListener) { Network::MockListener* listener = new NiceMock(); Network::ListenerCallbacks* listener_callbacks; - EXPECT_CALL(dispatcher_, createListener_(_, _, _, false)) - .WillOnce(Invoke( - [&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool) -> Network::Listener* { - listener_callbacks = &cb; - return listener; - - })); - TestListener* test_listener = addListener(1, true, false, "test_listener"); + EXPECT_CALL(dispatcher_, createListener_(_, _, _, _, false)) + .WillOnce(Invoke([&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool, + bool) -> Network::Listener* { + listener_callbacks = &cb; + return listener; + + })); + TestListener* test_listener = addListener(1, true, false, false, "test_listener"); EXPECT_CALL(test_listener->socket_, localAddress()); handler_->addListener(*test_listener); @@ -119,14 +123,14 @@ TEST_F(ConnectionHandlerTest, DestroyCloseConnections) { Network::MockListener* listener = new NiceMock(); Network::ListenerCallbacks* listener_callbacks; - EXPECT_CALL(dispatcher_, createListener_(_, _, _, _)) - .WillOnce(Invoke( - [&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool) -> Network::Listener* { - listener_callbacks = &cb; - return listener; - - })); - TestListener* test_listener = addListener(1, true, false, "test_listener"); + EXPECT_CALL(dispatcher_, createListener_(_, _, _, _, _)) + .WillOnce(Invoke([&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool, + bool) -> Network::Listener* { + listener_callbacks = &cb; + return listener; + + })); + TestListener* test_listener = addListener(1, true, false, false, "test_listener"); EXPECT_CALL(test_listener->socket_, localAddress()); handler_->addListener(*test_listener); @@ -146,14 +150,14 @@ TEST_F(ConnectionHandlerTest, CloseDuringFilterChainCreate) { Network::MockListener* listener = new Network::MockListener(); Network::ListenerCallbacks* listener_callbacks; - EXPECT_CALL(dispatcher_, createListener_(_, _, _, _)) - .WillOnce(Invoke( - [&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool) -> Network::Listener* { - listener_callbacks = &cb; - return listener; - - })); - TestListener* test_listener = addListener(1, true, false, "test_listener"); + EXPECT_CALL(dispatcher_, createListener_(_, _, _, _, _)) + .WillOnce(Invoke([&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool, + bool) -> Network::Listener* { + listener_callbacks = &cb; + return listener; + + })); + TestListener* test_listener = addListener(1, true, false, false, "test_listener"); EXPECT_CALL(test_listener->socket_, localAddress()); handler_->addListener(*test_listener); @@ -172,14 +176,14 @@ TEST_F(ConnectionHandlerTest, CloseConnectionOnEmptyFilterChain) { Network::MockListener* listener = new Network::MockListener(); Network::ListenerCallbacks* listener_callbacks; - EXPECT_CALL(dispatcher_, createListener_(_, _, _, _)) - .WillOnce(Invoke( - [&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool) -> Network::Listener* { - listener_callbacks = &cb; - return listener; - - })); - TestListener* test_listener = addListener(1, true, false, "test_listener"); + EXPECT_CALL(dispatcher_, createListener_(_, _, _, _, _)) + .WillOnce(Invoke([&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool, + bool) -> Network::Listener* { + listener_callbacks = &cb; + return listener; + + })); + TestListener* test_listener = addListener(1, true, false, false, "test_listener"); EXPECT_CALL(test_listener->socket_, localAddress()); handler_->addListener(*test_listener); @@ -193,28 +197,28 @@ TEST_F(ConnectionHandlerTest, CloseConnectionOnEmptyFilterChain) { } TEST_F(ConnectionHandlerTest, FindListenerByAddress) { - TestListener* test_listener1 = addListener(1, true, true, "test_listener1"); + TestListener* test_listener1 = addListener(1, true, false, true, "test_listener1"); Network::Address::InstanceConstSharedPtr alt_address( new Network::Address::Ipv4Instance("127.0.0.1", 10001)); Network::MockListener* listener = new Network::MockListener(); - EXPECT_CALL(dispatcher_, createListener_(_, _, _, true)) - .WillOnce(Invoke([&](Network::Socket&, Network::ListenerCallbacks&, bool, + EXPECT_CALL(dispatcher_, createListener_(_, _, _, _, true)) + .WillOnce(Invoke([&](Network::Socket&, Network::ListenerCallbacks&, bool, bool, bool) -> Network::Listener* { return listener; })); EXPECT_CALL(test_listener1->socket_, localAddress()).WillRepeatedly(ReturnRef(alt_address)); handler_->addListener(*test_listener1); EXPECT_EQ(listener, handler_->findListenerByAddress(ByRef(*alt_address))); - TestListener* test_listener2 = addListener(2, true, false, "test_listener2"); + TestListener* test_listener2 = addListener(2, true, false, false, "test_listener2"); Network::Address::InstanceConstSharedPtr alt_address2( new Network::Address::Ipv4Instance("0.0.0.0", 10001)); Network::Address::InstanceConstSharedPtr alt_address3( new Network::Address::Ipv4Instance("127.0.0.2", 10001)); Network::MockListener* listener2 = new Network::MockListener(); - EXPECT_CALL(dispatcher_, createListener_(_, _, _, false)) - .WillOnce(Invoke([&](Network::Socket&, Network::ListenerCallbacks&, bool, + EXPECT_CALL(dispatcher_, createListener_(_, _, _, _, false)) + .WillOnce(Invoke([&](Network::Socket&, Network::ListenerCallbacks&, bool, bool, bool) -> Network::Listener* { return listener2; })); EXPECT_CALL(test_listener2->socket_, localAddress()).WillRepeatedly(ReturnRef(alt_address2)); handler_->addListener(*test_listener2); @@ -231,8 +235,8 @@ TEST_F(ConnectionHandlerTest, FindListenerByAddress) { handler_->stopListeners(2); Network::MockListener* listener3 = new Network::MockListener(); - EXPECT_CALL(dispatcher_, createListener_(_, _, _, _)) - .WillOnce(Invoke([&](Network::Socket&, Network::ListenerCallbacks&, bool, + EXPECT_CALL(dispatcher_, createListener_(_, _, _, _, _)) + .WillOnce(Invoke([&](Network::Socket&, Network::ListenerCallbacks&, bool, bool, bool) -> Network::Listener* { return listener3; })); handler_->addListener(*test_listener2); @@ -243,29 +247,29 @@ TEST_F(ConnectionHandlerTest, FindListenerByAddress) { } TEST_F(ConnectionHandlerTest, NormalRedirect) { - TestListener* test_listener1 = addListener(1, true, true, "test_listener1"); + TestListener* test_listener1 = addListener(1, true, false, true, "test_listener1"); Network::MockListener* listener1 = new Network::MockListener(); Network::ListenerCallbacks* listener_callbacks1; - EXPECT_CALL(dispatcher_, createListener_(_, _, _, true)) - .WillOnce(Invoke( - [&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool) -> Network::Listener* { - listener_callbacks1 = &cb; - return listener1; - })); + EXPECT_CALL(dispatcher_, createListener_(_, _, _, _, true)) + .WillOnce(Invoke([&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool, + bool) -> Network::Listener* { + listener_callbacks1 = &cb; + return listener1; + })); Network::Address::InstanceConstSharedPtr normal_address( new Network::Address::Ipv4Instance("127.0.0.1", 10001)); EXPECT_CALL(test_listener1->socket_, localAddress()).WillRepeatedly(ReturnRef(normal_address)); handler_->addListener(*test_listener1); - TestListener* test_listener2 = addListener(1, false, false, "test_listener2"); + TestListener* test_listener2 = addListener(1, false, false, false, "test_listener2"); Network::MockListener* listener2 = new Network::MockListener(); Network::ListenerCallbacks* listener_callbacks2; - EXPECT_CALL(dispatcher_, createListener_(_, _, _, false)) - .WillOnce(Invoke( - [&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool) -> Network::Listener* { - listener_callbacks2 = &cb; - return listener2; - })); + EXPECT_CALL(dispatcher_, createListener_(_, _, _, _, false)) + .WillOnce(Invoke([&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool, + bool) -> Network::Listener* { + listener_callbacks2 = &cb; + return listener2; + })); Network::Address::InstanceConstSharedPtr alt_address( new Network::Address::Ipv4Instance("127.0.0.2", 20002)); EXPECT_CALL(test_listener2->socket_, localAddress()).WillRepeatedly(ReturnRef(alt_address)); @@ -302,29 +306,29 @@ TEST_F(ConnectionHandlerTest, NormalRedirect) { } TEST_F(ConnectionHandlerTest, FallbackToWildcardListener) { - TestListener* test_listener1 = addListener(1, true, true, "test_listener1"); + TestListener* test_listener1 = addListener(1, true, false, true, "test_listener1"); Network::MockListener* listener1 = new Network::MockListener(); Network::ListenerCallbacks* listener_callbacks1; - EXPECT_CALL(dispatcher_, createListener_(_, _, _, true)) - .WillOnce(Invoke( - [&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool) -> Network::Listener* { - listener_callbacks1 = &cb; - return listener1; - })); + EXPECT_CALL(dispatcher_, createListener_(_, _, _, _, true)) + .WillOnce(Invoke([&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool, + bool) -> Network::Listener* { + listener_callbacks1 = &cb; + return listener1; + })); Network::Address::InstanceConstSharedPtr normal_address( new Network::Address::Ipv4Instance("127.0.0.1", 10001)); EXPECT_CALL(test_listener1->socket_, localAddress()).WillRepeatedly(ReturnRef(normal_address)); handler_->addListener(*test_listener1); - TestListener* test_listener2 = addListener(1, false, false, "test_listener2"); + TestListener* test_listener2 = addListener(1, false, false, false, "test_listener2"); Network::MockListener* listener2 = new Network::MockListener(); Network::ListenerCallbacks* listener_callbacks2; - EXPECT_CALL(dispatcher_, createListener_(_, _, _, false)) - .WillOnce(Invoke( - [&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool) -> Network::Listener* { - listener_callbacks2 = &cb; - return listener2; - })); + EXPECT_CALL(dispatcher_, createListener_(_, _, _, _, false)) + .WillOnce(Invoke([&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool, + bool) -> Network::Listener* { + listener_callbacks2 = &cb; + return listener2; + })); Network::Address::InstanceConstSharedPtr any_address = Network::Utility::getIpv4AnyAddress(); EXPECT_CALL(test_listener2->socket_, localAddress()).WillRepeatedly(ReturnRef(any_address)); handler_->addListener(*test_listener2); @@ -363,15 +367,15 @@ TEST_F(ConnectionHandlerTest, FallbackToWildcardListener) { } TEST_F(ConnectionHandlerTest, WildcardListenerWithOriginalDst) { - TestListener* test_listener1 = addListener(1, true, true, "test_listener1"); + TestListener* test_listener1 = addListener(1, true, false, true, "test_listener1"); Network::MockListener* listener1 = new Network::MockListener(); Network::ListenerCallbacks* listener_callbacks1; - EXPECT_CALL(dispatcher_, createListener_(_, _, _, true)) - .WillOnce(Invoke( - [&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool) -> Network::Listener* { - listener_callbacks1 = &cb; - return listener1; - })); + EXPECT_CALL(dispatcher_, createListener_(_, _, _, _, true)) + .WillOnce(Invoke([&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool, + bool) -> Network::Listener* { + listener_callbacks1 = &cb; + return listener1; + })); Network::Address::InstanceConstSharedPtr normal_address( new Network::Address::Ipv4Instance("127.0.0.1", 80)); // Original dst address nor port number match that of the listener's address. @@ -408,15 +412,15 @@ TEST_F(ConnectionHandlerTest, WildcardListenerWithOriginalDst) { } TEST_F(ConnectionHandlerTest, WildcardListenerWithNoOriginalDst) { - TestListener* test_listener1 = addListener(1, true, true, "test_listener1"); + TestListener* test_listener1 = addListener(1, true, false, true, "test_listener1"); Network::MockListener* listener1 = new Network::MockListener(); Network::ListenerCallbacks* listener_callbacks1; - EXPECT_CALL(dispatcher_, createListener_(_, _, _, true)) - .WillOnce(Invoke( - [&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool) -> Network::Listener* { - listener_callbacks1 = &cb; - return listener1; - })); + EXPECT_CALL(dispatcher_, createListener_(_, _, _, _, true)) + .WillOnce(Invoke([&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool, + bool) -> Network::Listener* { + listener_callbacks1 = &cb; + return listener1; + })); Network::Address::InstanceConstSharedPtr normal_address( new Network::Address::Ipv4Instance("127.0.0.1", 80)); Network::Address::InstanceConstSharedPtr any_address = Network::Utility::getAddressWithPort(