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