Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 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 | |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 19 | import static org.junit.Assert.assertEquals; |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 20 | import static org.junit.Assert.assertFalse; |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 21 | import static org.junit.Assert.assertTrue; |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 22 | import static org.mockito.Mockito.eq; |
Lorenzo Colitti | df59563 | 2019-01-08 14:43:37 +0900 | [diff] [blame] | 23 | import static org.mockito.Mockito.inOrder; |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 24 | import static org.mockito.Mockito.times; |
| 25 | import static org.mockito.Mockito.verify; |
| 26 | import static org.mockito.Mockito.verifyNoMoreInteractions; |
| 27 | import static org.mockito.Mockito.when; |
| 28 | |
| 29 | import android.net.ConnectivityManager; |
Luke Huang | 6591477 | 2019-03-16 00:31:46 +0800 | [diff] [blame] | 30 | import android.net.IDnsResolver; |
Lorenzo Colitti | 9307ca2 | 2019-01-12 01:54:23 +0900 | [diff] [blame] | 31 | import android.net.INetd; |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 32 | import android.net.InterfaceConfiguration; |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 33 | import android.net.IpPrefix; |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 34 | import android.net.LinkAddress; |
| 35 | import android.net.LinkProperties; |
| 36 | import android.net.NetworkInfo; |
soma, kawata | 88b8f63 | 2018-10-23 21:10:02 +0900 | [diff] [blame] | 37 | import android.net.NetworkMisc; |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 38 | import android.os.Handler; |
| 39 | import android.os.INetworkManagementService; |
| 40 | import android.os.test.TestLooper; |
Brett Chabot | 1ae2aa6 | 2019-03-04 14:14:56 -0800 | [diff] [blame] | 41 | |
| 42 | import androidx.test.filters.SmallTest; |
| 43 | import androidx.test.runner.AndroidJUnit4; |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 44 | |
| 45 | import com.android.server.ConnectivityService; |
| 46 | |
| 47 | import org.junit.Before; |
| 48 | import org.junit.Test; |
| 49 | import org.junit.runner.RunWith; |
| 50 | import org.mockito.ArgumentCaptor; |
Lorenzo Colitti | df59563 | 2019-01-08 14:43:37 +0900 | [diff] [blame] | 51 | import org.mockito.InOrder; |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 52 | import org.mockito.Mock; |
| 53 | import org.mockito.MockitoAnnotations; |
| 54 | |
| 55 | @RunWith(AndroidJUnit4.class) |
| 56 | @SmallTest |
| 57 | public class Nat464XlatTest { |
| 58 | |
| 59 | static final String BASE_IFACE = "test0"; |
| 60 | static final String STACKED_IFACE = "v4-test0"; |
| 61 | static final LinkAddress ADDR = new LinkAddress("192.0.2.5/29"); |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 62 | static final String NAT64_PREFIX = "64:ff9b::/96"; |
Lorenzo Colitti | d593e29 | 2019-02-19 13:21:56 +0900 | [diff] [blame] | 63 | static final int NETID = 42; |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 64 | |
| 65 | @Mock ConnectivityService mConnectivity; |
soma, kawata | 88b8f63 | 2018-10-23 21:10:02 +0900 | [diff] [blame] | 66 | @Mock NetworkMisc mMisc; |
Luke Huang | 6591477 | 2019-03-16 00:31:46 +0800 | [diff] [blame] | 67 | @Mock IDnsResolver mDnsResolver; |
Lorenzo Colitti | 9307ca2 | 2019-01-12 01:54:23 +0900 | [diff] [blame] | 68 | @Mock INetd mNetd; |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 69 | @Mock INetworkManagementService mNms; |
| 70 | @Mock InterfaceConfiguration mConfig; |
| 71 | @Mock NetworkAgentInfo mNai; |
| 72 | |
| 73 | TestLooper mLooper; |
| 74 | Handler mHandler; |
| 75 | |
| 76 | Nat464Xlat makeNat464Xlat() { |
Luke Huang | 6591477 | 2019-03-16 00:31:46 +0800 | [diff] [blame] | 77 | return new Nat464Xlat(mNai, mNetd, mDnsResolver, mNms) { |
Lorenzo Colitti | d593e29 | 2019-02-19 13:21:56 +0900 | [diff] [blame] | 78 | @Override protected int getNetId() { |
| 79 | return NETID; |
| 80 | } |
| 81 | }; |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 82 | } |
| 83 | |
| 84 | @Before |
| 85 | public void setUp() throws Exception { |
| 86 | mLooper = new TestLooper(); |
| 87 | mHandler = new Handler(mLooper.getLooper()); |
| 88 | |
| 89 | MockitoAnnotations.initMocks(this); |
| 90 | |
| 91 | mNai.linkProperties = new LinkProperties(); |
| 92 | mNai.linkProperties.setInterfaceName(BASE_IFACE); |
| 93 | mNai.networkInfo = new NetworkInfo(null); |
| 94 | mNai.networkInfo.setType(ConnectivityManager.TYPE_WIFI); |
| 95 | when(mNai.connService()).thenReturn(mConnectivity); |
soma, kawata | 88b8f63 | 2018-10-23 21:10:02 +0900 | [diff] [blame] | 96 | when(mNai.netMisc()).thenReturn(mMisc); |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 97 | when(mNai.handler()).thenReturn(mHandler); |
| 98 | |
| 99 | when(mNms.getInterfaceConfig(eq(STACKED_IFACE))).thenReturn(mConfig); |
| 100 | when(mConfig.getLinkAddress()).thenReturn(ADDR); |
| 101 | } |
| 102 | |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 103 | private void assertRequiresClat(boolean expected, NetworkAgentInfo nai) { |
Lorenzo Colitti | d593e29 | 2019-02-19 13:21:56 +0900 | [diff] [blame] | 104 | String msg = String.format("requiresClat expected %b for type=%d state=%s skip=%b " |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 105 | + "nat64Prefix=%s addresses=%s", expected, nai.networkInfo.getType(), |
| 106 | nai.networkInfo.getDetailedState(), |
| 107 | mMisc.skip464xlat, nai.linkProperties.getNat64Prefix(), |
| 108 | nai.linkProperties.getLinkAddresses()); |
| 109 | assertEquals(msg, expected, Nat464Xlat.requiresClat(nai)); |
| 110 | } |
| 111 | |
Lorenzo Colitti | d593e29 | 2019-02-19 13:21:56 +0900 | [diff] [blame] | 112 | private void assertShouldStartClat(boolean expected, NetworkAgentInfo nai) { |
| 113 | String msg = String.format("shouldStartClat expected %b for type=%d state=%s skip=%b " |
| 114 | + "nat64Prefix=%s addresses=%s", expected, nai.networkInfo.getType(), |
| 115 | nai.networkInfo.getDetailedState(), |
| 116 | mMisc.skip464xlat, nai.linkProperties.getNat64Prefix(), |
| 117 | nai.linkProperties.getLinkAddresses()); |
| 118 | assertEquals(msg, expected, Nat464Xlat.shouldStartClat(nai)); |
| 119 | } |
| 120 | |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 121 | @Test |
Erik Kline | 3c18216 | 2017-09-21 17:28:10 +0900 | [diff] [blame] | 122 | public void testRequiresClat() throws Exception { |
| 123 | final int[] supportedTypes = { |
| 124 | ConnectivityManager.TYPE_MOBILE, |
| 125 | ConnectivityManager.TYPE_WIFI, |
| 126 | ConnectivityManager.TYPE_ETHERNET, |
| 127 | }; |
| 128 | |
| 129 | // NetworkInfo doesn't allow setting the State directly, but rather |
| 130 | // requires setting DetailedState in order set State as a side-effect. |
| 131 | final NetworkInfo.DetailedState[] supportedDetailedStates = { |
| 132 | NetworkInfo.DetailedState.CONNECTED, |
| 133 | NetworkInfo.DetailedState.SUSPENDED, |
| 134 | }; |
| 135 | |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 136 | LinkProperties oldLp = new LinkProperties(mNai.linkProperties); |
Erik Kline | 3c18216 | 2017-09-21 17:28:10 +0900 | [diff] [blame] | 137 | for (int type : supportedTypes) { |
| 138 | mNai.networkInfo.setType(type); |
| 139 | for (NetworkInfo.DetailedState state : supportedDetailedStates) { |
| 140 | mNai.networkInfo.setDetailedState(state, "reason", "extraInfo"); |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 141 | |
| 142 | mNai.linkProperties.setNat64Prefix(new IpPrefix("2001:db8:0:64::/96")); |
| 143 | assertRequiresClat(false, mNai); |
Lorenzo Colitti | d593e29 | 2019-02-19 13:21:56 +0900 | [diff] [blame] | 144 | assertShouldStartClat(false, mNai); |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 145 | |
| 146 | mNai.linkProperties.addLinkAddress(new LinkAddress("fc00::1/64")); |
| 147 | assertRequiresClat(false, mNai); |
Lorenzo Colitti | d593e29 | 2019-02-19 13:21:56 +0900 | [diff] [blame] | 148 | assertShouldStartClat(false, mNai); |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 149 | |
| 150 | mNai.linkProperties.addLinkAddress(new LinkAddress("2001:db8::1/64")); |
| 151 | assertRequiresClat(true, mNai); |
Lorenzo Colitti | d593e29 | 2019-02-19 13:21:56 +0900 | [diff] [blame] | 152 | assertShouldStartClat(true, mNai); |
soma, kawata | 88b8f63 | 2018-10-23 21:10:02 +0900 | [diff] [blame] | 153 | |
| 154 | mMisc.skip464xlat = true; |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 155 | assertRequiresClat(false, mNai); |
Lorenzo Colitti | d593e29 | 2019-02-19 13:21:56 +0900 | [diff] [blame] | 156 | assertShouldStartClat(false, mNai); |
soma, kawata | 88b8f63 | 2018-10-23 21:10:02 +0900 | [diff] [blame] | 157 | |
| 158 | mMisc.skip464xlat = false; |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 159 | assertRequiresClat(true, mNai); |
Lorenzo Colitti | d593e29 | 2019-02-19 13:21:56 +0900 | [diff] [blame] | 160 | assertShouldStartClat(true, mNai); |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 161 | |
| 162 | mNai.linkProperties.addLinkAddress(new LinkAddress("192.0.2.2/24")); |
| 163 | assertRequiresClat(false, mNai); |
Lorenzo Colitti | d593e29 | 2019-02-19 13:21:56 +0900 | [diff] [blame] | 164 | assertShouldStartClat(false, mNai); |
| 165 | |
| 166 | mNai.linkProperties.removeLinkAddress(new LinkAddress("192.0.2.2/24")); |
| 167 | assertRequiresClat(true, mNai); |
| 168 | assertShouldStartClat(true, mNai); |
| 169 | |
| 170 | mNai.linkProperties.setNat64Prefix(null); |
| 171 | assertRequiresClat(true, mNai); |
| 172 | assertShouldStartClat(false, mNai); |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 173 | |
| 174 | mNai.linkProperties = new LinkProperties(oldLp); |
Erik Kline | 3c18216 | 2017-09-21 17:28:10 +0900 | [diff] [blame] | 175 | } |
| 176 | } |
| 177 | } |
| 178 | |
| 179 | @Test |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 180 | public void testNormalStartAndStop() throws Exception { |
| 181 | Nat464Xlat nat = makeNat464Xlat(); |
| 182 | ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class); |
| 183 | |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 184 | nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX)); |
| 185 | |
Lorenzo Colitti | d593e29 | 2019-02-19 13:21:56 +0900 | [diff] [blame] | 186 | // Start clat. |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 187 | nat.start(); |
| 188 | |
| 189 | verify(mNms).registerObserver(eq(nat)); |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 190 | verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX)); |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 191 | |
| 192 | // Stacked interface up notification arrives. |
| 193 | nat.interfaceLinkStateChanged(STACKED_IFACE, true); |
| 194 | mLooper.dispatchNext(); |
| 195 | |
| 196 | verify(mNms).getInterfaceConfig(eq(STACKED_IFACE)); |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 197 | verify(mConnectivity).handleUpdateLinkProperties(eq(mNai), c.capture()); |
| 198 | assertFalse(c.getValue().getStackedLinks().isEmpty()); |
| 199 | assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); |
| 200 | assertRunning(nat); |
| 201 | |
Lorenzo Colitti | d593e29 | 2019-02-19 13:21:56 +0900 | [diff] [blame] | 202 | // Stop clat (Network disconnects, IPv4 addr appears, ...). |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 203 | nat.stop(); |
| 204 | |
Lorenzo Colitti | 9307ca2 | 2019-01-12 01:54:23 +0900 | [diff] [blame] | 205 | verify(mNetd).clatdStop(eq(BASE_IFACE)); |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 206 | verify(mConnectivity, times(2)).handleUpdateLinkProperties(eq(mNai), c.capture()); |
Lorenzo Colitti | df59563 | 2019-01-08 14:43:37 +0900 | [diff] [blame] | 207 | verify(mNms).unregisterObserver(eq(nat)); |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 208 | assertTrue(c.getValue().getStackedLinks().isEmpty()); |
| 209 | assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); |
Luke Huang | 6591477 | 2019-03-16 00:31:46 +0800 | [diff] [blame] | 210 | verify(mDnsResolver).stopPrefix64Discovery(eq(NETID)); |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 211 | assertIdle(nat); |
| 212 | |
Lorenzo Colitti | df59563 | 2019-01-08 14:43:37 +0900 | [diff] [blame] | 213 | // Stacked interface removed notification arrives and is ignored. |
| 214 | nat.interfaceRemoved(STACKED_IFACE); |
| 215 | mLooper.dispatchNext(); |
| 216 | |
Lorenzo Colitti | 9307ca2 | 2019-01-12 01:54:23 +0900 | [diff] [blame] | 217 | verifyNoMoreInteractions(mNetd, mNms, mConnectivity); |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 218 | } |
| 219 | |
Lorenzo Colitti | df59563 | 2019-01-08 14:43:37 +0900 | [diff] [blame] | 220 | private void checkStartStopStart(boolean interfaceRemovedFirst) throws Exception { |
| 221 | Nat464Xlat nat = makeNat464Xlat(); |
| 222 | ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class); |
| 223 | InOrder inOrder = inOrder(mNetd, mConnectivity); |
| 224 | |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 225 | nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX)); |
| 226 | |
Lorenzo Colitti | df59563 | 2019-01-08 14:43:37 +0900 | [diff] [blame] | 227 | nat.start(); |
| 228 | |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 229 | inOrder.verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX)); |
Lorenzo Colitti | df59563 | 2019-01-08 14:43:37 +0900 | [diff] [blame] | 230 | |
| 231 | // Stacked interface up notification arrives. |
| 232 | nat.interfaceLinkStateChanged(STACKED_IFACE, true); |
| 233 | mLooper.dispatchNext(); |
| 234 | |
| 235 | inOrder.verify(mConnectivity).handleUpdateLinkProperties(eq(mNai), c.capture()); |
| 236 | assertFalse(c.getValue().getStackedLinks().isEmpty()); |
| 237 | assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); |
| 238 | assertRunning(nat); |
| 239 | |
| 240 | // ConnectivityService stops clat (Network disconnects, IPv4 addr appears, ...). |
| 241 | nat.stop(); |
| 242 | |
| 243 | inOrder.verify(mNetd).clatdStop(eq(BASE_IFACE)); |
| 244 | |
| 245 | inOrder.verify(mConnectivity, times(1)).handleUpdateLinkProperties(eq(mNai), c.capture()); |
| 246 | assertTrue(c.getValue().getStackedLinks().isEmpty()); |
| 247 | assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); |
| 248 | assertIdle(nat); |
| 249 | |
| 250 | if (interfaceRemovedFirst) { |
| 251 | // Stacked interface removed notification arrives and is ignored. |
| 252 | nat.interfaceRemoved(STACKED_IFACE); |
| 253 | mLooper.dispatchNext(); |
| 254 | nat.interfaceLinkStateChanged(STACKED_IFACE, false); |
| 255 | mLooper.dispatchNext(); |
| 256 | } |
| 257 | |
| 258 | assertTrue(c.getValue().getStackedLinks().isEmpty()); |
| 259 | assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); |
| 260 | assertIdle(nat); |
| 261 | inOrder.verifyNoMoreInteractions(); |
| 262 | |
Lorenzo Colitti | df59563 | 2019-01-08 14:43:37 +0900 | [diff] [blame] | 263 | nat.start(); |
| 264 | |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 265 | inOrder.verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX)); |
Lorenzo Colitti | df59563 | 2019-01-08 14:43:37 +0900 | [diff] [blame] | 266 | |
| 267 | if (!interfaceRemovedFirst) { |
| 268 | // Stacked interface removed notification arrives and is ignored. |
| 269 | nat.interfaceRemoved(STACKED_IFACE); |
| 270 | mLooper.dispatchNext(); |
| 271 | nat.interfaceLinkStateChanged(STACKED_IFACE, false); |
| 272 | mLooper.dispatchNext(); |
| 273 | } |
| 274 | |
| 275 | // Stacked interface up notification arrives. |
| 276 | nat.interfaceLinkStateChanged(STACKED_IFACE, true); |
| 277 | mLooper.dispatchNext(); |
| 278 | |
| 279 | inOrder.verify(mConnectivity).handleUpdateLinkProperties(eq(mNai), c.capture()); |
| 280 | assertFalse(c.getValue().getStackedLinks().isEmpty()); |
| 281 | assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); |
| 282 | assertRunning(nat); |
| 283 | |
| 284 | // ConnectivityService stops clat again. |
| 285 | nat.stop(); |
| 286 | |
| 287 | inOrder.verify(mNetd).clatdStop(eq(BASE_IFACE)); |
| 288 | |
| 289 | inOrder.verify(mConnectivity, times(1)).handleUpdateLinkProperties(eq(mNai), c.capture()); |
| 290 | assertTrue(c.getValue().getStackedLinks().isEmpty()); |
| 291 | assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); |
| 292 | assertIdle(nat); |
| 293 | |
| 294 | inOrder.verifyNoMoreInteractions(); |
| 295 | } |
| 296 | |
| 297 | @Test |
| 298 | public void testStartStopStart() throws Exception { |
| 299 | checkStartStopStart(true); |
| 300 | } |
| 301 | |
| 302 | @Test |
| 303 | public void testStartStopStartBeforeInterfaceRemoved() throws Exception { |
| 304 | checkStartStopStart(false); |
| 305 | } |
| 306 | |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 307 | @Test |
| 308 | public void testClatdCrashWhileRunning() throws Exception { |
| 309 | Nat464Xlat nat = makeNat464Xlat(); |
| 310 | ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class); |
| 311 | |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 312 | nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX)); |
| 313 | |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 314 | nat.start(); |
| 315 | |
| 316 | verify(mNms).registerObserver(eq(nat)); |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 317 | verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX)); |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 318 | |
| 319 | // Stacked interface up notification arrives. |
| 320 | nat.interfaceLinkStateChanged(STACKED_IFACE, true); |
| 321 | mLooper.dispatchNext(); |
| 322 | |
| 323 | verify(mNms).getInterfaceConfig(eq(STACKED_IFACE)); |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 324 | verify(mConnectivity, times(1)).handleUpdateLinkProperties(eq(mNai), c.capture()); |
| 325 | assertFalse(c.getValue().getStackedLinks().isEmpty()); |
| 326 | assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); |
| 327 | assertRunning(nat); |
| 328 | |
| 329 | // Stacked interface removed notification arrives (clatd crashed, ...). |
| 330 | nat.interfaceRemoved(STACKED_IFACE); |
| 331 | mLooper.dispatchNext(); |
| 332 | |
Lorenzo Colitti | 9307ca2 | 2019-01-12 01:54:23 +0900 | [diff] [blame] | 333 | verify(mNetd).clatdStop(eq(BASE_IFACE)); |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 334 | verify(mConnectivity, times(2)).handleUpdateLinkProperties(eq(mNai), c.capture()); |
Lorenzo Colitti | df59563 | 2019-01-08 14:43:37 +0900 | [diff] [blame] | 335 | verify(mNms).unregisterObserver(eq(nat)); |
Luke Huang | 6591477 | 2019-03-16 00:31:46 +0800 | [diff] [blame] | 336 | verify(mDnsResolver).stopPrefix64Discovery(eq(NETID)); |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 337 | assertTrue(c.getValue().getStackedLinks().isEmpty()); |
| 338 | assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); |
| 339 | assertIdle(nat); |
| 340 | |
| 341 | // ConnectivityService stops clat: no-op. |
| 342 | nat.stop(); |
| 343 | |
Lorenzo Colitti | 9307ca2 | 2019-01-12 01:54:23 +0900 | [diff] [blame] | 344 | verifyNoMoreInteractions(mNetd, mNms, mConnectivity); |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 345 | } |
| 346 | |
| 347 | @Test |
| 348 | public void testStopBeforeClatdStarts() throws Exception { |
| 349 | Nat464Xlat nat = makeNat464Xlat(); |
| 350 | |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 351 | nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX)); |
| 352 | |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 353 | nat.start(); |
| 354 | |
| 355 | verify(mNms).registerObserver(eq(nat)); |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 356 | verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX)); |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 357 | |
| 358 | // ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...) |
| 359 | nat.stop(); |
| 360 | |
Lorenzo Colitti | 9307ca2 | 2019-01-12 01:54:23 +0900 | [diff] [blame] | 361 | verify(mNetd).clatdStop(eq(BASE_IFACE)); |
Lorenzo Colitti | df59563 | 2019-01-08 14:43:37 +0900 | [diff] [blame] | 362 | verify(mNms).unregisterObserver(eq(nat)); |
Luke Huang | 6591477 | 2019-03-16 00:31:46 +0800 | [diff] [blame] | 363 | verify(mDnsResolver).stopPrefix64Discovery(eq(NETID)); |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 364 | assertIdle(nat); |
| 365 | |
| 366 | // In-flight interface up notification arrives: no-op |
| 367 | nat.interfaceLinkStateChanged(STACKED_IFACE, true); |
| 368 | mLooper.dispatchNext(); |
| 369 | |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 370 | // Interface removed notification arrives after stopClatd() takes effect: no-op. |
| 371 | nat.interfaceRemoved(STACKED_IFACE); |
| 372 | mLooper.dispatchNext(); |
| 373 | |
| 374 | assertIdle(nat); |
| 375 | |
Lorenzo Colitti | 9307ca2 | 2019-01-12 01:54:23 +0900 | [diff] [blame] | 376 | verifyNoMoreInteractions(mNetd, mNms, mConnectivity); |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 377 | } |
| 378 | |
| 379 | @Test |
| 380 | public void testStopAndClatdNeverStarts() throws Exception { |
| 381 | Nat464Xlat nat = makeNat464Xlat(); |
| 382 | |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 383 | nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX)); |
| 384 | |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 385 | nat.start(); |
| 386 | |
| 387 | verify(mNms).registerObserver(eq(nat)); |
Lorenzo Colitti | 6998fa8 | 2019-01-08 10:04:25 +0900 | [diff] [blame] | 388 | verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX)); |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 389 | |
| 390 | // ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...) |
| 391 | nat.stop(); |
| 392 | |
Lorenzo Colitti | 9307ca2 | 2019-01-12 01:54:23 +0900 | [diff] [blame] | 393 | verify(mNetd).clatdStop(eq(BASE_IFACE)); |
Lorenzo Colitti | df59563 | 2019-01-08 14:43:37 +0900 | [diff] [blame] | 394 | verify(mNms).unregisterObserver(eq(nat)); |
Luke Huang | 6591477 | 2019-03-16 00:31:46 +0800 | [diff] [blame] | 395 | verify(mDnsResolver).stopPrefix64Discovery(eq(NETID)); |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 396 | assertIdle(nat); |
| 397 | |
Lorenzo Colitti | 9307ca2 | 2019-01-12 01:54:23 +0900 | [diff] [blame] | 398 | verifyNoMoreInteractions(mNetd, mNms, mConnectivity); |
Hugo Benichi | ef50288 | 2017-09-01 01:23:32 +0000 | [diff] [blame] | 399 | } |
| 400 | |
| 401 | static void assertIdle(Nat464Xlat nat) { |
| 402 | assertTrue("Nat464Xlat was not IDLE", !nat.isStarted()); |
| 403 | } |
| 404 | |
| 405 | static void assertRunning(Nat464Xlat nat) { |
| 406 | assertTrue("Nat464Xlat was not RUNNING", nat.isRunning()); |
| 407 | } |
| 408 | } |