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