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