1
0
mirror of https://github.com/apple/foundationdb.git synced 2025-05-28 02:48:09 +08:00

Merge pull request from RenxuanW/hostname-backup

Prefer IPv6 in hostname resolving.
This commit is contained in:
Renxuan Wang 2022-08-01 12:34:02 -07:00 committed by GitHub
commit 51b92d59b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 3 deletions

@ -43,7 +43,7 @@ ACTOR Future<Optional<NetworkAddress>> resolveImpl(Hostname* self) {
try {
std::vector<NetworkAddress> addresses =
wait(INetworkConnections::net()->resolveTCPEndpointWithDNSCache(self->host, self->service));
NetworkAddress address = addresses[deterministicRandom()->randomInt(0, addresses.size())];
NetworkAddress address = INetworkConnections::pickOneAddress(addresses);
address.flags = 0; // Reset the parsed address to public
address.fromHostname = NetworkAddressFromHostname::True;
if (self->isTLS) {
@ -84,7 +84,7 @@ Optional<NetworkAddress> Hostname::resolveBlocking() {
try {
std::vector<NetworkAddress> addresses =
INetworkConnections::net()->resolveTCPEndpointBlockingWithDNSCache(host, service);
NetworkAddress address = addresses[deterministicRandom()->randomInt(0, addresses.size())];
NetworkAddress address = INetworkConnections::pickOneAddress(addresses);
address.flags = 0; // Reset the parsed address to public
address.fromHostname = NetworkAddressFromHostname::True;
if (isTLS) {

@ -736,6 +736,22 @@ public:
return static_cast<INetworkConnections*>((void*)g_network->global(INetwork::enNetworkConnections));
}
// If a DNS name can be resolved to both and IPv4 and IPv6 addresses, we want IPv6 addresses when running the
// clusters on IPv6.
// This function takes a vector of addresses and return a random one, preferring IPv6 over IPv4.
static NetworkAddress pickOneAddress(const std::vector<NetworkAddress>& addresses) {
std::vector<NetworkAddress> ipV6Addresses;
for (const NetworkAddress& addr : addresses) {
if (addr.isV6()) {
ipV6Addresses.push_back(addr);
}
}
if (ipV6Addresses.size() > 0) {
return ipV6Addresses[deterministicRandom()->randomInt(0, ipV6Addresses.size())];
}
return addresses[deterministicRandom()->randomInt(0, addresses.size())];
}
void removeCachedDNS(const std::string& host, const std::string& service) { dnsCache.remove(host, service); }
DNSCache dnsCache;

@ -279,7 +279,7 @@ Future<Reference<IConnection>> INetworkConnections::connect(const std::string& h
// Use map to create an actor that returns an endpoint or throws
Future<NetworkAddress> pickEndpoint =
map(resolveTCPEndpoint(host, service), [=](std::vector<NetworkAddress> const& addresses) -> NetworkAddress {
NetworkAddress addr = addresses[deterministicRandom()->randomInt(0, addresses.size())];
NetworkAddress addr = INetworkConnections::pickOneAddress(addresses);
addr.fromHostname = true;
if (isTLS) {
addr.flags = NetworkAddress::FLAG_TLS;
@ -347,4 +347,22 @@ TEST_CASE("/flow/network/ipaddress") {
return Void();
}
TEST_CASE("/flow/network/ipV6Preferred") {
std::vector<NetworkAddress> addresses;
for (int i = 0; i < 50; ++i) {
std::string s = fmt::format("{}.{}.{}.{}:{}", i, i, i, i, i);
addresses.push_back(NetworkAddress::parse(s));
}
std::string ipv6 = "[2001:db8:85a3::8a2e:370:7334]:4800";
addresses.push_back(NetworkAddress::parse(ipv6));
for (int i = 50; i < 100; ++i) {
std::string s = fmt::format("{}.{}.{}.{}:{}", i, i, i, i, i);
addresses.push_back(NetworkAddress::parse(s));
}
// Confirm IPv6 is always preferred.
ASSERT(INetworkConnections::pickOneAddress(addresses).toString() == ipv6);
return Void();
}
NetworkInfo::NetworkInfo() : handshakeLock(new FlowLock(FLOW_KNOBS->TLS_HANDSHAKE_LIMIT)) {}