-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
dfp: Insert correct preresolved hostname key in DNS cache #30784
Conversation
Previously, preresolved hostnames didn't include the port in the `host` that is used as a key in the DNS cache. This behavior differed from the regular resolution path which always normalized the host (via DnsHostInfo::normalizeHostForDfp). There was also a bug in the DnsCacheImplTest.PreresolveSuccess test, where the preresolve hostnames config included the port in the socket address, which is not how it would normally be specified and masked this issue. This PR fixes the problem by ensuring the preresolved hostnames have the host normalized (via DnsHostInfo::normalizeHostForDfp) before inserting into the DNS cache, just like the host is normalized before retrieving from the DNS cache. The test issue is also fixed so we can now verify that the correct cache key is being used for insertion, retrieval, and removal, and test coverage is added to ensure we can fetch the cache entry correctly whether the host includes the port or not. Signed-off-by: Ali Beyad <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch!
EXPECT_CALL(*resolver_, resolve("bar.baz.com", _, _)) | ||
std::string host = "bar.baz.com"; | ||
uint32_t port = 443; | ||
std::string authority = host + ":" + std::to_string(port); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I think absl::StrCat() is the canonical way to do this sort of concatenation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah i was debating whether to do that and add the new include or just use +
and to_string()
(since I see test code that use these quite liberally), but i just changed it to StrCat
@@ -58,7 +58,10 @@ DnsCacheImpl::DnsCacheImpl( | |||
// cache to load an entry. Further if this particular resolution fails all the is lost is the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(I'm trying to comment on line 56)
Wow, is this the correct type for hostname?
repeated config.core.v3.SocketAddress preresolve_hostnames = 10;
Hostname is a bizarre term for this as it seems to be a protocol (tcp/udp), an IP address, a port, and a resolver name. Am I reading that correctly? bizarre
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was also surprised SocketAddress was used for preresolved hostnames config, and doesn't seem to be the right structure to represent a DNS cache entry. Changing it is a good idea but probably outside the scope of the PR. I do share your concern though..
@@ -58,7 +58,10 @@ DnsCacheImpl::DnsCacheImpl( | |||
// cache to load an entry. Further if this particular resolution fails all the is lost is the | |||
// potential optimization of having the entry be preresolved the first time a true consumer of | |||
// this DNS cache asks for it. | |||
startCacheLoad(hostname.address(), hostname.port_value(), false); | |||
const std::string host = | |||
DnsHostInfo::normalizeHostForDfp(hostname.address(), hostname.port_value()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need a runtime guard for this, since it looks like a behavior change? (Or is there some reason we're safe here)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was debating this myself, and could be convinced of adding a runtime guard. I just figured that no one is using this currently (preresolved hostnames config), and in any case, all that will happen if the cache key change causes a cache miss is that the DNS record will have to be fetched (which is actually what was happening previously on "production" use cases, i.e. my traffic director integration test, without us knowing about it, you can just tell from the logs).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'd be inclined to add a guard (which will default to true) since it's easy to add and better safe than sorry. I think we know that nobody is using the mobile APIs for this config, but I'm not sure if we know about DFP users in the wild?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point, i had assumed DFP is only used for mobile but didn't consider the possibility it's used outside of mobile. runtime guard has been added!
Signed-off-by: Ali Beyad <[email protected]>
Signed-off-by: Ali Beyad <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for doing this!
Adding @lizan as DFP owner and cross-company reviewer |
/retest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one style nit. otherwise LGTM. @RyanTheOptimist feel free to merge.
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 (!preresolve_hostnames.empty()) { | ||
for (const auto& hostname : preresolve_hostnames) { | ||
for (const auto& host_pair : preresolve_hostnames) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
for (const auto& host_pair : preresolve_hostnames) { | |
for (const auto& [host, port] : preresolve_hostnames) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the recommendation, done!
Signed-off-by: Ali Beyad <[email protected]>
I think the protobuf check will fail until #30826 lands and is merged into this PR :( |
/retest |
Signed-off-by: Ali Beyad <[email protected]>
/retest |
Previously, preresolved hostnames didn't include the port in the
host
that is used as a key in the DNS cache. This behavior differed from the regular resolution path which always normalized the host (via DnsHostInfo::normalizeHostForDfp). There was also a bug in the DnsCacheImplTest.PreresolveSuccess test, where the preresolve hostnames config included the port in the socket address, which is not how it would normally be specified and masked this issue.This PR fixes the problem by ensuring the preresolved hostnames have the host normalized (via DnsHostInfo::normalizeHostForDfp) before inserting into the DNS cache, just like the host is normalized before retrieving from the DNS cache. The test issue is also fixed so we can now verify that the correct cache key is being used for insertion, retrieval, and removal, and test coverage is added to ensure we can fetch the cache entry correctly whether the host includes the port or not.