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
2 changes: 1 addition & 1 deletion ci/build_setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ fi
cp -f "${ENVOY_SRCDIR}"/ci/WORKSPACE.filter.example "${ENVOY_FILTER_EXAMPLE_SRCDIR}"/WORKSPACE

# This is the hash on https://github.com/lyft/envoy-filter-example.git we pin to.
(cd "${ENVOY_FILTER_EXAMPLE_SRCDIR}" && git checkout 9f006f6be519007e9be3b29ad531b8e8be5a18d6)
(cd "${ENVOY_FILTER_EXAMPLE_SRCDIR}" && git fetch origin && git checkout 03f5353c939b0d796925c67d94db52e8055ee732)

# Also setup some space for building Envoy standalone.
export ENVOY_BUILD_DIR="${BUILD_DIR}"/envoy
Expand Down
34 changes: 28 additions & 6 deletions source/common/network/utility.cc
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,11 @@ uint32_t Utility::portFromTcpUrl(const std::string& url) {
}
}

Address::InstanceConstSharedPtr Utility::getLocalAddress() {
// TODO(hennna): Currently getLocalAddress does not support choosing between
// multiple interfaces and addresses not returned by getifaddrs. In additon,
// the default is to return a loopback address of type version. This function may
// need to be updated in the future. Discussion can be found at Github issue #939.
Address::InstanceConstSharedPtr Utility::getLocalAddress(const Address::IpVersion version) {
struct ifaddrs* ifaddr;
struct ifaddrs* ifa;
Address::InstanceConstSharedPtr ret;
Expand All @@ -144,10 +148,13 @@ Address::InstanceConstSharedPtr Utility::getLocalAddress() {
continue;
}

if (ifa->ifa_addr->sa_family == AF_INET) {
sockaddr_in* addr = reinterpret_cast<sockaddr_in*>(ifa->ifa_addr);
if (htonl(INADDR_LOOPBACK) != addr->sin_addr.s_addr) {
ret.reset(new Address::Ipv4Instance(addr));
if ((ifa->ifa_addr->sa_family == AF_INET && version == Address::IpVersion::v4) ||
(ifa->ifa_addr->sa_family == AF_INET6 && version == Address::IpVersion::v6)) {
const struct sockaddr_storage* addr =
reinterpret_cast<const struct sockaddr_storage*>(ifa->ifa_addr);
ret = Address::addressFromSockAddr(
*addr, (version == Address::IpVersion::v4) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6));
if (!isLoopbackAddress(*ret)) {
break;
}
}
Expand All @@ -157,6 +164,14 @@ Address::InstanceConstSharedPtr Utility::getLocalAddress() {
freeifaddrs(ifaddr);
}

// If the local address is not found above, then return the loopback addresss by default.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you add a reference to #939?

if (ret == nullptr) {
if (version == Address::IpVersion::v4) {
ret.reset(new Address::Ipv4Instance("127.0.0.1"));
} else if (version == Address::IpVersion::v6) {
ret.reset(new Address::Ipv6Instance("::1"));
}
}
return ret;
}

Expand All @@ -183,7 +198,14 @@ bool Utility::isLoopbackAddress(const Address::Instance& address) {
return false;
}

return address.ip()->ipv4()->address() == htonl(INADDR_LOOPBACK);
if (address.ip()->version() == Address::IpVersion::v4) {
// Compare to the canonical v4 loopback address: 127.0.0.1.
return address.ip()->ipv4()->address() == htonl(INADDR_LOOPBACK);
} else if (address.ip()->version() == Address::IpVersion::v6) {
std::array<uint8_t, 16> addr = address.ip()->ipv6()->address();
return 0 == memcmp(&addr, &in6addr_loopback, sizeof(in6addr_loopback));
}
NOT_IMPLEMENTED;
}

Address::InstanceConstSharedPtr Utility::getCanonicalIpv4LoopbackAddress() {
Expand Down
7 changes: 6 additions & 1 deletion source/common/network/utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,13 @@ class Utility {
static uint32_t portFromTcpUrl(const std::string& url);

/**
* Get the local address of the first interface address that is of type
* version and is not a loopback address. If no matches are found, return the
* loopback address of type version.
* @param the local address IP version.
* @return the local IP address of the server
*/
static Address::InstanceConstSharedPtr getLocalAddress();
static Address::InstanceConstSharedPtr getLocalAddress(const Address::IpVersion version);

/**
* Determine whether this is an internal (RFC1918) address.
Expand All @@ -91,6 +95,7 @@ class Utility {

/**
* Check if address is loopback address.
* @param address IP address to check.
* @return true if so, otherwise false
*/
static bool isLoopbackAddress(const Address::Instance& address);
Expand Down
6 changes: 4 additions & 2 deletions source/exe/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ int main(int argc, char** argv) {
DefaultTestHooks default_test_hooks;
Stats::ThreadLocalStoreImpl stats_store(*restarter);
Server::ProdComponentFactory component_factory;
LocalInfo::LocalInfoImpl local_info(Network::Utility::getLocalAddress(), options.serviceZone(),
options.serviceClusterName(), options.serviceNodeName());
// TODO(henna): Add CLI option for local address IP version.
LocalInfo::LocalInfoImpl local_info(
Network::Utility::getLocalAddress(Network::Address::IpVersion::v4), options.serviceZone(),
options.serviceClusterName(), options.serviceNodeName());
Server::InstanceImpl server(options, default_test_hooks, *restarter, stats_store,
restarter->accessLogLock(), component_factory, local_info);
server.run();
Expand Down
4 changes: 0 additions & 4 deletions source/server/server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,6 @@ InstanceImpl::InstanceImpl(Options& options, TestHooks& hooks, HotRestart& resta
}
server_stats_.version_.set(version_int);

if (!local_info_.address()) {
throw EnvoyException("could not resolve local address");
}

restarter_.initialize(handler_.dispatcher(), *this);
drain_manager_ = component_factory.createDrainManager(*this);

Expand Down
1 change: 1 addition & 0 deletions test/common/network/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -138,5 +138,6 @@ envoy_cc_test(
"//source/common/json:json_loader_lib",
"//source/common/network:address_lib",
"//source/common/network:utility_lib",
"//test/test_common:environment_lib",
],
)
2 changes: 1 addition & 1 deletion test/common/network/address_impl_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ void testSocketBindAndConnect(const std::string& addr_port_str) {
ScopedFdCloser closer1(listen_fd);

// Check that IPv6 sockets accept IPv6 connections only.
if (addr_port->ip()->ipv6() != nullptr) {
if (addr_port->ip()->version() == IpVersion::v6) {
int v6only = 0;
socklen_t size_int = sizeof(v6only);
ASSERT_GE(::getsockopt(listen_fd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, &size_int), 0);
Expand Down
19 changes: 18 additions & 1 deletion test/common/network/utility_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "common/network/address_impl.h"
#include "common/network/utility.h"

#include "test/test_common/environment.h"

#include "gtest/gtest.h"

namespace Network {
Expand Down Expand Up @@ -147,7 +149,14 @@ TEST(NetworkUtility, resolveUrl) {
EXPECT_EQ("[a:b:c:d::]:0", Utility::resolveUrl("tcp://[a:b:c:d::]:0")->asString());
}

TEST(NetworkUtility, getLocalAddress) { EXPECT_NE(nullptr, Utility::getLocalAddress()); }
class NetworkUtilityGetLocalAddress : public testing::TestWithParam<Address::IpVersion> {};

INSTANTIATE_TEST_CASE_P(IpVersions, NetworkUtilityGetLocalAddress,
testing::ValuesIn(TestEnvironment::getIpVersionsForTest()));

TEST_P(NetworkUtilityGetLocalAddress, getLocalAddress) {
EXPECT_NE(nullptr, Utility::getLocalAddress(GetParam()));
}

TEST(NetworkUtility, getOriginalDst) { EXPECT_EQ(nullptr, Utility::getOriginalDst(-1)); }

Expand All @@ -164,6 +173,14 @@ TEST(NetworkUtility, loopbackAddress) {
Address::PipeInstance address("/foo");
EXPECT_FALSE(Utility::isLoopbackAddress(address));
}
{
Address::Ipv6Instance address("::1");
EXPECT_TRUE(Utility::isLoopbackAddress(address));
}
{
Address::Ipv6Instance address("::");
EXPECT_FALSE(Utility::isLoopbackAddress(address));
}
EXPECT_EQ("127.0.0.1:0", Utility::getCanonicalIpv4LoopbackAddress()->asString());
EXPECT_EQ("[::1]:0", Utility::getIpv6LoopbackAddress()->asString());
}
Expand Down
1 change: 1 addition & 0 deletions test/config/integration/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ load(
envoy_package()

exports_files([
"echo_server.json",
"server.json",
"server_http2.json",
"server_http2_upstream.json",
Expand Down
27 changes: 27 additions & 0 deletions test/config/integration/echo_server.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Since you are moving this test into a standalone config, is there any reason to leave the echo listener in the other config? Seems like that should be removed?

"listeners": [
{
"address": "tcp://{{ ip_loopback_address }}:0",
"use_original_dst": true,
"filters": [
{ "type": "read", "name": "ratelimit",
"config": {
"domain": "foo",
"descriptors": [[{"key": "foo", "value": "bar"}]],
"stat_prefix": "name"
}
},
{ "type": "read", "name": "echo", "config": {} }
]
}],

"admin": {
"access_log_path": "/dev/null",
"profile_path": "{{ test_tmpdir }}/envoy.prof",
"address": "tcp://{{ ip_loopback_address }}:0"
},

"cluster_manager": {
"clusters": []
}
}
14 changes: 0 additions & 14 deletions test/config/integration/server.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,5 @@
{
"listeners": [
{
"address": "tcp://127.0.0.1:0",
"use_original_dst": true,
"filters": [
{ "type": "read", "name": "ratelimit",
"config": {
"domain": "foo",
"descriptors": [[{"key": "foo", "value": "bar"}]],
"stat_prefix": "name"
}
},
{ "type": "read", "name": "echo", "config": {} }
]
},
{
"address": "tcp://127.0.0.1:0",
"filters": [
Expand Down
14 changes: 14 additions & 0 deletions test/integration/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ envoy_cc_test_library(
"//source/server/http:health_check_lib",
"//test/mocks/upstream:upstream_mocks",
"//test/test_common:environment_lib",
"//test/test_common:network_utility_lib",
"//test/test_common:utility_lib",
],
)
Expand All @@ -161,6 +162,19 @@ envoy_cc_test(
],
)

envoy_cc_test(
name = "echo_integration_test",
srcs = [
"echo_integration_test.cc",
],
data = [
"//test/config/integration:echo_server.json",
],
deps = [
":integration_lib",
],
)

envoy_cc_test(
name = "proxy_proto_integration_test",
srcs = [
Expand Down
42 changes: 42 additions & 0 deletions test/integration/echo_integration_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include "test/integration/integration.h"
#include "test/integration/utility.h"

class EchoIntegrationTest : public BaseIntegrationTest,
public testing::TestWithParam<Network::Address::IpVersion> {
public:
/**
* Initializer for an individual test.
*/
void SetUp() override {
fake_upstreams_.emplace_back(new FakeUpstream(GetParam(), 0, FakeHttpConnection::Type::HTTP1));
registerPort("upstream_0", fake_upstreams_.back()->localAddress()->ip()->port());
fake_upstreams_.emplace_back(new FakeUpstream(GetParam(), 0, FakeHttpConnection::Type::HTTP1));
registerPort("upstream_1", fake_upstreams_.back()->localAddress()->ip()->port());
createTestServer("test/config/integration/echo_server.json", GetParam(), {"echo"});
}

/**
* Destructor for an individual test.
*/
void TearDown() override {
test_server_.reset();
fake_upstreams_.clear();
}
};

INSTANTIATE_TEST_CASE_P(IpVersions, EchoIntegrationTest,
testing::ValuesIn(TestEnvironment::getIpVersionsForTest()));

TEST_P(EchoIntegrationTest, Hello) {
Buffer::OwnedImpl buffer("hello");
std::string response;
RawConnectionDriver connection(lookupPort("echo"), GetParam(), buffer,
[&](Network::ClientConnection&, const Buffer::Instance& data)
-> void {
response.append(TestUtility::bufferToString(data));
connection.close();
});

connection.run();
EXPECT_EQ("hello", response);
}
19 changes: 19 additions & 0 deletions test/integration/fake_upstream.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
#include "common/http/http2/codec_impl.h"
#include "common/network/address_impl.h"
#include "common/network/listen_socket_impl.h"
#include "common/network/utility.h"

#include "test/test_common/network_utility.h"
#include "test/test_common/printers.h"
#include "test/test_common/utility.h"

Expand Down Expand Up @@ -195,17 +197,34 @@ FakeUpstream::FakeUpstream(const std::string& uds_path, FakeHttpConnection::Type
log().info("starting fake server on unix domain socket {}", uds_path);
}

// TODO(henna): Deprecate when IPv6 test support is finished.
static Network::ListenSocketPtr makeTcpListenSocket(uint32_t port) {
auto addr =
Network::Address::InstanceConstSharedPtr{new Network::Address::Ipv4Instance("0.0.0.0", port)};
return Network::ListenSocketPtr{new Network::TcpListenSocket(addr, true)};
}

static Network::ListenSocketPtr makeTcpListenSocket(const Network::Address::IpVersion version,
uint32_t port) {
return Network::ListenSocketPtr{new Network::TcpListenSocket(
Network::Address::parseInternetAddressAndPort(
fmt::format("{}:{}", Network::Test::getAnyAddressUrlString(version), port)),
true)};
}

// TODO(henna): Deprecate when IPv6 test support is finished.
FakeUpstream::FakeUpstream(uint32_t port, FakeHttpConnection::Type type)
: FakeUpstream(nullptr, makeTcpListenSocket(port), type) {
log().info("starting fake server on port {}", this->localAddress()->ip()->port());
}

FakeUpstream::FakeUpstream(Network::Address::IpVersion version, uint32_t port,
FakeHttpConnection::Type type)
: FakeUpstream(nullptr, makeTcpListenSocket(version, port), type) {
log().info("starting fake server on port {}. Address version is {}",
this->localAddress()->ip()->port(), Network::Test::addressVersionAsString(version));
}

FakeUpstream::FakeUpstream(Ssl::ServerContext* ssl_ctx, uint32_t port,
FakeHttpConnection::Type type)
: FakeUpstream(ssl_ctx, makeTcpListenSocket(port), type) {
Expand Down
2 changes: 2 additions & 0 deletions test/integration/fake_upstream.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ class FakeUpstream : Logger::Loggable<Logger::Id::testing>, public Network::Filt
public:
FakeUpstream(const std::string& uds_path, FakeHttpConnection::Type type);
FakeUpstream(uint32_t port, FakeHttpConnection::Type type);
FakeUpstream(const Network::Address::IpVersion version, uint32_t port,
FakeHttpConnection::Type type);
FakeUpstream(Ssl::ServerContext* ssl_ctx, uint32_t port, FakeHttpConnection::Type type);
~FakeUpstream();

Expand Down
8 changes: 5 additions & 3 deletions test/integration/hotrestart_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ set -e

[[ -z "${ENVOY_BIN}" ]] && ENVOY_BIN="${TEST_RUNDIR}"/source/exe/envoy-static

# TODO(htuch): Clean this up when Bazelifying the hot restart test below. At the same time, restore
# some test behavior lost in #650, when we switched to 0 port binding - the hot restart tests no
# longer check socket passing. See #654.
# TODO(htuch): In this test script, we are duplicating work done in test_environment.cc via sed.
# Instead, we can add a simple C++ binary that links against test_environment.cc and uses the
# substitution methods provided there.
# TODO(henna): Parameterize IPv4 and IPv6 testing.
HOT_RESTART_JSON="${TEST_TMPDIR}"/hot_restart.json
cat "${TEST_RUNDIR}"/test/config/integration/server.json |
sed -e "s#{{ upstream_. }}#0#g" | \
sed -e "s#{{ test_rundir }}#$TEST_RUNDIR#" | \
sed -e "s#{{ ip_loopback_address }}#127.0.0.1#" | \
cat > "${HOT_RESTART_JSON}"

# Now start the real server, hot restart it twice, and shut it all down as a basic hot restart
Expand Down
8 changes: 4 additions & 4 deletions test/integration/http2_integration_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
class Http2IntegrationTest : public BaseIntegrationTest, public testing::Test {
public:
/**
* Global initializer for all integration tests.
* Initializer for an individual test.
*/
static void SetUpTestCase() {
void SetUp() override {
fake_upstreams_.emplace_back(new FakeUpstream(0, FakeHttpConnection::Type::HTTP1));
registerPort("upstream_0", fake_upstreams_.back()->localAddress()->ip()->port());
fake_upstreams_.emplace_back(new FakeUpstream(0, FakeHttpConnection::Type::HTTP1));
Expand All @@ -18,9 +18,9 @@ class Http2IntegrationTest : public BaseIntegrationTest, public testing::Test {
}

/**
* Global destructor for all integration tests.
* Destructor for an individual test test.
*/
static void TearDownTestCase() {
void TearDown() override {
test_server_.reset();
fake_upstreams_.clear();
}
Expand Down
Loading