1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net; 18 19 import android.net.IpPrefix; 20 import android.net.LinkAddress; 21 import android.net.LinkProperties; 22 import android.net.LinkProperties.ProvisioningChange; 23 import android.net.RouteInfo; 24 import android.system.OsConstants; 25 import android.test.suitebuilder.annotation.SmallTest; 26 import android.test.suitebuilder.annotation.Suppress; 27 import android.util.ArraySet; 28 29 import junit.framework.TestCase; 30 31 import java.net.InetAddress; 32 import java.util.Arrays; 33 import java.util.Collection; 34 import java.util.Collections; 35 import java.util.Set; 36 37 38 public class LinkPropertiesTest extends TestCase { 39 private static InetAddress ADDRV4 = NetworkUtils.numericToInetAddress("75.208.6.1"); 40 private static InetAddress ADDRV6 = NetworkUtils.numericToInetAddress( 41 "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); 42 private static InetAddress DNS1 = NetworkUtils.numericToInetAddress("75.208.7.1"); 43 private static InetAddress DNS2 = NetworkUtils.numericToInetAddress("69.78.7.1"); 44 private static InetAddress DNS6 = NetworkUtils.numericToInetAddress("2001:4860:4860::8888"); 45 private static InetAddress GATEWAY1 = NetworkUtils.numericToInetAddress("75.208.8.1"); 46 private static InetAddress GATEWAY2 = NetworkUtils.numericToInetAddress("69.78.8.1"); 47 private static InetAddress GATEWAY61 = NetworkUtils.numericToInetAddress("fe80::6:0000:613"); 48 private static InetAddress GATEWAY62 = NetworkUtils.numericToInetAddress("fe80::6:2222"); 49 private static String NAME = "qmi0"; 50 private static int MTU = 1500; 51 52 private static LinkAddress LINKADDRV4 = new LinkAddress(ADDRV4, 32); 53 private static LinkAddress LINKADDRV6 = new LinkAddress(ADDRV6, 128); 54 private static LinkAddress LINKADDRV6LINKLOCAL = new LinkAddress("fe80::1/64"); 55 56 // TODO: replace all calls to NetworkUtils.numericToInetAddress with calls to this method. Address(String addrString)57 private InetAddress Address(String addrString) { 58 return NetworkUtils.numericToInetAddress(addrString); 59 } 60 assertLinkPropertiesEqual(LinkProperties source, LinkProperties target)61 public void assertLinkPropertiesEqual(LinkProperties source, LinkProperties target) { 62 // Check implementation of equals(), element by element. 63 assertTrue(source.isIdenticalInterfaceName(target)); 64 assertTrue(target.isIdenticalInterfaceName(source)); 65 66 assertTrue(source.isIdenticalAddresses(target)); 67 assertTrue(target.isIdenticalAddresses(source)); 68 69 assertTrue(source.isIdenticalDnses(target)); 70 assertTrue(target.isIdenticalDnses(source)); 71 72 assertTrue(source.isIdenticalRoutes(target)); 73 assertTrue(target.isIdenticalRoutes(source)); 74 75 assertTrue(source.isIdenticalHttpProxy(target)); 76 assertTrue(target.isIdenticalHttpProxy(source)); 77 78 assertTrue(source.isIdenticalStackedLinks(target)); 79 assertTrue(target.isIdenticalStackedLinks(source)); 80 81 assertTrue(source.isIdenticalMtu(target)); 82 assertTrue(target.isIdenticalMtu(source)); 83 84 // Check result of equals(). 85 assertTrue(source.equals(target)); 86 assertTrue(target.equals(source)); 87 88 // Check hashCode. 89 assertEquals(source.hashCode(), target.hashCode()); 90 } 91 92 @SmallTest testEqualsNull()93 public void testEqualsNull() { 94 LinkProperties source = new LinkProperties(); 95 LinkProperties target = new LinkProperties(); 96 97 assertFalse(source == target); 98 assertLinkPropertiesEqual(source, target); 99 } 100 101 @SmallTest testEqualsSameOrder()102 public void testEqualsSameOrder() { 103 try { 104 LinkProperties source = new LinkProperties(); 105 source.setInterfaceName(NAME); 106 // set 2 link addresses 107 source.addLinkAddress(LINKADDRV4); 108 source.addLinkAddress(LINKADDRV6); 109 // set 2 dnses 110 source.addDnsServer(DNS1); 111 source.addDnsServer(DNS2); 112 // set 2 gateways 113 source.addRoute(new RouteInfo(GATEWAY1)); 114 source.addRoute(new RouteInfo(GATEWAY2)); 115 source.setMtu(MTU); 116 117 LinkProperties target = new LinkProperties(); 118 119 // All fields are same 120 target.setInterfaceName(NAME); 121 target.addLinkAddress(LINKADDRV4); 122 target.addLinkAddress(LINKADDRV6); 123 target.addDnsServer(DNS1); 124 target.addDnsServer(DNS2); 125 target.addRoute(new RouteInfo(GATEWAY1)); 126 target.addRoute(new RouteInfo(GATEWAY2)); 127 target.setMtu(MTU); 128 129 assertLinkPropertiesEqual(source, target); 130 131 target.clear(); 132 // change Interface Name 133 target.setInterfaceName("qmi1"); 134 target.addLinkAddress(LINKADDRV4); 135 target.addLinkAddress(LINKADDRV6); 136 target.addDnsServer(DNS1); 137 target.addDnsServer(DNS2); 138 target.addRoute(new RouteInfo(GATEWAY1)); 139 target.addRoute(new RouteInfo(GATEWAY2)); 140 target.setMtu(MTU); 141 assertFalse(source.equals(target)); 142 143 target.clear(); 144 target.setInterfaceName(NAME); 145 // change link addresses 146 target.addLinkAddress(new LinkAddress( 147 NetworkUtils.numericToInetAddress("75.208.6.2"), 32)); 148 target.addLinkAddress(LINKADDRV6); 149 target.addDnsServer(DNS1); 150 target.addDnsServer(DNS2); 151 target.addRoute(new RouteInfo(GATEWAY1)); 152 target.addRoute(new RouteInfo(GATEWAY2)); 153 target.setMtu(MTU); 154 assertFalse(source.equals(target)); 155 156 target.clear(); 157 target.setInterfaceName(NAME); 158 target.addLinkAddress(LINKADDRV4); 159 target.addLinkAddress(LINKADDRV6); 160 // change dnses 161 target.addDnsServer(NetworkUtils.numericToInetAddress("75.208.7.2")); 162 target.addDnsServer(DNS2); 163 target.addRoute(new RouteInfo(GATEWAY1)); 164 target.addRoute(new RouteInfo(GATEWAY2)); 165 target.setMtu(MTU); 166 assertFalse(source.equals(target)); 167 168 target.clear(); 169 target.setInterfaceName(NAME); 170 target.addLinkAddress(LINKADDRV4); 171 target.addLinkAddress(LINKADDRV6); 172 target.addDnsServer(DNS1); 173 target.addDnsServer(DNS2); 174 // change gateway 175 target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress("75.208.8.2"))); 176 target.addRoute(new RouteInfo(GATEWAY2)); 177 target.setMtu(MTU); 178 assertFalse(source.equals(target)); 179 180 target.clear(); 181 target.setInterfaceName(NAME); 182 target.addLinkAddress(LINKADDRV4); 183 target.addLinkAddress(LINKADDRV6); 184 target.addDnsServer(DNS1); 185 target.addDnsServer(DNS2); 186 target.addRoute(new RouteInfo(GATEWAY1)); 187 target.addRoute(new RouteInfo(GATEWAY2)); 188 // change mtu 189 target.setMtu(1440); 190 assertFalse(source.equals(target)); 191 192 } catch (Exception e) { 193 throw new RuntimeException(e.toString()); 194 //fail(); 195 } 196 } 197 198 @SmallTest testEqualsDifferentOrder()199 public void testEqualsDifferentOrder() { 200 try { 201 LinkProperties source = new LinkProperties(); 202 source.setInterfaceName(NAME); 203 // set 2 link addresses 204 source.addLinkAddress(LINKADDRV4); 205 source.addLinkAddress(LINKADDRV6); 206 // set 2 dnses 207 source.addDnsServer(DNS1); 208 source.addDnsServer(DNS2); 209 // set 2 gateways 210 source.addRoute(new RouteInfo(GATEWAY1)); 211 source.addRoute(new RouteInfo(GATEWAY2)); 212 source.setMtu(MTU); 213 214 LinkProperties target = new LinkProperties(); 215 // Exchange order 216 target.setInterfaceName(NAME); 217 target.addLinkAddress(LINKADDRV6); 218 target.addLinkAddress(LINKADDRV4); 219 target.addDnsServer(DNS2); 220 target.addDnsServer(DNS1); 221 target.addRoute(new RouteInfo(GATEWAY2)); 222 target.addRoute(new RouteInfo(GATEWAY1)); 223 target.setMtu(MTU); 224 225 assertLinkPropertiesEqual(source, target); 226 } catch (Exception e) { 227 fail(); 228 } 229 } 230 231 @SmallTest testEqualsDuplicated()232 public void testEqualsDuplicated() { 233 try { 234 LinkProperties source = new LinkProperties(); 235 // set 3 link addresses, eg, [A, A, B] 236 source.addLinkAddress(LINKADDRV4); 237 source.addLinkAddress(LINKADDRV4); 238 source.addLinkAddress(LINKADDRV6); 239 240 LinkProperties target = new LinkProperties(); 241 // set 3 link addresses, eg, [A, B, B] 242 target.addLinkAddress(LINKADDRV4); 243 target.addLinkAddress(LINKADDRV6); 244 target.addLinkAddress(LINKADDRV6); 245 246 assertLinkPropertiesEqual(source, target); 247 } catch (Exception e) { 248 fail(); 249 } 250 } 251 assertAllRoutesHaveInterface(String iface, LinkProperties lp)252 private void assertAllRoutesHaveInterface(String iface, LinkProperties lp) { 253 for (RouteInfo r : lp.getRoutes()) { 254 assertEquals(iface, r.getInterface()); 255 } 256 } 257 258 @SmallTest testRouteInterfaces()259 public void testRouteInterfaces() { 260 LinkAddress prefix = new LinkAddress( 261 NetworkUtils.numericToInetAddress("2001:db8::"), 32); 262 InetAddress address = ADDRV6; 263 264 // Add a route with no interface to a LinkProperties with no interface. No errors. 265 LinkProperties lp = new LinkProperties(); 266 RouteInfo r = new RouteInfo(prefix, address, null); 267 assertTrue(lp.addRoute(r)); 268 assertEquals(1, lp.getRoutes().size()); 269 assertAllRoutesHaveInterface(null, lp); 270 271 // Adding the same route twice has no effect. 272 assertFalse(lp.addRoute(r)); 273 assertEquals(1, lp.getRoutes().size()); 274 275 // Add a route with an interface. Expect an exception. 276 r = new RouteInfo(prefix, address, "wlan0"); 277 try { 278 lp.addRoute(r); 279 fail("Adding wlan0 route to LP with no interface, expect exception"); 280 } catch (IllegalArgumentException expected) {} 281 282 // Change the interface name. All the routes should change their interface name too. 283 lp.setInterfaceName("rmnet0"); 284 assertAllRoutesHaveInterface("rmnet0", lp); 285 286 // Now add a route with the wrong interface. This causes an exception too. 287 try { 288 lp.addRoute(r); 289 fail("Adding wlan0 route to rmnet0 LP, expect exception"); 290 } catch (IllegalArgumentException expected) {} 291 292 // If the interface name matches, the route is added. 293 r = new RouteInfo(prefix, null, "wlan0"); 294 lp.setInterfaceName("wlan0"); 295 lp.addRoute(r); 296 assertEquals(2, lp.getRoutes().size()); 297 assertAllRoutesHaveInterface("wlan0", lp); 298 299 // Routes with null interfaces are converted to wlan0. 300 r = RouteInfo.makeHostRoute(ADDRV6, null); 301 lp.addRoute(r); 302 assertEquals(3, lp.getRoutes().size()); 303 assertAllRoutesHaveInterface("wlan0", lp); 304 305 // Check comparisons work. 306 LinkProperties lp2 = new LinkProperties(lp); 307 assertAllRoutesHaveInterface("wlan0", lp); 308 assertEquals(0, lp.compareAllRoutes(lp2).added.size()); 309 assertEquals(0, lp.compareAllRoutes(lp2).removed.size()); 310 311 lp2.setInterfaceName("p2p0"); 312 assertAllRoutesHaveInterface("p2p0", lp2); 313 assertEquals(3, lp.compareAllRoutes(lp2).added.size()); 314 assertEquals(3, lp.compareAllRoutes(lp2).removed.size()); 315 } 316 317 @SmallTest testStackedInterfaces()318 public void testStackedInterfaces() { 319 LinkProperties rmnet0 = new LinkProperties(); 320 rmnet0.setInterfaceName("rmnet0"); 321 rmnet0.addLinkAddress(LINKADDRV6); 322 323 LinkProperties clat4 = new LinkProperties(); 324 clat4.setInterfaceName("clat4"); 325 clat4.addLinkAddress(LINKADDRV4); 326 327 assertEquals(0, rmnet0.getStackedLinks().size()); 328 assertEquals(1, rmnet0.getAddresses().size()); 329 assertEquals(1, rmnet0.getLinkAddresses().size()); 330 assertEquals(1, rmnet0.getAllAddresses().size()); 331 assertEquals(1, rmnet0.getAllLinkAddresses().size()); 332 333 rmnet0.addStackedLink(clat4); 334 assertEquals(1, rmnet0.getStackedLinks().size()); 335 assertEquals(1, rmnet0.getAddresses().size()); 336 assertEquals(1, rmnet0.getLinkAddresses().size()); 337 assertEquals(2, rmnet0.getAllAddresses().size()); 338 assertEquals(2, rmnet0.getAllLinkAddresses().size()); 339 340 rmnet0.addStackedLink(clat4); 341 assertEquals(1, rmnet0.getStackedLinks().size()); 342 assertEquals(1, rmnet0.getAddresses().size()); 343 assertEquals(1, rmnet0.getLinkAddresses().size()); 344 assertEquals(2, rmnet0.getAllAddresses().size()); 345 assertEquals(2, rmnet0.getAllLinkAddresses().size()); 346 347 assertEquals(0, clat4.getStackedLinks().size()); 348 349 // Modify an item in the returned collection to see what happens. 350 for (LinkProperties link : rmnet0.getStackedLinks()) { 351 if (link.getInterfaceName().equals("clat4")) { 352 link.setInterfaceName("newname"); 353 } 354 } 355 for (LinkProperties link : rmnet0.getStackedLinks()) { 356 assertFalse("newname".equals(link.getInterfaceName())); 357 } 358 359 assertTrue(rmnet0.removeStackedLink("clat4")); 360 assertEquals(0, rmnet0.getStackedLinks().size()); 361 assertEquals(1, rmnet0.getAddresses().size()); 362 assertEquals(1, rmnet0.getLinkAddresses().size()); 363 assertEquals(1, rmnet0.getAllAddresses().size()); 364 assertEquals(1, rmnet0.getAllLinkAddresses().size()); 365 366 assertFalse(rmnet0.removeStackedLink("clat4")); 367 } 368 getFirstLinkAddress(LinkProperties lp)369 private LinkAddress getFirstLinkAddress(LinkProperties lp) { 370 return lp.getLinkAddresses().iterator().next(); 371 } 372 373 @SmallTest testAddressMethods()374 public void testAddressMethods() { 375 LinkProperties lp = new LinkProperties(); 376 377 // No addresses. 378 assertFalse(lp.hasIPv4Address()); 379 assertFalse(lp.hasGlobalIPv6Address()); 380 381 // Addresses on stacked links don't count. 382 LinkProperties stacked = new LinkProperties(); 383 stacked.setInterfaceName("stacked"); 384 lp.addStackedLink(stacked); 385 stacked.addLinkAddress(LINKADDRV4); 386 stacked.addLinkAddress(LINKADDRV6); 387 assertTrue(stacked.hasIPv4Address()); 388 assertTrue(stacked.hasGlobalIPv6Address()); 389 assertFalse(lp.hasIPv4Address()); 390 assertFalse(lp.hasGlobalIPv6Address()); 391 lp.removeStackedLink("stacked"); 392 assertFalse(lp.hasIPv4Address()); 393 assertFalse(lp.hasGlobalIPv6Address()); 394 395 // Addresses on the base link. 396 // Check the return values of hasIPvXAddress and ensure the add/remove methods return true 397 // iff something changes. 398 assertEquals(0, lp.getLinkAddresses().size()); 399 assertTrue(lp.addLinkAddress(LINKADDRV6)); 400 assertEquals(1, lp.getLinkAddresses().size()); 401 assertFalse(lp.hasIPv4Address()); 402 assertTrue(lp.hasGlobalIPv6Address()); 403 404 assertTrue(lp.removeLinkAddress(LINKADDRV6)); 405 assertEquals(0, lp.getLinkAddresses().size()); 406 407 assertTrue(lp.addLinkAddress(LINKADDRV6LINKLOCAL)); 408 assertEquals(1, lp.getLinkAddresses().size()); 409 assertFalse(lp.hasGlobalIPv6Address()); 410 411 assertTrue(lp.addLinkAddress(LINKADDRV4)); 412 assertEquals(2, lp.getLinkAddresses().size()); 413 assertTrue(lp.hasIPv4Address()); 414 assertFalse(lp.hasGlobalIPv6Address()); 415 416 assertTrue(lp.addLinkAddress(LINKADDRV6)); 417 assertEquals(3, lp.getLinkAddresses().size()); 418 assertTrue(lp.hasIPv4Address()); 419 assertTrue(lp.hasGlobalIPv6Address()); 420 421 assertTrue(lp.removeLinkAddress(LINKADDRV6LINKLOCAL)); 422 assertEquals(2, lp.getLinkAddresses().size()); 423 assertTrue(lp.hasIPv4Address()); 424 assertTrue(lp.hasGlobalIPv6Address()); 425 426 // Adding an address twice has no effect. 427 // Removing an address that's not present has no effect. 428 assertFalse(lp.addLinkAddress(LINKADDRV4)); 429 assertEquals(2, lp.getLinkAddresses().size()); 430 assertTrue(lp.hasIPv4Address()); 431 assertTrue(lp.removeLinkAddress(LINKADDRV4)); 432 assertEquals(1, lp.getLinkAddresses().size()); 433 assertFalse(lp.hasIPv4Address()); 434 assertFalse(lp.removeLinkAddress(LINKADDRV4)); 435 assertEquals(1, lp.getLinkAddresses().size()); 436 437 // Adding an address that's already present but with different properties causes the 438 // existing address to be updated and returns true. 439 // Start with only LINKADDRV6. 440 assertEquals(1, lp.getLinkAddresses().size()); 441 assertEquals(LINKADDRV6, getFirstLinkAddress(lp)); 442 443 // Create a LinkAddress object for the same address, but with different flags. 444 LinkAddress deprecated = new LinkAddress(ADDRV6, 128, 445 OsConstants.IFA_F_DEPRECATED, OsConstants.RT_SCOPE_UNIVERSE); 446 assertTrue(deprecated.isSameAddressAs(LINKADDRV6)); 447 assertFalse(deprecated.equals(LINKADDRV6)); 448 449 // Check that adding it updates the existing address instead of adding a new one. 450 assertTrue(lp.addLinkAddress(deprecated)); 451 assertEquals(1, lp.getLinkAddresses().size()); 452 assertEquals(deprecated, getFirstLinkAddress(lp)); 453 assertFalse(LINKADDRV6.equals(getFirstLinkAddress(lp))); 454 455 // Removing LINKADDRV6 removes deprecated, because removing addresses ignores properties. 456 assertTrue(lp.removeLinkAddress(LINKADDRV6)); 457 assertEquals(0, lp.getLinkAddresses().size()); 458 } 459 460 @SmallTest testSetLinkAddresses()461 public void testSetLinkAddresses() { 462 LinkProperties lp = new LinkProperties(); 463 lp.addLinkAddress(LINKADDRV4); 464 lp.addLinkAddress(LINKADDRV6); 465 466 LinkProperties lp2 = new LinkProperties(); 467 lp2.addLinkAddress(LINKADDRV6); 468 469 assertFalse(lp.equals(lp2)); 470 471 lp2.setLinkAddresses(lp.getLinkAddresses()); 472 assertTrue(lp.equals(lp)); 473 } 474 475 @SmallTest testIsProvisioned()476 public void testIsProvisioned() { 477 LinkProperties lp4 = new LinkProperties(); 478 assertFalse("v4only:empty", lp4.isProvisioned()); 479 lp4.addLinkAddress(LINKADDRV4); 480 assertFalse("v4only:addr-only", lp4.isProvisioned()); 481 lp4.addDnsServer(DNS1); 482 assertFalse("v4only:addr+dns", lp4.isProvisioned()); 483 lp4.addRoute(new RouteInfo(GATEWAY1)); 484 assertTrue("v4only:addr+dns+route", lp4.isProvisioned()); 485 assertTrue("v4only:addr+dns+route", lp4.isIPv4Provisioned()); 486 assertFalse("v4only:addr+dns+route", lp4.isIPv6Provisioned()); 487 488 LinkProperties lp6 = new LinkProperties(); 489 assertFalse("v6only:empty", lp6.isProvisioned()); 490 lp6.addLinkAddress(LINKADDRV6LINKLOCAL); 491 assertFalse("v6only:fe80-only", lp6.isProvisioned()); 492 lp6.addDnsServer(DNS6); 493 assertFalse("v6only:fe80+dns", lp6.isProvisioned()); 494 lp6.addRoute(new RouteInfo(GATEWAY61)); 495 assertFalse("v6only:fe80+dns+route", lp6.isProvisioned()); 496 lp6.addLinkAddress(LINKADDRV6); 497 assertTrue("v6only:fe80+global+dns+route", lp6.isIPv6Provisioned()); 498 assertTrue("v6only:fe80+global+dns+route", lp6.isProvisioned()); 499 lp6.removeLinkAddress(LINKADDRV6LINKLOCAL); 500 assertFalse("v6only:global+dns+route", lp6.isIPv4Provisioned()); 501 assertTrue("v6only:global+dns+route", lp6.isIPv6Provisioned()); 502 assertTrue("v6only:global+dns+route", lp6.isProvisioned()); 503 504 LinkProperties lp46 = new LinkProperties(); 505 lp46.addLinkAddress(LINKADDRV4); 506 lp46.addLinkAddress(LINKADDRV6); 507 lp46.addDnsServer(DNS1); 508 lp46.addDnsServer(DNS6); 509 assertFalse("dualstack:missing-routes", lp46.isProvisioned()); 510 lp46.addRoute(new RouteInfo(GATEWAY1)); 511 assertTrue("dualstack:v4-provisioned", lp46.isIPv4Provisioned()); 512 assertFalse("dualstack:v4-provisioned", lp46.isIPv6Provisioned()); 513 assertTrue("dualstack:v4-provisioned", lp46.isProvisioned()); 514 lp46.addRoute(new RouteInfo(GATEWAY61)); 515 assertTrue("dualstack:both-provisioned", lp46.isIPv4Provisioned()); 516 assertTrue("dualstack:both-provisioned", lp46.isIPv6Provisioned()); 517 assertTrue("dualstack:both-provisioned", lp46.isProvisioned()); 518 519 // A link with an IPv6 address and default route, but IPv4 DNS server. 520 LinkProperties mixed = new LinkProperties(); 521 mixed.addLinkAddress(LINKADDRV6); 522 mixed.addDnsServer(DNS1); 523 mixed.addRoute(new RouteInfo(GATEWAY61)); 524 assertFalse("mixed:addr6+route6+dns4", mixed.isIPv4Provisioned()); 525 assertFalse("mixed:addr6+route6+dns4", mixed.isIPv6Provisioned()); 526 assertFalse("mixed:addr6+route6+dns4", mixed.isProvisioned()); 527 } 528 529 @SmallTest testCompareProvisioning()530 public void testCompareProvisioning() { 531 LinkProperties v4lp = new LinkProperties(); 532 v4lp.addLinkAddress(LINKADDRV4); 533 v4lp.addRoute(new RouteInfo(GATEWAY1)); 534 v4lp.addDnsServer(DNS1); 535 assertTrue(v4lp.isProvisioned()); 536 537 LinkProperties v4r = new LinkProperties(v4lp); 538 v4r.removeDnsServer(DNS1); 539 assertFalse(v4r.isProvisioned()); 540 541 assertEquals(ProvisioningChange.STILL_NOT_PROVISIONED, 542 LinkProperties.compareProvisioning(v4r, v4r)); 543 assertEquals(ProvisioningChange.LOST_PROVISIONING, 544 LinkProperties.compareProvisioning(v4lp, v4r)); 545 assertEquals(ProvisioningChange.GAINED_PROVISIONING, 546 LinkProperties.compareProvisioning(v4r, v4lp)); 547 assertEquals(ProvisioningChange.STILL_PROVISIONED, 548 LinkProperties.compareProvisioning(v4lp, v4lp)); 549 550 // Check that losing IPv4 provisioning on a dualstack network is 551 // seen as a total loss of provisioning. 552 LinkProperties v6lp = new LinkProperties(); 553 v6lp.addLinkAddress(LINKADDRV6); 554 v6lp.addRoute(new RouteInfo(GATEWAY61)); 555 v6lp.addDnsServer(DNS6); 556 assertFalse(v6lp.isIPv4Provisioned()); 557 assertTrue(v6lp.isIPv6Provisioned()); 558 assertTrue(v6lp.isProvisioned()); 559 560 LinkProperties v46lp = new LinkProperties(v6lp); 561 v46lp.addLinkAddress(LINKADDRV4); 562 v46lp.addRoute(new RouteInfo(GATEWAY1)); 563 v46lp.addDnsServer(DNS1); 564 assertTrue(v46lp.isIPv4Provisioned()); 565 assertTrue(v46lp.isIPv6Provisioned()); 566 assertTrue(v46lp.isProvisioned()); 567 568 assertEquals(ProvisioningChange.STILL_PROVISIONED, 569 LinkProperties.compareProvisioning(v4lp, v46lp)); 570 assertEquals(ProvisioningChange.STILL_PROVISIONED, 571 LinkProperties.compareProvisioning(v6lp, v46lp)); 572 assertEquals(ProvisioningChange.LOST_PROVISIONING, 573 LinkProperties.compareProvisioning(v46lp, v6lp)); 574 assertEquals(ProvisioningChange.LOST_PROVISIONING, 575 LinkProperties.compareProvisioning(v46lp, v4lp)); 576 577 // Check that losing and gaining a secondary router does not change 578 // the provisioning status. 579 LinkProperties v6lp2 = new LinkProperties(v6lp); 580 v6lp2.addRoute(new RouteInfo(GATEWAY62)); 581 assertTrue(v6lp2.isProvisioned()); 582 583 assertEquals(ProvisioningChange.STILL_PROVISIONED, 584 LinkProperties.compareProvisioning(v6lp2, v6lp)); 585 assertEquals(ProvisioningChange.STILL_PROVISIONED, 586 LinkProperties.compareProvisioning(v6lp, v6lp2)); 587 } 588 589 @SmallTest 590 @Suppress // Failing. testIsReachable()591 public void testIsReachable() { 592 final LinkProperties v4lp = new LinkProperties(); 593 assertFalse(v4lp.isReachable(DNS1)); 594 assertFalse(v4lp.isReachable(DNS2)); 595 596 // Add an on-link route, making the on-link DNS server reachable, 597 // but there is still no IPv4 address. 598 assertTrue(v4lp.addRoute(new RouteInfo( 599 new IpPrefix(NetworkUtils.numericToInetAddress("75.208.0.0"), 16)))); 600 assertFalse(v4lp.isReachable(DNS1)); 601 assertFalse(v4lp.isReachable(DNS2)); 602 603 // Adding an IPv4 address (right now, any IPv4 address) means we use 604 // the routes to compute likely reachability. 605 assertTrue(v4lp.addLinkAddress(new LinkAddress(ADDRV4, 16))); 606 assertTrue(v4lp.isReachable(DNS1)); 607 assertFalse(v4lp.isReachable(DNS2)); 608 609 // Adding a default route makes the off-link DNS server reachable. 610 assertTrue(v4lp.addRoute(new RouteInfo(GATEWAY1))); 611 assertTrue(v4lp.isReachable(DNS1)); 612 assertTrue(v4lp.isReachable(DNS2)); 613 614 final LinkProperties v6lp = new LinkProperties(); 615 final InetAddress kLinkLocalDns = NetworkUtils.numericToInetAddress("fe80::6:1"); 616 final InetAddress kLinkLocalDnsWithScope = NetworkUtils.numericToInetAddress("fe80::6:2%43"); 617 final InetAddress kOnLinkDns = NetworkUtils.numericToInetAddress("2001:db8:85a3::53"); 618 assertFalse(v6lp.isReachable(kLinkLocalDns)); 619 assertFalse(v6lp.isReachable(kLinkLocalDnsWithScope)); 620 assertFalse(v6lp.isReachable(kOnLinkDns)); 621 assertFalse(v6lp.isReachable(DNS6)); 622 623 // Add a link-local route, making the link-local DNS servers reachable. Because 624 // we assume the presence of an IPv6 link-local address, link-local DNS servers 625 // are considered reachable, but only those with a non-zero scope identifier. 626 assertTrue(v6lp.addRoute(new RouteInfo( 627 new IpPrefix(NetworkUtils.numericToInetAddress("fe80::"), 64)))); 628 assertFalse(v6lp.isReachable(kLinkLocalDns)); 629 assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope)); 630 assertFalse(v6lp.isReachable(kOnLinkDns)); 631 assertFalse(v6lp.isReachable(DNS6)); 632 633 // Add a link-local address--nothing changes. 634 assertTrue(v6lp.addLinkAddress(LINKADDRV6LINKLOCAL)); 635 assertFalse(v6lp.isReachable(kLinkLocalDns)); 636 assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope)); 637 assertFalse(v6lp.isReachable(kOnLinkDns)); 638 assertFalse(v6lp.isReachable(DNS6)); 639 640 // Add a global route on link, but no global address yet. DNS servers reachable 641 // via a route that doesn't require a gateway: give them the benefit of the 642 // doubt and hope the link-local source address suffices for communication. 643 assertTrue(v6lp.addRoute(new RouteInfo( 644 new IpPrefix(NetworkUtils.numericToInetAddress("2001:db8:85a3::"), 64)))); 645 assertFalse(v6lp.isReachable(kLinkLocalDns)); 646 assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope)); 647 assertTrue(v6lp.isReachable(kOnLinkDns)); 648 assertFalse(v6lp.isReachable(DNS6)); 649 650 // Add a global address; the on-link global address DNS server is (still) 651 // presumed reachable. 652 assertTrue(v6lp.addLinkAddress(new LinkAddress(ADDRV6, 64))); 653 assertFalse(v6lp.isReachable(kLinkLocalDns)); 654 assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope)); 655 assertTrue(v6lp.isReachable(kOnLinkDns)); 656 assertFalse(v6lp.isReachable(DNS6)); 657 658 // Adding a default route makes the off-link DNS server reachable. 659 assertTrue(v6lp.addRoute(new RouteInfo(GATEWAY62))); 660 assertFalse(v6lp.isReachable(kLinkLocalDns)); 661 assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope)); 662 assertTrue(v6lp.isReachable(kOnLinkDns)); 663 assertTrue(v6lp.isReachable(DNS6)); 664 665 // Check isReachable on stacked links. This requires that the source IP address be assigned 666 // on the interface returned by the route lookup. 667 LinkProperties stacked = new LinkProperties(); 668 669 // Can't add a stacked link without an interface name. 670 stacked.setInterfaceName("v4-test0"); 671 v6lp.addStackedLink(stacked); 672 673 InetAddress stackedAddress = Address("192.0.0.4"); 674 LinkAddress stackedLinkAddress = new LinkAddress(stackedAddress, 32); 675 assertFalse(v6lp.isReachable(stackedAddress)); 676 stacked.addLinkAddress(stackedLinkAddress); 677 assertFalse(v6lp.isReachable(stackedAddress)); 678 stacked.addRoute(new RouteInfo(stackedLinkAddress)); 679 assertTrue(stacked.isReachable(stackedAddress)); 680 assertTrue(v6lp.isReachable(stackedAddress)); 681 682 assertFalse(v6lp.isReachable(DNS1)); 683 stacked.addRoute(new RouteInfo((IpPrefix) null, stackedAddress)); 684 assertTrue(v6lp.isReachable(DNS1)); 685 } 686 687 @SmallTest testLinkPropertiesEnsureDirectlyConnectedRoutes()688 public void testLinkPropertiesEnsureDirectlyConnectedRoutes() { 689 // IPv4 case: no route added initially 690 LinkProperties rmnet0 = new LinkProperties(); 691 rmnet0.setInterfaceName("rmnet0"); 692 rmnet0.addLinkAddress(new LinkAddress("10.0.0.2/8")); 693 RouteInfo directRoute0 = new RouteInfo(new IpPrefix("10.0.0.0/8"), null, 694 rmnet0.getInterfaceName()); 695 696 // Since no routes is added explicitly, getAllRoutes() should return empty. 697 assertTrue(rmnet0.getAllRoutes().isEmpty()); 698 rmnet0.ensureDirectlyConnectedRoutes(); 699 // ensureDirectlyConnectedRoutes() should have added the missing local route. 700 assertEqualRoutes(Collections.singletonList(directRoute0), rmnet0.getAllRoutes()); 701 702 // IPv4 case: both direct and default routes added initially 703 LinkProperties rmnet1 = new LinkProperties(); 704 rmnet1.setInterfaceName("rmnet1"); 705 rmnet1.addLinkAddress(new LinkAddress("10.0.0.3/8")); 706 RouteInfo defaultRoute1 = new RouteInfo((IpPrefix) null, 707 NetworkUtils.numericToInetAddress("10.0.0.1"), rmnet1.getInterfaceName()); 708 RouteInfo directRoute1 = new RouteInfo(new IpPrefix("10.0.0.0/8"), null, 709 rmnet1.getInterfaceName()); 710 rmnet1.addRoute(defaultRoute1); 711 rmnet1.addRoute(directRoute1); 712 713 // Check added routes 714 assertEqualRoutes(Arrays.asList(defaultRoute1, directRoute1), rmnet1.getAllRoutes()); 715 // ensureDirectlyConnectedRoutes() shouldn't change the routes since direct connected 716 // route is already part of the configuration. 717 rmnet1.ensureDirectlyConnectedRoutes(); 718 assertEqualRoutes(Arrays.asList(defaultRoute1, directRoute1), rmnet1.getAllRoutes()); 719 720 // IPv6 case: only default routes added initially 721 LinkProperties rmnet2 = new LinkProperties(); 722 rmnet2.setInterfaceName("rmnet2"); 723 rmnet2.addLinkAddress(new LinkAddress("fe80::cafe/64")); 724 rmnet2.addLinkAddress(new LinkAddress("2001:db8::2/64")); 725 RouteInfo defaultRoute2 = new RouteInfo((IpPrefix) null, 726 NetworkUtils.numericToInetAddress("2001:db8::1"), rmnet2.getInterfaceName()); 727 RouteInfo directRoute2 = new RouteInfo(new IpPrefix("2001:db8::/64"), null, 728 rmnet2.getInterfaceName()); 729 RouteInfo linkLocalRoute2 = new RouteInfo(new IpPrefix("fe80::/64"), null, 730 rmnet2.getInterfaceName()); 731 rmnet2.addRoute(defaultRoute2); 732 733 assertEqualRoutes(Arrays.asList(defaultRoute2), rmnet2.getAllRoutes()); 734 rmnet2.ensureDirectlyConnectedRoutes(); 735 assertEqualRoutes(Arrays.asList(defaultRoute2, directRoute2, linkLocalRoute2), 736 rmnet2.getAllRoutes()); 737 738 // Corner case: no interface name 739 LinkProperties rmnet3 = new LinkProperties(); 740 rmnet3.addLinkAddress(new LinkAddress("192.168.0.2/24")); 741 RouteInfo directRoute3 = new RouteInfo(new IpPrefix("192.168.0.0/24"), null, 742 rmnet3.getInterfaceName()); 743 744 assertTrue(rmnet3.getAllRoutes().isEmpty()); 745 rmnet3.ensureDirectlyConnectedRoutes(); 746 assertEqualRoutes(Collections.singletonList(directRoute3), rmnet3.getAllRoutes()); 747 748 } 749 assertEqualRoutes(Collection<RouteInfo> expected, Collection<RouteInfo> actual)750 private void assertEqualRoutes(Collection<RouteInfo> expected, Collection<RouteInfo> actual) { 751 Set<RouteInfo> expectedSet = new ArraySet<>(expected); 752 Set<RouteInfo> actualSet = new ArraySet<>(actual); 753 // Duplicated entries in actual routes are considered failures 754 assertEquals(actual.size(), actualSet.size()); 755 756 assertEquals(expectedSet, actualSet); 757 } 758 } 759