1 //
2 //
3 // Copyright 2017 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18
19 #include <address_sorting/address_sorting.h>
20 #include <gmock/gmock.h>
21 #include <grpc/grpc.h>
22 #include <grpc/support/alloc.h>
23 #include <grpc/support/string_util.h>
24 #include <grpc/support/sync.h>
25 #include <grpc/support/time.h>
26 #include <string.h>
27 #include <sys/types.h>
28
29 #include <vector>
30
31 #include "absl/log/check.h"
32 #include "absl/log/log.h"
33 #include "src/core/client_channel/client_channel_filter.h"
34 #include "src/core/config/config_vars.h"
35 #include "src/core/lib/address_utils/sockaddr_utils.h"
36 #include "src/core/lib/channel/channel_args.h"
37 #include "src/core/lib/iomgr/combiner.h"
38 #include "src/core/lib/iomgr/executor.h"
39 #include "src/core/lib/iomgr/iomgr.h"
40 #include "src/core/lib/iomgr/resolve_address.h"
41 #include "src/core/resolver/dns/c_ares/grpc_ares_wrapper.h"
42 #include "src/core/resolver/endpoint_addresses.h"
43 #include "src/core/resolver/resolver.h"
44 #include "src/core/resolver/resolver_registry.h"
45 #include "src/core/util/crash.h"
46 #include "src/core/util/host_port.h"
47 #include "src/core/util/string.h"
48 #include "test/core/test_util/port.h"
49 #include "test/core/test_util/test_config.h"
50 #include "test/cpp/util/subprocess.h"
51 #include "test/cpp/util/test_config.h"
52
53 #ifndef GPR_WINDOWS
54 #include <arpa/inet.h>
55 #include <netinet/in.h>
56 #include <sys/socket.h>
57 #endif
58
59 namespace {
60
61 struct TestAddress {
62 std::string dest_addr;
63 int family;
64 };
65
TestAddressToGrpcResolvedAddress(TestAddress test_addr)66 grpc_resolved_address TestAddressToGrpcResolvedAddress(TestAddress test_addr) {
67 std::string host;
68 std::string port;
69 grpc_resolved_address resolved_addr;
70 grpc_core::SplitHostPort(test_addr.dest_addr.c_str(), &host, &port);
71 if (test_addr.family == AF_INET) {
72 sockaddr_in in_dest;
73 memset(&in_dest, 0, sizeof(sockaddr_in));
74 in_dest.sin_port = htons(atoi(port.c_str()));
75 in_dest.sin_family = AF_INET;
76 CHECK_EQ(inet_pton(AF_INET, host.c_str(), &in_dest.sin_addr), 1);
77 memcpy(&resolved_addr.addr, &in_dest, sizeof(sockaddr_in));
78 resolved_addr.len = sizeof(sockaddr_in);
79 } else {
80 CHECK(test_addr.family == AF_INET6);
81 sockaddr_in6 in6_dest;
82 memset(&in6_dest, 0, sizeof(sockaddr_in6));
83 in6_dest.sin6_port = htons(atoi(port.c_str()));
84 in6_dest.sin6_family = AF_INET6;
85 CHECK_EQ(inet_pton(AF_INET6, host.c_str(), &in6_dest.sin6_addr), 1);
86 memcpy(&resolved_addr.addr, &in6_dest, sizeof(sockaddr_in6));
87 resolved_addr.len = sizeof(sockaddr_in6);
88 }
89 return resolved_addr;
90 }
91
92 class MockSourceAddrFactory : public address_sorting_source_addr_factory {
93 public:
MockSourceAddrFactory(bool ipv4_supported,bool ipv6_supported,const std::map<std::string,TestAddress> & dest_addr_to_src_addr)94 MockSourceAddrFactory(
95 bool ipv4_supported, bool ipv6_supported,
96 const std::map<std::string, TestAddress>& dest_addr_to_src_addr)
97 : ipv4_supported_(ipv4_supported),
98 ipv6_supported_(ipv6_supported),
99 dest_addr_to_src_addr_(dest_addr_to_src_addr) {}
100
GetSourceAddr(const address_sorting_address * dest_addr,address_sorting_address * source_addr)101 bool GetSourceAddr(const address_sorting_address* dest_addr,
102 address_sorting_address* source_addr) {
103 if ((address_sorting_abstract_get_family(dest_addr) ==
104 ADDRESS_SORTING_AF_INET &&
105 !ipv4_supported_) ||
106 (address_sorting_abstract_get_family(dest_addr) ==
107 ADDRESS_SORTING_AF_INET6 &&
108 !ipv6_supported_)) {
109 return false;
110 }
111 grpc_resolved_address dest_addr_as_resolved_addr;
112 memcpy(&dest_addr_as_resolved_addr.addr, dest_addr, dest_addr->len);
113 dest_addr_as_resolved_addr.len = dest_addr->len;
114 std::string ip_addr_str =
115 grpc_sockaddr_to_string(&dest_addr_as_resolved_addr,
116 false /* normalize */)
117 .value();
118 auto it = dest_addr_to_src_addr_.find(ip_addr_str);
119 if (it == dest_addr_to_src_addr_.end()) {
120 VLOG(2) << "can't find |" << ip_addr_str << "| in dest to src map";
121 return false;
122 }
123 grpc_resolved_address source_addr_as_resolved_addr =
124 TestAddressToGrpcResolvedAddress(it->second);
125 memcpy(source_addr->addr, &source_addr_as_resolved_addr.addr,
126 source_addr_as_resolved_addr.len);
127 source_addr->len = source_addr_as_resolved_addr.len;
128 return true;
129 }
130
131 private:
132 // user provided test config
133 bool ipv4_supported_;
134 bool ipv6_supported_;
135 std::map<std::string, TestAddress> dest_addr_to_src_addr_;
136 };
137
mock_source_addr_factory_wrapper_get_source_addr(address_sorting_source_addr_factory * factory,const address_sorting_address * dest_addr,address_sorting_address * source_addr)138 bool mock_source_addr_factory_wrapper_get_source_addr(
139 address_sorting_source_addr_factory* factory,
140 const address_sorting_address* dest_addr,
141 address_sorting_address* source_addr) {
142 MockSourceAddrFactory* mock =
143 reinterpret_cast<MockSourceAddrFactory*>(factory);
144 return mock->GetSourceAddr(dest_addr, source_addr);
145 }
146
mock_source_addr_factory_wrapper_destroy(address_sorting_source_addr_factory * factory)147 void mock_source_addr_factory_wrapper_destroy(
148 address_sorting_source_addr_factory* factory) {
149 MockSourceAddrFactory* mock =
150 reinterpret_cast<MockSourceAddrFactory*>(factory);
151 delete mock;
152 }
153
154 const address_sorting_source_addr_factory_vtable kMockSourceAddrFactoryVtable =
155 {
156 mock_source_addr_factory_wrapper_get_source_addr,
157 mock_source_addr_factory_wrapper_destroy,
158 };
159
OverrideAddressSortingSourceAddrFactory(bool ipv4_supported,bool ipv6_supported,const std::map<std::string,TestAddress> & dest_addr_to_src_addr)160 void OverrideAddressSortingSourceAddrFactory(
161 bool ipv4_supported, bool ipv6_supported,
162 const std::map<std::string, TestAddress>& dest_addr_to_src_addr) {
163 address_sorting_source_addr_factory* factory = new MockSourceAddrFactory(
164 ipv4_supported, ipv6_supported, dest_addr_to_src_addr);
165 factory->vtable = &kMockSourceAddrFactoryVtable;
166 address_sorting_override_source_addr_factory_for_testing(factory);
167 }
168
BuildLbAddrInputs(const std::vector<TestAddress> & test_addrs)169 grpc_core::EndpointAddressesList BuildLbAddrInputs(
170 const std::vector<TestAddress>& test_addrs) {
171 grpc_core::EndpointAddressesList addresses;
172 for (const auto& addr : test_addrs) {
173 addresses.emplace_back(TestAddressToGrpcResolvedAddress(addr),
174 grpc_core::ChannelArgs());
175 }
176 return addresses;
177 }
178
VerifyLbAddrOutputs(const grpc_core::EndpointAddressesList & addresses,std::vector<std::string> expected_addrs)179 void VerifyLbAddrOutputs(const grpc_core::EndpointAddressesList& addresses,
180 std::vector<std::string> expected_addrs) {
181 EXPECT_EQ(addresses.size(), expected_addrs.size());
182 for (size_t i = 0; i < addresses.size(); ++i) {
183 std::string ip_addr_str =
184 grpc_sockaddr_to_string(&addresses[i].address(), false /* normalize */)
185 .value();
186 EXPECT_EQ(expected_addrs[i], ip_addr_str);
187 }
188 }
189
190 // We need to run each test case inside of its own
191 // isolated grpc_init/grpc_shutdown pair, so that
192 // the "address sorting source addr factory" can be
193 // restored to its default for each test case.
194 class AddressSortingTest : public ::testing::Test {
195 protected:
SetUp()196 void SetUp() override { grpc_init(); }
TearDown()197 void TearDown() override { grpc_shutdown(); }
198 };
199
200 // Tests for rule 1
TEST_F(AddressSortingTest,TestDepriotizesUnreachableAddresses)201 TEST_F(AddressSortingTest, TestDepriotizesUnreachableAddresses) {
202 bool ipv4_supported = true;
203 bool ipv6_supported = true;
204 OverrideAddressSortingSourceAddrFactory(
205 ipv4_supported, ipv6_supported,
206 {
207 {"1.2.3.4:443", {"4.3.2.1:443", AF_INET}},
208 });
209 auto lb_addrs = BuildLbAddrInputs({
210 {"1.2.3.4:443", AF_INET},
211 {"5.6.7.8:443", AF_INET},
212 });
213 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
214 VerifyLbAddrOutputs(lb_addrs, {
215 "1.2.3.4:443",
216 "5.6.7.8:443",
217 });
218 }
219
TEST_F(AddressSortingTest,TestDepriotizesUnsupportedDomainIpv6)220 TEST_F(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv6) {
221 bool ipv4_supported = true;
222 bool ipv6_supported = false;
223 OverrideAddressSortingSourceAddrFactory(
224 ipv4_supported, ipv6_supported,
225 {
226 {"1.2.3.4:443", {"4.3.2.1:0", AF_INET}},
227 });
228 auto lb_addrs = BuildLbAddrInputs({
229 {"[2607:f8b0:400a:801::1002]:443", AF_INET6},
230 {"1.2.3.4:443", AF_INET},
231 });
232 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
233 VerifyLbAddrOutputs(lb_addrs, {
234 "1.2.3.4:443",
235 "[2607:f8b0:400a:801::1002]:443",
236 });
237 }
238
TEST_F(AddressSortingTest,TestDepriotizesUnsupportedDomainIpv4)239 TEST_F(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv4) {
240 bool ipv4_supported = false;
241 bool ipv6_supported = true;
242 OverrideAddressSortingSourceAddrFactory(
243 ipv4_supported, ipv6_supported,
244 {
245 {"1.2.3.4:443", {"4.3.2.1:0", AF_INET}},
246 {"[2607:f8b0:400a:801::1002]:443", {"[fec0::1234]:0", AF_INET6}},
247 });
248 auto lb_addrs = BuildLbAddrInputs({
249 {"[2607:f8b0:400a:801::1002]:443", AF_INET6},
250 {"1.2.3.4:443", AF_INET},
251 });
252 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
253 VerifyLbAddrOutputs(lb_addrs, {
254 "[2607:f8b0:400a:801::1002]:443",
255 "1.2.3.4:443",
256 });
257 }
258
259 // Tests for rule 2
260
TEST_F(AddressSortingTest,TestDepriotizesNonMatchingScope)261 TEST_F(AddressSortingTest, TestDepriotizesNonMatchingScope) {
262 bool ipv4_supported = true;
263 bool ipv6_supported = true;
264 OverrideAddressSortingSourceAddrFactory(
265 ipv4_supported, ipv6_supported,
266 {
267 {"[2000:f8b0:400a:801::1002]:443",
268 {"[fec0::1000]:0", AF_INET6}}, // global and site-local scope
269 {"[fec0::5000]:443",
270 {"[fec0::5001]:0", AF_INET6}}, // site-local and site-local scope
271 });
272 auto lb_addrs = BuildLbAddrInputs({
273 {"[2000:f8b0:400a:801::1002]:443", AF_INET6},
274 {"[fec0::5000]:443", AF_INET6},
275 });
276 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
277 VerifyLbAddrOutputs(lb_addrs, {
278 "[fec0::5000]:443",
279 "[2000:f8b0:400a:801::1002]:443",
280 });
281 }
282
283 // Tests for rule 5
284
TEST_F(AddressSortingTest,TestUsesLabelFromDefaultTable)285 TEST_F(AddressSortingTest, TestUsesLabelFromDefaultTable) {
286 bool ipv4_supported = true;
287 bool ipv6_supported = true;
288 OverrideAddressSortingSourceAddrFactory(
289 ipv4_supported, ipv6_supported,
290 {
291 {"[2002::5001]:443", {"[2001::5002]:0", AF_INET6}},
292 {"[2001::5001]:443",
293 {"[2001::5002]:0", AF_INET6}}, // matching labels
294 });
295 auto lb_addrs = BuildLbAddrInputs({
296 {"[2002::5001]:443", AF_INET6},
297 {"[2001::5001]:443", AF_INET6},
298 });
299 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
300 VerifyLbAddrOutputs(lb_addrs, {
301 "[2001::5001]:443",
302 "[2002::5001]:443",
303 });
304 }
305
306 // Flip the input on the test above to reorder the sort function's
307 // comparator's inputs.
TEST_F(AddressSortingTest,TestUsesLabelFromDefaultTableInputFlipped)308 TEST_F(AddressSortingTest, TestUsesLabelFromDefaultTableInputFlipped) {
309 bool ipv4_supported = true;
310 bool ipv6_supported = true;
311 OverrideAddressSortingSourceAddrFactory(
312 ipv4_supported, ipv6_supported,
313 {
314 {"[2002::5001]:443", {"[2001::5002]:0", AF_INET6}},
315 {"[2001::5001]:443",
316 {"[2001::5002]:0", AF_INET6}}, // matching labels
317 });
318 auto lb_addrs = BuildLbAddrInputs({
319 {"[2001::5001]:443", AF_INET6},
320 {"[2002::5001]:443", AF_INET6},
321 });
322 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
323 VerifyLbAddrOutputs(lb_addrs, {
324 "[2001::5001]:443",
325 "[2002::5001]:443",
326 });
327 }
328
329 // Tests for rule 6
330
TEST_F(AddressSortingTest,TestUsesDestinationWithHigherPrecedenceWithAnIpv4Address)331 TEST_F(AddressSortingTest,
332 TestUsesDestinationWithHigherPrecedenceWithAnIpv4Address) {
333 bool ipv4_supported = true;
334 bool ipv6_supported = true;
335 OverrideAddressSortingSourceAddrFactory(
336 ipv4_supported, ipv6_supported,
337 {
338 {"[3ffe::5001]:443", {"[3ffe::5002]:0", AF_INET6}},
339 {"1.2.3.4:443", {"5.6.7.8:0", AF_INET}},
340 });
341 auto lb_addrs = BuildLbAddrInputs({
342 {"[3ffe::5001]:443", AF_INET6},
343 {"1.2.3.4:443", AF_INET},
344 });
345 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
346 VerifyLbAddrOutputs(
347 lb_addrs, {
348 // The AF_INET address should be IPv4-mapped by the sort,
349 // and IPv4-mapped
350 // addresses have higher precedence than 3ffe::/16 by spec.
351 "1.2.3.4:443",
352 "[3ffe::5001]:443",
353 });
354 }
355
TEST_F(AddressSortingTest,TestUsesDestinationWithHigherPrecedenceWithV4CompatAndLocalhostAddress)356 TEST_F(AddressSortingTest,
357 TestUsesDestinationWithHigherPrecedenceWithV4CompatAndLocalhostAddress) {
358 bool ipv4_supported = true;
359 bool ipv6_supported = true;
360 const char* v4_compat_dest = "[::2]:443";
361 const char* v4_compat_src = "[::2]:0";
362 OverrideAddressSortingSourceAddrFactory(
363 ipv4_supported, ipv6_supported,
364 {
365 {"[::1]:443", {"[::1]:0", AF_INET6}},
366 {v4_compat_dest, {v4_compat_src, AF_INET6}},
367 });
368 auto lb_addrs = BuildLbAddrInputs({
369 {v4_compat_dest, AF_INET6},
370 {"[::1]:443", AF_INET6},
371 });
372 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
373 ASSERT_EQ(lb_addrs.size(), 2);
374 EXPECT_EQ(
375 grpc_sockaddr_to_string(&lb_addrs[0].address(), false /* normalize */)
376 .value(),
377 "[::1]:443");
378 // We've observed some inet_ntop implementations have special representations
379 // of IPv4-compatible IPv6 addresses, and others represent them as normal
380 // IPv6 addresses. For the purposes of this test, we don't care which
381 // representation is used.
382 std::vector<std::string> acceptable_addresses = {
383 "[::0.0.0.2]:443",
384 "[::2]:443",
385 };
386 EXPECT_THAT(
387 acceptable_addresses,
388 ::testing::Contains(
389 grpc_sockaddr_to_string(&lb_addrs[1].address(), false /* normalize */)
390 .value()));
391 }
392
TEST_F(AddressSortingTest,TestUsesDestinationWithHigherPrecedenceWithCatchAllAndLocalhostAddress)393 TEST_F(AddressSortingTest,
394 TestUsesDestinationWithHigherPrecedenceWithCatchAllAndLocalhostAddress) {
395 bool ipv4_supported = true;
396 bool ipv6_supported = true;
397 OverrideAddressSortingSourceAddrFactory(
398 ipv4_supported, ipv6_supported,
399 {
400 // 1234::2 for src and dest to make sure that prefix matching has no
401 // influence on this test.
402 {"[1234::2]:443", {"[1234::2]:0", AF_INET6}},
403 {"[::1]:443", {"[::1]:0", AF_INET6}},
404 });
405 auto lb_addrs = BuildLbAddrInputs({
406 {"[1234::2]:443", AF_INET6},
407 {"[::1]:443", AF_INET6},
408 });
409 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
410 VerifyLbAddrOutputs(
411 lb_addrs,
412 {
413 // ::1 should match the localhost precedence entry and be prioritized
414 "[::1]:443",
415 "[1234::2]:443",
416 });
417 }
418
TEST_F(AddressSortingTest,TestUsesDestinationWithHigherPrecedenceWith2000PrefixedAddress)419 TEST_F(AddressSortingTest,
420 TestUsesDestinationWithHigherPrecedenceWith2000PrefixedAddress) {
421 bool ipv4_supported = true;
422 bool ipv6_supported = true;
423 OverrideAddressSortingSourceAddrFactory(
424 ipv4_supported, ipv6_supported,
425 {
426 {"[2001::1234]:443", {"[2001::5678]:0", AF_INET6}},
427 {"[2000::5001]:443", {"[2000::5002]:0", AF_INET6}},
428 });
429 auto lb_addrs = BuildLbAddrInputs({
430 {"[2001::1234]:443", AF_INET6},
431 {"[2000::5001]:443", AF_INET6},
432 });
433 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
434 VerifyLbAddrOutputs(
435 lb_addrs, {
436 // The 2000::/16 address should match the ::/0 prefix rule
437 "[2000::5001]:443",
438 "[2001::1234]:443",
439 });
440 }
441
TEST_F(AddressSortingTest,TestUsesDestinationWithHigherPrecedenceWith2000PrefixedAddressEnsurePrefixMatchHasNoEffect)442 TEST_F(
443 AddressSortingTest,
444 TestUsesDestinationWithHigherPrecedenceWith2000PrefixedAddressEnsurePrefixMatchHasNoEffect) {
445 bool ipv4_supported = true;
446 bool ipv6_supported = true;
447 OverrideAddressSortingSourceAddrFactory(
448 ipv4_supported, ipv6_supported,
449 {
450 {"[2001::1231]:443", {"[2001::1232]:0", AF_INET6}},
451 {"[2000::5001]:443", {"[2000::5002]:0", AF_INET6}},
452 });
453 auto lb_addrs = BuildLbAddrInputs({
454 {"[2001::1231]:443", AF_INET6},
455 {"[2000::5001]:443", AF_INET6},
456 });
457 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
458 VerifyLbAddrOutputs(lb_addrs, {
459 "[2000::5001]:443",
460 "[2001::1231]:443",
461 });
462 }
463
TEST_F(AddressSortingTest,TestUsesDestinationWithHigherPrecedenceWithLinkAndSiteLocalAddresses)464 TEST_F(AddressSortingTest,
465 TestUsesDestinationWithHigherPrecedenceWithLinkAndSiteLocalAddresses) {
466 bool ipv4_supported = true;
467 bool ipv6_supported = true;
468 OverrideAddressSortingSourceAddrFactory(
469 ipv4_supported, ipv6_supported,
470 {
471 {"[fec0::1234]:443", {"[fec0::5678]:0", AF_INET6}},
472 {"[fc00::5001]:443", {"[fc00::5002]:0", AF_INET6}},
473 });
474 auto lb_addrs = BuildLbAddrInputs({
475 {"[fec0::1234]:443", AF_INET6},
476 {"[fc00::5001]:443", AF_INET6},
477 });
478 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
479 VerifyLbAddrOutputs(lb_addrs, {
480 "[fc00::5001]:443",
481 "[fec0::1234]:443",
482 });
483 }
484
TEST_F(AddressSortingTest,TestUsesDestinationWithHigherPrecedenceWithCatchAllAndAndV4MappedAddresses)485 TEST_F(
486 AddressSortingTest,
487 TestUsesDestinationWithHigherPrecedenceWithCatchAllAndAndV4MappedAddresses) {
488 bool ipv4_supported = true;
489 bool ipv6_supported = true;
490 // Use embedded ipv4 addresses with leading 1's instead of zero's to be
491 // compatible with inet_ntop implementations that can display such
492 // addresses with leading zero's as e.g.: "::ffff:0:2", as on windows.
493 OverrideAddressSortingSourceAddrFactory(
494 ipv4_supported, ipv6_supported,
495 {
496 {"[::ffff:1.1.1.2]:443", {"[::ffff:1.1.1.3]:0", AF_INET6}},
497 {"[1234::2]:443", {"[1234::3]:0", AF_INET6}},
498 });
499 auto lb_addrs = BuildLbAddrInputs({
500 {"[::ffff:1.1.1.2]:443", AF_INET6},
501 {"[1234::2]:443", AF_INET6},
502 });
503 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
504 VerifyLbAddrOutputs(lb_addrs, {
505 // ::ffff:0:2 should match the v4-mapped
506 // precedence entry and be deprioritized.
507 "[1234::2]:443",
508 "[::ffff:1.1.1.2]:443",
509 });
510 }
511
512 // Tests for rule 8
513
TEST_F(AddressSortingTest,TestPrefersSmallerScope)514 TEST_F(AddressSortingTest, TestPrefersSmallerScope) {
515 bool ipv4_supported = true;
516 bool ipv6_supported = true;
517 OverrideAddressSortingSourceAddrFactory(
518 ipv4_supported, ipv6_supported,
519 {
520 // Both of these destinations have the same precedence in default
521 // policy
522 // table.
523 {"[fec0::1234]:443", {"[fec0::5678]:0", AF_INET6}},
524 {"[3ffe::5001]:443", {"[3ffe::5002]:0", AF_INET6}},
525 });
526 auto lb_addrs = BuildLbAddrInputs({
527 {"[3ffe::5001]:443", AF_INET6},
528 {"[fec0::1234]:443", AF_INET6},
529 });
530 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
531 VerifyLbAddrOutputs(lb_addrs, {
532 "[fec0::1234]:443",
533 "[3ffe::5001]:443",
534 });
535 }
536
537 // Tests for rule 9
538
TEST_F(AddressSortingTest,TestPrefersLongestMatchingSrcDstPrefix)539 TEST_F(AddressSortingTest, TestPrefersLongestMatchingSrcDstPrefix) {
540 bool ipv4_supported = true;
541 bool ipv6_supported = true;
542 OverrideAddressSortingSourceAddrFactory(
543 ipv4_supported, ipv6_supported,
544 {
545 // Both of these destinations have the same precedence in default
546 // policy
547 // table.
548 {"[3ffe:1234::]:443", {"[3ffe:1235::]:0", AF_INET6}},
549 {"[3ffe:5001::]:443", {"[3ffe:4321::]:0", AF_INET6}},
550 });
551 auto lb_addrs = BuildLbAddrInputs({
552 {"[3ffe:5001::]:443", AF_INET6},
553 {"[3ffe:1234::]:443", AF_INET6},
554 });
555 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
556 VerifyLbAddrOutputs(lb_addrs, {
557 "[3ffe:1234::]:443",
558 "[3ffe:5001::]:443",
559 });
560 }
561
TEST_F(AddressSortingTest,TestPrefersLongestMatchingSrcDstPrefixMatchesWholeAddress)562 TEST_F(AddressSortingTest,
563 TestPrefersLongestMatchingSrcDstPrefixMatchesWholeAddress) {
564 bool ipv4_supported = true;
565 bool ipv6_supported = true;
566 OverrideAddressSortingSourceAddrFactory(
567 ipv4_supported, ipv6_supported,
568 {
569 {"[3ffe::1234]:443", {"[3ffe::1235]:0", AF_INET6}},
570 {"[3ffe::5001]:443", {"[3ffe::4321]:0", AF_INET6}},
571 });
572 auto lb_addrs = BuildLbAddrInputs({
573 {"[3ffe::5001]:443", AF_INET6},
574 {"[3ffe::1234]:443", AF_INET6},
575 });
576 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
577 VerifyLbAddrOutputs(lb_addrs, {
578 "[3ffe::1234]:443",
579 "[3ffe::5001]:443",
580 });
581 }
582
TEST_F(AddressSortingTest,TestPrefersLongestPrefixStressInnerBytePrefix)583 TEST_F(AddressSortingTest, TestPrefersLongestPrefixStressInnerBytePrefix) {
584 bool ipv4_supported = true;
585 bool ipv6_supported = true;
586 OverrideAddressSortingSourceAddrFactory(
587 ipv4_supported, ipv6_supported,
588 {
589 {"[3ffe:8000::]:443", {"[3ffe:C000::]:0", AF_INET6}},
590 {"[3ffe:2000::]:443", {"[3ffe:3000::]:0", AF_INET6}},
591 });
592 auto lb_addrs = BuildLbAddrInputs({
593 {"[3ffe:8000::]:443", AF_INET6},
594 {"[3ffe:2000::]:443", AF_INET6},
595 });
596 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
597 VerifyLbAddrOutputs(lb_addrs, {
598 "[3ffe:2000::]:443",
599 "[3ffe:8000::]:443",
600 });
601 }
602
TEST_F(AddressSortingTest,TestPrefersLongestPrefixDiffersOnHighestBitOfByte)603 TEST_F(AddressSortingTest, TestPrefersLongestPrefixDiffersOnHighestBitOfByte) {
604 bool ipv4_supported = true;
605 bool ipv6_supported = true;
606 OverrideAddressSortingSourceAddrFactory(
607 ipv4_supported, ipv6_supported,
608 {
609 {"[3ffe:6::]:443", {"[3ffe:8::]:0", AF_INET6}},
610 {"[3ffe:c::]:443", {"[3ffe:8::]:0", AF_INET6}},
611 });
612 auto lb_addrs = BuildLbAddrInputs({
613 {"[3ffe:6::]:443", AF_INET6},
614 {"[3ffe:c::]:443", AF_INET6},
615 });
616 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
617 VerifyLbAddrOutputs(lb_addrs, {
618 "[3ffe:c::]:443",
619 "[3ffe:6::]:443",
620 });
621 }
622
TEST_F(AddressSortingTest,TestPrefersLongestPrefixDiffersByLastBit)623 TEST_F(AddressSortingTest, TestPrefersLongestPrefixDiffersByLastBit) {
624 bool ipv4_supported = true;
625 bool ipv6_supported = true;
626 OverrideAddressSortingSourceAddrFactory(
627 ipv4_supported, ipv6_supported,
628 {
629 {"[3ffe:1111:1111:1111::]:443",
630 {"[3ffe:1111:1111:1111::]:0", AF_INET6}},
631 {"[3ffe:1111:1111:1110::]:443",
632 {"[3ffe:1111:1111:1111::]:0", AF_INET6}},
633 });
634 auto lb_addrs = BuildLbAddrInputs({
635 {"[3ffe:1111:1111:1110::]:443", AF_INET6},
636 {"[3ffe:1111:1111:1111::]:443", AF_INET6},
637 });
638 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
639 VerifyLbAddrOutputs(lb_addrs, {
640 "[3ffe:1111:1111:1111::]:443",
641 "[3ffe:1111:1111:1110::]:443",
642 });
643 }
644
645 // Tests for rule 10
646
TEST_F(AddressSortingTest,TestStableSort)647 TEST_F(AddressSortingTest, TestStableSort) {
648 bool ipv4_supported = true;
649 bool ipv6_supported = true;
650 OverrideAddressSortingSourceAddrFactory(
651 ipv4_supported, ipv6_supported,
652 {
653 {"[3ffe::1234]:443", {"[3ffe::1236]:0", AF_INET6}},
654 {"[3ffe::1235]:443", {"[3ffe::1237]:0", AF_INET6}},
655 });
656 auto lb_addrs = BuildLbAddrInputs({
657 {"[3ffe::1234]:443", AF_INET6},
658 {"[3ffe::1235]:443", AF_INET6},
659 });
660 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
661 VerifyLbAddrOutputs(lb_addrs, {
662 "[3ffe::1234]:443",
663 "[3ffe::1235]:443",
664 });
665 }
666
TEST_F(AddressSortingTest,TestStableSortFiveElements)667 TEST_F(AddressSortingTest, TestStableSortFiveElements) {
668 bool ipv4_supported = true;
669 bool ipv6_supported = true;
670 OverrideAddressSortingSourceAddrFactory(
671 ipv4_supported, ipv6_supported,
672 {
673 {"[3ffe::1231]:443", {"[3ffe::1201]:0", AF_INET6}},
674 {"[3ffe::1232]:443", {"[3ffe::1202]:0", AF_INET6}},
675 {"[3ffe::1233]:443", {"[3ffe::1203]:0", AF_INET6}},
676 {"[3ffe::1234]:443", {"[3ffe::1204]:0", AF_INET6}},
677 {"[3ffe::1235]:443", {"[3ffe::1205]:0", AF_INET6}},
678 });
679 auto lb_addrs = BuildLbAddrInputs({
680 {"[3ffe::1231]:443", AF_INET6},
681 {"[3ffe::1232]:443", AF_INET6},
682 {"[3ffe::1233]:443", AF_INET6},
683 {"[3ffe::1234]:443", AF_INET6},
684 {"[3ffe::1235]:443", AF_INET6},
685 });
686 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
687 VerifyLbAddrOutputs(lb_addrs, {
688 "[3ffe::1231]:443",
689 "[3ffe::1232]:443",
690 "[3ffe::1233]:443",
691 "[3ffe::1234]:443",
692 "[3ffe::1235]:443",
693 });
694 }
695
TEST_F(AddressSortingTest,TestStableSortNoSrcAddrsExist)696 TEST_F(AddressSortingTest, TestStableSortNoSrcAddrsExist) {
697 bool ipv4_supported = true;
698 bool ipv6_supported = true;
699 OverrideAddressSortingSourceAddrFactory(ipv4_supported, ipv6_supported, {});
700 auto lb_addrs = BuildLbAddrInputs({
701 {"[3ffe::1231]:443", AF_INET6},
702 {"[3ffe::1232]:443", AF_INET6},
703 {"[3ffe::1233]:443", AF_INET6},
704 {"[3ffe::1234]:443", AF_INET6},
705 {"[3ffe::1235]:443", AF_INET6},
706 });
707 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
708 VerifyLbAddrOutputs(lb_addrs, {
709 "[3ffe::1231]:443",
710 "[3ffe::1232]:443",
711 "[3ffe::1233]:443",
712 "[3ffe::1234]:443",
713 "[3ffe::1235]:443",
714 });
715 }
716
TEST_F(AddressSortingTest,TestStableSortNoSrcAddrsExistWithIpv4)717 TEST_F(AddressSortingTest, TestStableSortNoSrcAddrsExistWithIpv4) {
718 bool ipv4_supported = true;
719 bool ipv6_supported = true;
720 OverrideAddressSortingSourceAddrFactory(ipv4_supported, ipv6_supported, {});
721 auto lb_addrs = BuildLbAddrInputs({
722 {"[::ffff:5.6.7.8]:443", AF_INET6},
723 {"1.2.3.4:443", AF_INET},
724 });
725 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
726 VerifyLbAddrOutputs(lb_addrs, {
727 "[::ffff:5.6.7.8]:443",
728 "1.2.3.4:443",
729 });
730 }
731
TEST_F(AddressSortingTest,TestStableSortV4CompatAndSiteLocalAddresses)732 TEST_F(AddressSortingTest, TestStableSortV4CompatAndSiteLocalAddresses) {
733 bool ipv4_supported = true;
734 bool ipv6_supported = true;
735 const char* v4_compat_dest = "[::2]:443";
736 const char* v4_compat_src = "[::3]:0";
737 OverrideAddressSortingSourceAddrFactory(
738 ipv4_supported, ipv6_supported,
739 {
740 {"[fec0::2000]:443", {"[fec0::2001]:0", AF_INET6}},
741 {v4_compat_dest, {v4_compat_src, AF_INET6}},
742 });
743 auto lb_addrs = BuildLbAddrInputs({
744 {"[fec0::2000]:443", AF_INET6},
745 {v4_compat_dest, AF_INET6},
746 });
747 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
748 ASSERT_EQ(lb_addrs.size(), 2);
749 // The sort should be stable since
750 // v4-compatible has same precedence as site-local.
751 EXPECT_EQ(
752 grpc_sockaddr_to_string(&lb_addrs[0].address(), false /* normalize */)
753 .value(),
754 "[fec0::2000]:443");
755 // We've observed some inet_ntop implementations have special representations
756 // of IPv4-compatible IPv6 addresses, and others represent them as normal
757 // IPv6 addresses. For the purposes of this test, we don't care which
758 // representation is used.
759 std::vector<std::string> acceptable_addresses = {
760 "[::0.0.0.2]:443",
761 "[::2]:443",
762 };
763 EXPECT_THAT(
764 acceptable_addresses,
765 ::testing::Contains(
766 grpc_sockaddr_to_string(&lb_addrs[1].address(), false /* normalize */)
767 .value()));
768 }
769
770 // TestPrefersIpv6Loopback tests the actual "address probing" code
771 // for the current platform, without any mocks.
772 // This test relies on the assumption that the ipv6 loopback address is
773 // available in the hosts/containers that grpc C/C++ tests run on
774 // (whether ipv4 loopback is available or not, an available ipv6
775 // loopback should be preferred).
TEST_F(AddressSortingTest,TestPrefersIpv6Loopback)776 TEST_F(AddressSortingTest, TestPrefersIpv6Loopback) {
777 auto lb_addrs = BuildLbAddrInputs({
778 {"[::1]:443", AF_INET6},
779 {"127.0.0.1:443", AF_INET},
780 });
781 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
782 VerifyLbAddrOutputs(lb_addrs, {
783 "[::1]:443",
784 "127.0.0.1:443",
785 });
786 }
787
788 // Flip the order of the inputs above and expect the same output order
789 // (try to rule out influence of arbitrary qsort ordering)
TEST_F(AddressSortingTest,TestPrefersIpv6LoopbackInputsFlipped)790 TEST_F(AddressSortingTest, TestPrefersIpv6LoopbackInputsFlipped) {
791 auto lb_addrs = BuildLbAddrInputs({
792 {"127.0.0.1:443", AF_INET},
793 {"[::1]:443", AF_INET6},
794 });
795 grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
796 VerifyLbAddrOutputs(lb_addrs, {
797 "[::1]:443",
798 "127.0.0.1:443",
799 });
800 }
801
802 // Try to rule out false positives in the above two tests in which
803 // the sorter might think that neither ipv6 or ipv4 loopback is
804 // available, but ipv6 loopback is still preferred only due
805 // to precedence table lookups.
TEST_F(AddressSortingTest,TestSorterKnowsIpv6LoopbackIsAvailable)806 TEST_F(AddressSortingTest, TestSorterKnowsIpv6LoopbackIsAvailable) {
807 sockaddr_in6 ipv6_loopback;
808 memset(&ipv6_loopback, 0, sizeof(ipv6_loopback));
809 ipv6_loopback.sin6_family = AF_INET6;
810 (reinterpret_cast<char*>(&ipv6_loopback.sin6_addr))[15] = 1;
811 ipv6_loopback.sin6_port = htons(443);
812 // Set up the source and destination parameters of
813 // address_sorting_get_source_addr
814 address_sorting_address sort_input_dest;
815 memcpy(&sort_input_dest.addr, &ipv6_loopback, sizeof(ipv6_loopback));
816 sort_input_dest.len = sizeof(ipv6_loopback);
817 address_sorting_address source_for_sort_input_dest;
818 memset(&source_for_sort_input_dest, 0, sizeof(source_for_sort_input_dest));
819 // address_sorting_get_source_addr returns true if a source address was found
820 // for the destination address, otherwise false.
821 EXPECT_TRUE(address_sorting_get_source_addr_for_testing(
822 &sort_input_dest, &source_for_sort_input_dest));
823 // Now also check that the source address was filled in correctly.
824 EXPECT_GT(source_for_sort_input_dest.len, 0u);
825 sockaddr_in6* source_addr_output =
826 reinterpret_cast<sockaddr_in6*>(source_for_sort_input_dest.addr);
827 EXPECT_EQ(source_addr_output->sin6_family, AF_INET6);
828 char* buf = static_cast<char*>(gpr_zalloc(100));
829 EXPECT_NE(inet_ntop(AF_INET6, &source_addr_output->sin6_addr, buf, 100),
830 nullptr)
831 << "inet_ntop failed. Errno: " + std::to_string(errno);
832 std::string source_addr_str(buf);
833 gpr_free(buf);
834 // This test
835 // assumes that the source address for any loopback destination is also the
836 // loopback address.
837 EXPECT_EQ(source_addr_str, "::1");
838 }
839
840 } // namespace
841
main(int argc,char ** argv)842 int main(int argc, char** argv) {
843 grpc_core::ConfigVars::Overrides overrides;
844 overrides.dns_resolver = "ares";
845 grpc_core::ConfigVars::SetOverrides(overrides);
846 grpc::testing::TestEnvironment env(&argc, argv);
847 ::testing::InitGoogleTest(&argc, argv);
848 auto result = RUN_ALL_TESTS();
849 // Test sequential and nested inits and shutdowns.
850 grpc_init();
851 grpc_init();
852 grpc_shutdown();
853 grpc_shutdown();
854 grpc_init();
855 grpc_shutdown();
856 return result;
857 }
858