Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ syntax = "proto3";
package envoy.extensions.common.dynamic_forward_proxy.v3;

import "envoy/config/cluster/v3/cluster.proto";
import "envoy/config/core/v3/address.proto";
import "envoy/config/core/v3/resolver.proto";

import "google/protobuf/duration.proto";
Expand All @@ -29,7 +30,7 @@ message DnsCacheCircuitBreakers {

// Configuration for the dynamic forward proxy DNS cache. See the :ref:`architecture overview
// <arch_overview_http_dynamic_forward_proxy>` for more information.
// [#next-free-field: 10]
// [#next-free-field: 11]
message DnsCacheConfig {
option (udpa.annotations.versioning).previous_message_type =
"envoy.config.common.dynamic_forward_proxy.v2alpha.DnsCacheConfig";
Expand Down Expand Up @@ -108,4 +109,7 @@ message DnsCacheConfig {

// DNS resolution configuration which includes the underlying dns resolver addresses and options.
config.core.v3.DnsResolutionConfig dns_resolution_config = 9;

// Hostnames to pre-load into the cache upon cache creation.
repeated config.core.v3.SocketAddress pre_load_hostnames = 10;
Comment thread
junr03 marked this conversation as resolved.
Outdated
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,25 @@ DnsCacheImpl::DnsCacheImpl(
host_ttl_(PROTOBUF_GET_MS_OR_DEFAULT(config, host_ttl, 300000)),
max_hosts_(PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, max_hosts, 1024)) {
tls_slot_.set([&](Event::Dispatcher&) { return std::make_shared<ThreadLocalHostInfo>(*this); });

// Pre-Loaded hostnames are resolved without a read lock on primary hosts because it is done
Comment thread
junr03 marked this conversation as resolved.
Outdated
// during object construction.
uint pre_loaded_hostnames{};
for (auto it = config.pre_load_hostnames().begin();
it != config.pre_load_hostnames().end() && pre_loaded_hostnames < max_hosts_;
Comment thread
junr03 marked this conversation as resolved.
Outdated
++it, ++pre_loaded_hostnames) {
// No need to get a resolution handle on this resolution as the only outcome needed is for the
// cache to load an entry. Further if this particular resolution fails all the is lost is the
// potential optimization of having the entry be pre-loaded the first time a true consumer of
// this DNS cache asks for it.
main_thread_dispatcher_.post([this, host = it->address(), default_port = it->port_value()]() {
startCacheLoad(host, default_port);
Comment thread
junr03 marked this conversation as resolved.
Outdated
});
}

if (static_cast<size_t>(config.pre_load_hostnames().size()) > max_hosts_) {
stats_.host_overflow_.add(config.pre_load_hostnames().size() - max_hosts_);
}
}

DnsCacheImpl::~DnsCacheImpl() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,15 @@ namespace {

class DnsCacheImplTest : public testing::Test, public Event::TestUsingSimulatedTime {
public:
void initialize() {
void initialize(bool set_pre_load_hostnames = false, uint max_hosts = 1024) {
config_.set_name("foo");
config_.set_dns_lookup_family(envoy::config::cluster::v3::Cluster::V4_ONLY);
config_.mutable_max_hosts()->set_value(max_hosts);
if (set_pre_load_hostnames) {
envoy::config::core::v3::SocketAddress* address = config_.add_pre_load_hostnames();
address->set_address("bar");
address->set_port_value(443);
}

EXPECT_CALL(dispatcher_, isThreadSafe).WillRepeatedly(Return(true));

Expand Down Expand Up @@ -98,6 +104,34 @@ MATCHER_P(CustomDnsResolversSizeEquals, expected_resolvers, "") {
return expected_resolvers.size() == arg.size();
}

TEST_F(DnsCacheImplTest, PreLoadSuccess) {
Network::DnsResolver::ResolveCb resolve_cb;
EXPECT_CALL(*resolver_, resolve("bar", _, _))
.WillOnce(DoAll(SaveArg<2>(&resolve_cb), Return(&resolver_->active_query_)));
EXPECT_CALL(update_callbacks_,
onDnsHostAddOrUpdate("bar", DnsHostInfoEquals("10.0.0.1:443", "bar", false)));

initialize(true /* set_pre_load_hostnames */);

resolve_cb(Network::DnsResolver::ResolutionStatus::Success,
TestUtility::makeDnsResponse({"10.0.0.1"}));
checkStats(1 /* attempt */, 1 /* success */, 0 /* failure */, 1 /* address changed */,
1 /* added */, 0 /* removed */, 1 /* num hosts */);

MockLoadDnsCacheEntryCallbacks callbacks;
auto result = dns_cache_->loadDnsCacheEntry("bar", 80, callbacks);
EXPECT_EQ(DnsCache::LoadDnsCacheEntryStatus::InCache, result.status_);
EXPECT_EQ(result.handle_, nullptr);
EXPECT_NE(absl::nullopt, result.host_info_);
}

TEST_F(DnsCacheImplTest, PreLoadOverflow) {
initialize(true, 0);
EXPECT_EQ(1, TestUtility::findCounter(store_, "dns_cache.foo.host_overflow")->value());
checkStats(0 /* attempt */, 0 /* success */, 0 /* failure */, 0 /* address changed */,
0 /* added */, 0 /* removed */, 0 /* num hosts */);
}

// Basic successful resolution and then re-resolution.
TEST_F(DnsCacheImplTest, ResolveSuccess) {
initialize();
Expand Down Expand Up @@ -698,8 +732,7 @@ TEST_F(DnsCacheImplTest, InvalidPort) {

// Max host overflow.
TEST_F(DnsCacheImplTest, MaxHostOverflow) {
config_.mutable_max_hosts()->set_value(0);
initialize();
initialize(false /* set_pre_load_hostnames */, 0 /* max_hosts */);
InSequence s;

MockLoadDnsCacheEntryCallbacks callbacks;
Expand Down