Skip to content

Commit

Permalink
listener: Add support for LDS API "transparent" option.
Browse files Browse the repository at this point in the history
Insert a Listener Socket Option if "transparent" option is requested.

Signed-off-by: Jarno Rajahalme <[email protected]>
  • Loading branch information
jrajahalme committed Mar 14, 2018
1 parent 3495654 commit 1b58b6f
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 1 deletion.
2 changes: 1 addition & 1 deletion bazel/repository_locations.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "4702452e358190a1444c7bb6dc256285de1f63f9",
remote = "https://github.com/envoyproxy/data-plane-api",
),
grpc_httpjson_transcoding = dict(
Expand Down
36 changes: 36 additions & 0 deletions source/server/listener_manager_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,36 @@ ProdListenerComponentFactory::createDrainManager(envoy::api::v2::Listener::Drain
return DrainManagerPtr{new DrainManagerImpl(server_, drain_type)};
}

// Socket::Option implementation for API-defined listener socket options.
// This same object can be extended to handle additional listener socket options.
class ListenerSocketOption : public Network::Socket::Option, Logger::Loggable<Logger::Id::config> {
public:
ListenerSocketOption(bool transparent) : transparent_(transparent) {}

// Network::Socket::Option
bool setOption(Network::Socket& socket, bool pre_bind) const override {
// IP_TRANSPARENT makes a difference only for the following bind(). Set it before the bind
// and ignore it after.
if (transparent_ && pre_bind) {
#ifdef SOL_IP
int on = 1;
if (setsockopt(socket.fd(), SOL_IP, IP_TRANSPARENT, &on, sizeof(on)) == -1) {
ENVOY_LOG(warn, "Setting IP_TRANSPARENT on listener socket failed: {}", strerror(errno));
throw EnvoyException("ListenSocketOption: Error setting IP_TRANSPARENT socket option");
}
#else
UNREFERENCED_PARAMETER(socket);
throw EnvoyException("ListenSocketOption: Error setting IP_TRANSPARENT socket option");
#endif
}
return true;
}
void hashKey(std::vector<uint8_t>&) const override{}; // Not used for listener sockets.

private:
bool transparent_;
};

ListenerImpl::ListenerImpl(const envoy::api::v2::Listener& config, ListenerManagerImpl& parent,
const std::string& name, bool modifiable, bool workers_started,
uint64_t hash)
Expand All @@ -126,6 +156,12 @@ ListenerImpl::ListenerImpl(const envoy::api::v2::Listener& config, ListenerManag
// filter chain #1308.
ASSERT(config.filter_chains().size() >= 1);

// Add listen socket options, if any.
bool transparent = config.transparent();
if (transparent) {
setListenSocketOption(std::make_shared<ListenerSocketOption>(transparent));
}

if (!config.listener_filters().empty()) {
listener_filter_factories_ =
parent_.factory_.createListenerFilterFactoryList(config.listener_filters(), *this);
Expand Down
20 changes: 20 additions & 0 deletions test/server/listener_manager_impl_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1391,6 +1391,26 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterOptionFail)
EXPECT_EQ(0U, manager_->listeners().size());
}

TEST_F(ListenerManagerImplWithRealFiltersTest, TransparentListener) {
const std::string yaml = TestEnvironment::substitute(R"EOF(
name: "TransparentListener"
address:
socket_address: { address: 127.0.0.1, port_value: 1111 }
filter_chains:
- filters:
transparent: true
)EOF",
Network::Address::IpVersion::v4);

EXPECT_CALL(listener_factory_, createListenSocket(_, _, true));

// MockListenerSocket is not a real socket, so this always fails in testing.
EXPECT_THROW_WITH_MESSAGE(manager_->addOrUpdateListener(parseListenerFromV2Yaml(yaml), true),
EnvoyException,
"ListenSocketOption: Error setting IP_TRANSPARENT socket option");
EXPECT_EQ(0U, manager_->listeners().size());
}

TEST_F(ListenerManagerImplWithRealFiltersTest, CRLFilename) {
const std::string yaml = TestEnvironment::substitute(R"EOF(
address:
Expand Down

0 comments on commit 1b58b6f

Please sign in to comment.