From 0f37ecb31e0cc3367a897920ea121bc0870e5738 Mon Sep 17 00:00:00 2001 From: Nate Jiang Date: Wed, 27 May 2020 12:17:52 -0700 Subject: [AWARE] Loop retry to get valid IPv6 address and verify usablity Bug: 155255680 Test: atest com.android.server.wifi Test: acts DataPathTest Change-Id: I20d62ac93298c1609a5edc18b369c31521076ccb --- .../wifi/aware/WifiAwareDataPathStateManager.java | 146 ++++++++++----------- .../aware/WifiAwareDataPathStateManagerTest.java | 34 +++-- 2 files changed, 94 insertions(+), 86 deletions(-) diff --git a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java index 49ce8ad6f..e190a2454 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java @@ -568,12 +568,7 @@ public class WifiAwareDataPathStateManager { nnri.peerDataMac = mac; nnri.channelInfo = channelInfo; - final NetworkCapabilities.Builder ncBuilder = new NetworkCapabilities.Builder( - sNetworkCapabilitiesFilter); - LinkProperties linkProperties = new LinkProperties(); - - boolean interfaceUsedByAnotherNdp = isInterfaceUpAndUsedByAnotherNdp(nnri); - if (!interfaceUsedByAnotherNdp) { + if (!isInterfaceUpAndUsedByAnotherNdp(nnri)) { try { mNetdWrapper.setInterfaceUp(nnri.interfaceName); mNetdWrapper.enableIpv6(nnri.interfaceName); @@ -609,59 +604,8 @@ public class WifiAwareDataPathStateManager { } } - try { - if (nnri.peerIpv6Override == null) { - nnri.peerIpv6 = Inet6Address.getByAddress(null, - MacAddress.fromBytes(mac).getLinkLocalIpv6FromEui48Mac().getAddress(), - NetworkInterface.getByName(nnri.interfaceName)); - } else { - byte[] addr = new byte[16]; - - addr[0] = (byte) 0xfe; - addr[1] = (byte) 0x80; - addr[8] = nnri.peerIpv6Override[0]; - addr[9] = nnri.peerIpv6Override[1]; - addr[10] = nnri.peerIpv6Override[2]; - addr[11] = nnri.peerIpv6Override[3]; - addr[12] = nnri.peerIpv6Override[4]; - addr[13] = nnri.peerIpv6Override[5]; - addr[14] = nnri.peerIpv6Override[6]; - addr[15] = nnri.peerIpv6Override[7]; - - nnri.peerIpv6 = Inet6Address.getByAddress(null, addr, - NetworkInterface.getByName(nnri.interfaceName)); - } - } catch (SocketException | UnknownHostException e) { - Log.e(TAG, "onDataPathConfirm: error obtaining scoped IPv6 address -- " + e); - nnri.peerIpv6 = null; - } - - if (nnri.peerIpv6 != null) { - final WifiAwareNetworkInfo ni = new WifiAwareNetworkInfo( - nnri.peerIpv6, nnri.peerPort, nnri.peerTransportProtocol); - ncBuilder.setTransportInfo(ni); - if (VDBG) { - Log.v(TAG, "onDataPathConfirm: AwareNetworkInfo=" + ni); - } - } - - if (!mNiWrapper.configureAgentProperties(nnri, nnri.equivalentRequests, ndpId, - ncBuilder, linkProperties)) { - declareUnfullfillableAndEndDp(nnri, ndpId); - return networkSpecifier; - } - - final NetworkAgentConfig naConfig = new NetworkAgentConfig.Builder() - .setLegacyType(ConnectivityManager.TYPE_NONE) - .setLegacyTypeName(NETWORK_TAG) - .build(); - - nnri.networkAgent = new WifiAwareNetworkAgent(mLooper, mContext, - AGENT_TAG_PREFIX + nnri.ndpId, ncBuilder.build(), - linkProperties, NETWORK_FACTORY_SCORE_AVAIL, - naConfig, mNetworkFactory.getProvider(), nnri); nnri.startValidationTimestamp = mClock.getElapsedSinceBootMillis(); - handleAddressValidation(nnri, linkProperties, ndpId, networkSpecifier.isOutOfBand()); + handleAddressValidation(nnri, ndpId, networkSpecifier.isOutOfBand(), mac); } else { if (VDBG) { Log.v(TAG, "onDataPathConfirm: data-path for networkSpecifier=" + networkSpecifier @@ -676,29 +620,81 @@ public class WifiAwareDataPathStateManager { return networkSpecifier; } - private void handleAddressValidation(AwareNetworkRequestInformation nnri, - LinkProperties linkProperties, int ndpId, boolean isOutOfBand) { - if (mNiWrapper.isAddressUsable(linkProperties)) { - mNiWrapper.setConnected(nnri.networkAgent); - - mAwareMetrics.recordNdpStatus(NanStatusType.SUCCESS, isOutOfBand, nnri.startTimestamp); - nnri.startTimestamp = mClock.getElapsedSinceBootMillis(); // update time-stamp - mAwareMetrics.recordNdpCreation(nnri.uid, nnri.packageName, mNetworkRequestsCache); - } else { - if (mClock.getElapsedSinceBootMillis() - nnri.startValidationTimestamp - > ADDRESS_VALIDATION_TIMEOUT_MS) { - Log.e(TAG, "Timed-out while waiting for IPv6 address to be usable"); + private void getInet6Address(AwareNetworkRequestInformation nnri, byte[] mac) { + try { + byte[] addr; + if (nnri.peerIpv6Override == null) { + addr = MacAddress.fromBytes(mac).getLinkLocalIpv6FromEui48Mac().getAddress(); + } else { + addr = new byte[16]; + addr[0] = (byte) 0xfe; + addr[1] = (byte) 0x80; + addr[8] = nnri.peerIpv6Override[0]; + addr[9] = nnri.peerIpv6Override[1]; + addr[10] = nnri.peerIpv6Override[2]; + addr[11] = nnri.peerIpv6Override[3]; + addr[12] = nnri.peerIpv6Override[4]; + addr[13] = nnri.peerIpv6Override[5]; + addr[14] = nnri.peerIpv6Override[6]; + addr[15] = nnri.peerIpv6Override[7]; + } + nnri.peerIpv6 = Inet6Address.getByAddress(null, addr, + NetworkInterface.getByName(nnri.interfaceName)); + } catch (SocketException | UnknownHostException e) { + if (mDbg) { + Log.d(TAG, "onDataPathConfirm: error obtaining scoped IPv6 address -- " + e); + } + nnri.peerIpv6 = null; + } + } - declareUnfullfillableAndEndDp(nnri, ndpId); - return; + private void handleAddressValidation(AwareNetworkRequestInformation nnri, int ndpId, + boolean isOutOfBand, byte[] mac) { + final NetworkCapabilities.Builder ncBuilder = new NetworkCapabilities.Builder( + sNetworkCapabilitiesFilter); + LinkProperties linkProperties = new LinkProperties(); + getInet6Address(nnri, mac); + if (nnri.peerIpv6 != null) { + final WifiAwareNetworkInfo ni = new WifiAwareNetworkInfo( + nnri.peerIpv6, nnri.peerPort, nnri.peerTransportProtocol); + ncBuilder.setTransportInfo(ni); + if (VDBG) { + Log.v(TAG, "onDataPathConfirm: AwareNetworkInfo=" + ni); } + } + if (!(mNiWrapper.configureAgentProperties(nnri, nnri.equivalentRequests, ndpId, + ncBuilder, linkProperties) && mNiWrapper.isAddressUsable(linkProperties))) { if (VDBG) { Log.d(TAG, "Failed address validation"); } - mHandler.postDelayed(() -> { - handleAddressValidation(nnri, linkProperties, ndpId, isOutOfBand); - }, ADDRESS_VALIDATION_RETRY_INTERVAL_MS); + if (!isAddressValidationExpired(nnri, ndpId)) { + mHandler.postDelayed(() -> { + handleAddressValidation(nnri, ndpId, isOutOfBand, mac); + }, ADDRESS_VALIDATION_RETRY_INTERVAL_MS); + } + return; + } + final NetworkAgentConfig naConfig = new NetworkAgentConfig.Builder() + .setLegacyType(ConnectivityManager.TYPE_NONE) + .setLegacyTypeName(NETWORK_TAG) + .build(); + nnri.networkAgent = new WifiAwareNetworkAgent(mLooper, mContext, + AGENT_TAG_PREFIX + nnri.ndpId, ncBuilder.build(), linkProperties, + NETWORK_FACTORY_SCORE_AVAIL, naConfig, mNetworkFactory.getProvider(), nnri); + mNiWrapper.setConnected(nnri.networkAgent); + mAwareMetrics.recordNdpStatus(NanStatusType.SUCCESS, isOutOfBand, nnri.startTimestamp); + nnri.startTimestamp = mClock.getElapsedSinceBootMillis(); // update time-stamp + mAwareMetrics.recordNdpCreation(nnri.uid, nnri.packageName, mNetworkRequestsCache); + } + + private boolean isAddressValidationExpired(AwareNetworkRequestInformation nnri, int ndpId) { + if (mClock.getElapsedSinceBootMillis() - nnri.startValidationTimestamp + > ADDRESS_VALIDATION_TIMEOUT_MS) { + Log.e(TAG, "Timed-out while waiting for IPv6 address to be usable"); + declareUnfullfillableAndEndDp(nnri, ndpId); + return true; } + return false; } private void declareUnfullfillableAndEndDp(AwareNetworkRequestInformation nnri, int ndpId) { diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java index df7417338..f496b1c95 100644 --- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java @@ -1394,9 +1394,15 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { mMockLooper.dispatchAll(); // (2) get confirmation OR timeout + boolean timeout = false; if (getConfirmation) { + int numConfigureAgentPropertiesFail = 0; if (numAddrValidationRetries > 0) { when(mMockNetworkInterface.isAddressUsable(any())).thenReturn(false); + when(mMockNetworkInterface.configureAgentProperties(any(), any(), anyInt(), + any(), any())).thenReturn(false); + // First retry will be ConfigureAgentProperties failure. + numConfigureAgentPropertiesFail = 1; } when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); @@ -1406,35 +1412,41 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { inOrder.verify(mMockNetdWrapper).enableIpv6(anyString()); inOrder.verify(mMockNetworkInterface).configureAgentProperties(any(), any(), anyInt(), any(), any()); - inOrder.verify(mMockCm).registerNetworkAgent(messengerCaptor.capture(), any(), any(), - netCapCaptor.capture(), anyInt(), any(), anyInt()); - - inOrder.verify(mMockNetworkInterface).isAddressUsable(any()); - boolean timedout = false; + if (numAddrValidationRetries <= 0) { + inOrder.verify(mMockNetworkInterface).isAddressUsable(any()); + } for (int i = 0; i < numAddrValidationRetries; ++i) { + if (i == numConfigureAgentPropertiesFail) { + when(mMockNetworkInterface.configureAgentProperties(any(), any(), anyInt(), + any(), any())).thenReturn(true); + } if (i == numAddrValidationRetries - 1) { when(mMockNetworkInterface.isAddressUsable(any())).thenReturn(true); } - long currentTime = (i + 1L) * WifiAwareDataPathStateManager.ADDRESS_VALIDATION_RETRY_INTERVAL_MS; when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTime); mMockLooper.moveTimeForward( WifiAwareDataPathStateManager.ADDRESS_VALIDATION_RETRY_INTERVAL_MS + 1); mMockLooper.dispatchAll(); + inOrder.verify(mMockNetworkInterface).configureAgentProperties(any(), any(), + anyInt(), any(), any()); + if (i < numConfigureAgentPropertiesFail) { + continue; + } inOrder.verify(mMockNetworkInterface).isAddressUsable(any()); - if (currentTime > WifiAwareDataPathStateManager.ADDRESS_VALIDATION_TIMEOUT_MS) { - timedout = true; + timeout = true; break; } } - - if (timedout) { + if (timeout) { verifyRequestDeclaredUnfullfillable(nr); inOrder.verify(mMockNative).endDataPath(transactionId.capture(), eq(ndpId)); mDut.onEndDataPathResponse(transactionId.getValue(), true, 0); } else { + inOrder.verify(mMockCm).registerNetworkAgent(messengerCaptor.capture(), any(), + any(), netCapCaptor.capture(), anyInt(), any(), anyInt()); inOrder.verify(mMockNetworkInterface).setConnected(any()); inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusType.SUCCESS), eq(useDirect), anyLong()); @@ -1458,7 +1470,7 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { } // (3) end data-path (unless didn't get confirmation) - if (getConfirmation) { + if (getConfirmation && !timeout) { Message endNetworkReqMsg = Message.obtain(); endNetworkReqMsg.what = NetworkFactory.CMD_CANCEL_REQUEST; endNetworkReqMsg.obj = nr; -- cgit v1.2.3