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