1 /* 2 * Copyright (C) 2017 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 com.android.server.connectivity; 18 19 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertFalse; 23 import static org.junit.Assert.assertNull; 24 import static org.junit.Assert.assertTrue; 25 import static org.mockito.Mockito.any; 26 import static org.mockito.Mockito.anyInt; 27 import static org.mockito.Mockito.anyString; 28 import static org.mockito.Mockito.doReturn; 29 import static org.mockito.Mockito.eq; 30 import static org.mockito.Mockito.inOrder; 31 import static org.mockito.Mockito.never; 32 import static org.mockito.Mockito.times; 33 import static org.mockito.Mockito.verify; 34 import static org.mockito.Mockito.verifyNoMoreInteractions; 35 import static org.mockito.Mockito.when; 36 37 import android.net.ConnectivityManager; 38 import android.net.IDnsResolver; 39 import android.net.INetd; 40 import android.net.InterfaceConfigurationParcel; 41 import android.net.IpPrefix; 42 import android.net.LinkAddress; 43 import android.net.LinkProperties; 44 import android.net.NetworkAgentConfig; 45 import android.net.NetworkCapabilities; 46 import android.net.NetworkInfo; 47 import android.os.Build; 48 import android.os.Handler; 49 import android.os.test.TestLooper; 50 51 import androidx.annotation.NonNull; 52 import androidx.annotation.Nullable; 53 import androidx.test.filters.SmallTest; 54 55 import com.android.modules.utils.build.SdkLevel; 56 import com.android.server.ConnectivityService; 57 import com.android.testutils.DevSdkIgnoreRule; 58 import com.android.testutils.DevSdkIgnoreRunner; 59 60 import org.junit.Before; 61 import org.junit.Test; 62 import org.junit.runner.RunWith; 63 import org.mockito.ArgumentCaptor; 64 import org.mockito.InOrder; 65 import org.mockito.Mock; 66 import org.mockito.MockitoAnnotations; 67 68 @RunWith(DevSdkIgnoreRunner.class) 69 @SmallTest 70 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) 71 public class Nat464XlatTest { 72 73 static final String BASE_IFACE = "test0"; 74 static final String STACKED_IFACE = "v4-test0"; 75 static final LinkAddress V6ADDR = new LinkAddress("2001:db8:1::f00/64"); 76 static final LinkAddress ADDR = new LinkAddress("192.0.2.5/29"); 77 static final String CLAT_V6 = "64:ff9b::1"; 78 static final String NAT64_PREFIX = "64:ff9b::/96"; 79 static final String OTHER_NAT64_PREFIX = "2001:db8:0:64::/96"; 80 static final int NETID = 42; 81 82 @Mock ConnectivityService mConnectivity; 83 @Mock IDnsResolver mDnsResolver; 84 @Mock INetd mNetd; 85 @Mock NetworkAgentInfo mNai; 86 @Mock ClatCoordinator mClatCoordinator; 87 88 TestLooper mLooper; 89 NetworkAgentConfig mAgentConfig = new NetworkAgentConfig(); 90 makeNat464Xlat(boolean isCellular464XlatEnabled)91 Nat464Xlat makeNat464Xlat(boolean isCellular464XlatEnabled) { 92 final ConnectivityService.Dependencies deps = new ConnectivityService.Dependencies() { 93 @Override public ClatCoordinator getClatCoordinator(INetd netd) { 94 return mClatCoordinator; 95 } 96 }; 97 98 // The test looper needs to be created here on the test case thread and not in setUp, 99 // because setUp and test cases are run in different threads. Creating the test looper in 100 // setUp would make Looper.getThread() return the setUp thread, which does not match the 101 // test case thread that is actually used to process the messages. 102 mLooper = new TestLooper(); 103 final Handler handler = new Handler(mLooper.getLooper()); 104 doReturn(handler).when(mNai).handler(); 105 106 return new Nat464Xlat(mNai, mNetd, mDnsResolver, deps) { 107 @Override protected int getNetId() { 108 return NETID; 109 } 110 111 @Override protected boolean isCellular464XlatEnabled() { 112 return isCellular464XlatEnabled; 113 } 114 }; 115 } 116 117 private void markNetworkConnected() { 118 mNai.networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", ""); 119 } 120 121 private void markNetworkDisconnected() { 122 mNai.networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, "", ""); 123 } 124 125 @Before 126 public void setUp() throws Exception { 127 MockitoAnnotations.initMocks(this); 128 129 mNai.linkProperties = new LinkProperties(); 130 mNai.linkProperties.setInterfaceName(BASE_IFACE); 131 mNai.networkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, 132 null /* typeName */, null /* subtypeName */); 133 mNai.networkCapabilities = new NetworkCapabilities(); 134 markNetworkConnected(); 135 when(mNai.connService()).thenReturn(mConnectivity); 136 when(mNai.netAgentConfig()).thenReturn(mAgentConfig); 137 final InterfaceConfigurationParcel mConfig = new InterfaceConfigurationParcel(); 138 when(mNetd.interfaceGetCfg(eq(STACKED_IFACE))).thenReturn(mConfig); 139 mConfig.ipv4Addr = ADDR.getAddress().getHostAddress(); 140 mConfig.prefixLength = ADDR.getPrefixLength(); 141 doReturn(CLAT_V6).when(mClatCoordinator).clatStart( 142 BASE_IFACE, NETID, new IpPrefix(NAT64_PREFIX)); 143 } 144 145 private void assertRequiresClat(boolean expected, NetworkAgentInfo nai) { 146 Nat464Xlat nat = makeNat464Xlat(true); 147 String msg = String.format("requiresClat expected %b for type=%d state=%s skip=%b " 148 + "nat64Prefix=%s addresses=%s", expected, nai.networkInfo.getType(), 149 nai.networkInfo.getDetailedState(), 150 mAgentConfig.skip464xlat, nai.linkProperties.getNat64Prefix(), 151 nai.linkProperties.getLinkAddresses()); 152 assertEquals(msg, expected, nat.requiresClat(nai)); 153 } 154 155 private void assertShouldStartClat(boolean expected, NetworkAgentInfo nai) { 156 Nat464Xlat nat = makeNat464Xlat(true); 157 String msg = String.format("shouldStartClat expected %b for type=%d state=%s skip=%b " 158 + "nat64Prefix=%s addresses=%s", expected, nai.networkInfo.getType(), 159 nai.networkInfo.getDetailedState(), 160 mAgentConfig.skip464xlat, nai.linkProperties.getNat64Prefix(), 161 nai.linkProperties.getLinkAddresses()); 162 assertEquals(msg, expected, nat.shouldStartClat(nai)); 163 } 164 165 @Test 166 public void testRequiresClat() throws Exception { 167 final int[] supportedTypes = { 168 ConnectivityManager.TYPE_MOBILE, 169 ConnectivityManager.TYPE_WIFI, 170 ConnectivityManager.TYPE_ETHERNET, 171 }; 172 173 // NetworkInfo doesn't allow setting the State directly, but rather 174 // requires setting DetailedState in order set State as a side-effect. 175 final NetworkInfo.DetailedState[] supportedDetailedStates = { 176 NetworkInfo.DetailedState.CONNECTED, 177 NetworkInfo.DetailedState.SUSPENDED, 178 }; 179 180 LinkProperties oldLp = new LinkProperties(mNai.linkProperties); 181 for (int type : supportedTypes) { 182 mNai.networkInfo.setType(type); 183 for (NetworkInfo.DetailedState state : supportedDetailedStates) { 184 mNai.networkInfo.setDetailedState(state, "reason", "extraInfo"); 185 186 mNai.linkProperties.setNat64Prefix(new IpPrefix(OTHER_NAT64_PREFIX)); 187 assertRequiresClat(false, mNai); 188 assertShouldStartClat(false, mNai); 189 190 mNai.linkProperties.addLinkAddress(new LinkAddress("fc00::1/64")); 191 assertRequiresClat(false, mNai); 192 assertShouldStartClat(false, mNai); 193 194 mNai.linkProperties.addLinkAddress(new LinkAddress("2001:db8::1/64")); 195 assertRequiresClat(true, mNai); 196 assertShouldStartClat(true, mNai); 197 198 mAgentConfig.skip464xlat = true; 199 assertRequiresClat(false, mNai); 200 assertShouldStartClat(false, mNai); 201 202 mAgentConfig.skip464xlat = false; 203 assertRequiresClat(true, mNai); 204 assertShouldStartClat(true, mNai); 205 206 mNai.linkProperties.addLinkAddress(new LinkAddress("192.0.2.2/24")); 207 assertRequiresClat(false, mNai); 208 assertShouldStartClat(false, mNai); 209 210 mNai.linkProperties.removeLinkAddress(new LinkAddress("192.0.2.2/24")); 211 assertRequiresClat(true, mNai); 212 assertShouldStartClat(true, mNai); 213 214 mNai.linkProperties.setNat64Prefix(null); 215 assertRequiresClat(true, mNai); 216 assertShouldStartClat(false, mNai); 217 218 mNai.linkProperties = new LinkProperties(oldLp); 219 } 220 } 221 } 222 223 private void makeClatUnnecessary(boolean dueToDisconnect) { 224 if (dueToDisconnect) { 225 markNetworkDisconnected(); 226 } else { 227 mNai.linkProperties.addLinkAddress(ADDR); 228 } 229 } 230 231 private <T> T verifyWithOrder(@Nullable InOrder inOrder, @NonNull T t) { 232 if (inOrder != null) { 233 return inOrder.verify(t); 234 } else { 235 return verify(t); 236 } 237 } 238 239 private void verifyClatdStart(@Nullable InOrder inOrder) throws Exception { 240 if (SdkLevel.isAtLeastT()) { 241 verifyWithOrder(inOrder, mClatCoordinator) 242 .clatStart(eq(BASE_IFACE), eq(NETID), eq(new IpPrefix(NAT64_PREFIX))); 243 } else { 244 verifyWithOrder(inOrder, mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX)); 245 } 246 } 247 248 private void verifyNeverClatdStart() throws Exception { 249 if (SdkLevel.isAtLeastT()) { 250 verify(mClatCoordinator, never()).clatStart(anyString(), anyInt(), any()); 251 } else { 252 verify(mNetd, never()).clatdStart(anyString(), anyString()); 253 } 254 } 255 256 private void verifyClatdStop(@Nullable InOrder inOrder) throws Exception { 257 if (SdkLevel.isAtLeastT()) { 258 verifyWithOrder(inOrder, mClatCoordinator).clatStop(); 259 } else { 260 verifyWithOrder(inOrder, mNetd).clatdStop(eq(BASE_IFACE)); 261 } 262 } 263 264 private void checkNormalStartAndStop(boolean dueToDisconnect) throws Exception { 265 Nat464Xlat nat = makeNat464Xlat(true); 266 ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class); 267 268 mNai.linkProperties.addLinkAddress(V6ADDR); 269 270 nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX)); 271 272 // Start clat. 273 nat.start(); 274 275 verifyClatdStart(null /* inOrder */); 276 277 // Stacked interface up notification arrives. 278 nat.handleInterfaceLinkStateChanged(STACKED_IFACE, true); 279 280 verify(mNetd).interfaceGetCfg(eq(STACKED_IFACE)); 281 verify(mConnectivity).handleUpdateLinkProperties(eq(mNai), c.capture()); 282 assertFalse(c.getValue().getStackedLinks().isEmpty()); 283 assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); 284 assertRunning(nat); 285 286 // Stop clat (Network disconnects, IPv4 addr appears, ...). 287 makeClatUnnecessary(dueToDisconnect); 288 nat.stop(); 289 290 verifyClatdStop(null /* inOrder */); 291 verify(mConnectivity, times(2)).handleUpdateLinkProperties(eq(mNai), c.capture()); 292 assertTrue(c.getValue().getStackedLinks().isEmpty()); 293 assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); 294 verify(mDnsResolver).stopPrefix64Discovery(eq(NETID)); 295 assertIdle(nat); 296 // Verify the generated v6 is reset when clat is stopped. 297 assertNull(nat.mIPv6Address); 298 // Stacked interface removed notification arrives and is ignored. 299 nat.handleInterfaceRemoved(STACKED_IFACE); 300 301 verifyNoMoreInteractions(mNetd, mConnectivity); 302 } 303 304 @Test 305 public void testNormalStartAndStopDueToDisconnect() throws Exception { 306 checkNormalStartAndStop(true); 307 } 308 309 @Test 310 public void testNormalStartAndStopDueToIpv4Addr() throws Exception { 311 checkNormalStartAndStop(false); 312 } 313 314 private void checkStartStopStart(boolean interfaceRemovedFirst) throws Exception { 315 Nat464Xlat nat = makeNat464Xlat(true); 316 ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class); 317 InOrder inOrder = inOrder(mNetd, mConnectivity, mClatCoordinator); 318 319 mNai.linkProperties.addLinkAddress(V6ADDR); 320 321 nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX)); 322 323 nat.start(); 324 325 verifyClatdStart(inOrder); 326 327 // Stacked interface up notification arrives. 328 nat.handleInterfaceLinkStateChanged(STACKED_IFACE, true); 329 330 inOrder.verify(mConnectivity).handleUpdateLinkProperties(eq(mNai), c.capture()); 331 assertFalse(c.getValue().getStackedLinks().isEmpty()); 332 assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); 333 assertRunning(nat); 334 335 // ConnectivityService stops clat (Network disconnects, IPv4 addr appears, ...). 336 nat.stop(); 337 338 verifyClatdStop(inOrder); 339 340 inOrder.verify(mConnectivity, times(1)).handleUpdateLinkProperties(eq(mNai), c.capture()); 341 assertTrue(c.getValue().getStackedLinks().isEmpty()); 342 assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); 343 assertIdle(nat); 344 345 if (interfaceRemovedFirst) { 346 // Stacked interface removed notification arrives and is ignored. 347 nat.handleInterfaceRemoved(STACKED_IFACE); 348 nat.handleInterfaceLinkStateChanged(STACKED_IFACE, false); 349 } 350 351 assertTrue(c.getValue().getStackedLinks().isEmpty()); 352 assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); 353 assertIdle(nat); 354 inOrder.verifyNoMoreInteractions(); 355 356 nat.start(); 357 358 verifyClatdStart(inOrder); 359 360 if (!interfaceRemovedFirst) { 361 // Stacked interface removed notification arrives and is ignored. 362 nat.handleInterfaceRemoved(STACKED_IFACE); 363 nat.handleInterfaceLinkStateChanged(STACKED_IFACE, false); 364 } 365 366 // Stacked interface up notification arrives. 367 nat.handleInterfaceLinkStateChanged(STACKED_IFACE, true); 368 369 inOrder.verify(mConnectivity).handleUpdateLinkProperties(eq(mNai), c.capture()); 370 assertFalse(c.getValue().getStackedLinks().isEmpty()); 371 assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); 372 assertRunning(nat); 373 374 // ConnectivityService stops clat again. 375 nat.stop(); 376 377 verifyClatdStop(inOrder); 378 379 inOrder.verify(mConnectivity, times(1)).handleUpdateLinkProperties(eq(mNai), c.capture()); 380 assertTrue(c.getValue().getStackedLinks().isEmpty()); 381 assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); 382 assertIdle(nat); 383 384 inOrder.verifyNoMoreInteractions(); 385 } 386 387 @Test 388 public void testStartStopStart() throws Exception { 389 checkStartStopStart(true); 390 } 391 392 @Test 393 public void testStartStopStartBeforeInterfaceRemoved() throws Exception { 394 checkStartStopStart(false); 395 } 396 397 @Test 398 public void testClatdCrashWhileRunning() throws Exception { 399 Nat464Xlat nat = makeNat464Xlat(true); 400 ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class); 401 402 nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX)); 403 404 nat.start(); 405 406 verifyClatdStart(null /* inOrder */); 407 408 // Stacked interface up notification arrives. 409 nat.handleInterfaceLinkStateChanged(STACKED_IFACE, true); 410 411 verify(mNetd).interfaceGetCfg(eq(STACKED_IFACE)); 412 verify(mConnectivity, times(1)).handleUpdateLinkProperties(eq(mNai), c.capture()); 413 assertFalse(c.getValue().getStackedLinks().isEmpty()); 414 assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); 415 assertRunning(nat); 416 417 // Stacked interface removed notification arrives (clatd crashed, ...). 418 nat.handleInterfaceRemoved(STACKED_IFACE); 419 420 verifyClatdStop(null /* inOrder */); 421 verify(mConnectivity, times(2)).handleUpdateLinkProperties(eq(mNai), c.capture()); 422 verify(mDnsResolver).stopPrefix64Discovery(eq(NETID)); 423 assertTrue(c.getValue().getStackedLinks().isEmpty()); 424 assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); 425 assertIdle(nat); 426 427 // ConnectivityService stops clat: no-op. 428 nat.stop(); 429 430 verifyNoMoreInteractions(mNetd, mConnectivity); 431 } 432 433 private void checkStopBeforeClatdStarts(boolean dueToDisconnect) throws Exception { 434 Nat464Xlat nat = makeNat464Xlat(true); 435 436 mNai.linkProperties.addLinkAddress(new LinkAddress("2001:db8::1/64")); 437 438 nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX)); 439 440 nat.start(); 441 442 verifyClatdStart(null /* inOrder */); 443 444 // ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...) 445 makeClatUnnecessary(dueToDisconnect); 446 nat.stop(); 447 448 verifyClatdStop(null /* inOrder */); 449 verify(mDnsResolver).stopPrefix64Discovery(eq(NETID)); 450 assertIdle(nat); 451 452 // In-flight interface up notification arrives: no-op 453 nat.handleInterfaceLinkStateChanged(STACKED_IFACE, true); 454 455 // Interface removed notification arrives after stopClatd() takes effect: no-op. 456 nat.handleInterfaceRemoved(STACKED_IFACE); 457 458 assertIdle(nat); 459 460 verifyNoMoreInteractions(mNetd, mConnectivity); 461 } 462 463 @Test 464 public void testStopDueToDisconnectBeforeClatdStarts() throws Exception { 465 checkStopBeforeClatdStarts(true); 466 } 467 468 @Test 469 public void testStopDueToIpv4AddrBeforeClatdStarts() throws Exception { 470 checkStopBeforeClatdStarts(false); 471 } 472 473 private void checkStopAndClatdNeverStarts(boolean dueToDisconnect) throws Exception { 474 Nat464Xlat nat = makeNat464Xlat(true); 475 476 mNai.linkProperties.addLinkAddress(new LinkAddress("2001:db8::1/64")); 477 478 nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX)); 479 480 nat.start(); 481 482 verifyClatdStart(null /* inOrder */); 483 484 // ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...) 485 makeClatUnnecessary(dueToDisconnect); 486 nat.stop(); 487 488 verifyClatdStop(null /* inOrder */); 489 verify(mDnsResolver).stopPrefix64Discovery(eq(NETID)); 490 assertIdle(nat); 491 492 verifyNoMoreInteractions(mNetd, mConnectivity); 493 } 494 495 @Test 496 public void testStopDueToDisconnectAndClatdNeverStarts() throws Exception { 497 checkStopAndClatdNeverStarts(true); 498 } 499 500 @Test 501 public void testStopDueToIpv4AddressAndClatdNeverStarts() throws Exception { 502 checkStopAndClatdNeverStarts(false); 503 } 504 505 @Test 506 public void testNat64PrefixPreference() throws Exception { 507 final IpPrefix prefixFromDns = new IpPrefix(NAT64_PREFIX); 508 final IpPrefix prefixFromRa = new IpPrefix(OTHER_NAT64_PREFIX); 509 510 Nat464Xlat nat = makeNat464Xlat(true); 511 512 final LinkProperties emptyLp = new LinkProperties(); 513 LinkProperties fixedupLp; 514 515 fixedupLp = new LinkProperties(); 516 nat.setNat64PrefixFromDns(prefixFromDns); 517 nat.fixupLinkProperties(emptyLp, fixedupLp); 518 assertEquals(prefixFromDns, fixedupLp.getNat64Prefix()); 519 520 fixedupLp = new LinkProperties(); 521 nat.setNat64PrefixFromRa(prefixFromRa); 522 nat.fixupLinkProperties(emptyLp, fixedupLp); 523 assertEquals(prefixFromRa, fixedupLp.getNat64Prefix()); 524 525 fixedupLp = new LinkProperties(); 526 nat.setNat64PrefixFromRa(null); 527 nat.fixupLinkProperties(emptyLp, fixedupLp); 528 assertEquals(prefixFromDns, fixedupLp.getNat64Prefix()); 529 530 fixedupLp = new LinkProperties(); 531 nat.setNat64PrefixFromRa(prefixFromRa); 532 nat.fixupLinkProperties(emptyLp, fixedupLp); 533 assertEquals(prefixFromRa, fixedupLp.getNat64Prefix()); 534 535 fixedupLp = new LinkProperties(); 536 nat.setNat64PrefixFromDns(null); 537 nat.fixupLinkProperties(emptyLp, fixedupLp); 538 assertEquals(prefixFromRa, fixedupLp.getNat64Prefix()); 539 540 fixedupLp = new LinkProperties(); 541 nat.setNat64PrefixFromRa(null); 542 nat.fixupLinkProperties(emptyLp, fixedupLp); 543 assertEquals(null, fixedupLp.getNat64Prefix()); 544 } 545 546 private void checkClatDisabledOnCellular(boolean onCellular) throws Exception { 547 // Disable 464xlat on cellular networks. 548 Nat464Xlat nat = makeNat464Xlat(false); 549 mNai.linkProperties.addLinkAddress(V6ADDR); 550 mNai.networkCapabilities.setTransportType(TRANSPORT_CELLULAR, onCellular); 551 nat.update(); 552 553 final IpPrefix nat64Prefix = new IpPrefix(NAT64_PREFIX); 554 if (onCellular) { 555 // Prefix discovery is never started. 556 verify(mDnsResolver, never()).startPrefix64Discovery(eq(NETID)); 557 assertIdle(nat); 558 559 // If a NAT64 prefix comes in from an RA, clat is not started either. 560 mNai.linkProperties.setNat64Prefix(nat64Prefix); 561 nat.setNat64PrefixFromRa(nat64Prefix); 562 nat.update(); 563 verifyNeverClatdStart(); 564 assertIdle(nat); 565 } else { 566 // Prefix discovery is started. 567 verify(mDnsResolver).startPrefix64Discovery(eq(NETID)); 568 assertIdle(nat); 569 570 // If a NAT64 prefix comes in from an RA, clat is started. 571 mNai.linkProperties.setNat64Prefix(nat64Prefix); 572 nat.setNat64PrefixFromRa(nat64Prefix); 573 nat.update(); 574 verifyClatdStart(null /* inOrder */); 575 assertStarting(nat); 576 } 577 } 578 579 @Test 580 public void testClatDisabledOnCellular() throws Exception { 581 checkClatDisabledOnCellular(true); 582 } 583 584 @Test 585 public void testClatDisabledOnNonCellular() throws Exception { 586 checkClatDisabledOnCellular(false); 587 } 588 589 static void assertIdle(Nat464Xlat nat) { 590 assertTrue("Nat464Xlat was not IDLE", !nat.isStarted()); 591 } 592 593 static void assertStarting(Nat464Xlat nat) { 594 assertTrue("Nat464Xlat was not STARTING", nat.isStarting()); 595 } 596 597 static void assertRunning(Nat464Xlat nat) { 598 assertTrue("Nat464Xlat was not RUNNING", nat.isRunning()); 599 } 600 } 601