Merge "Add unit test on getting initial BSSID in IpClientTest." am: 01db53a532 am: 3d8131515b

Original change: https://android-review.googlesource.com/c/platform/packages/modules/NetworkStack/+/1711434

Change-Id: I8c258a6915d4ad2f63365338d6f1252b8681658c
diff --git a/src/android/net/apf/ApfFilter.java b/src/android/net/apf/ApfFilter.java
index 34469b8..7a13392 100644
--- a/src/android/net/apf/ApfFilter.java
+++ b/src/android/net/apf/ApfFilter.java
@@ -1411,7 +1411,7 @@
         //     pass
         // if it's ICMPv6 RS to any:
         //   drop
-        // if it's ICMPv6 NA to ff02::1 or ff02::2:
+        // if it's ICMPv6 NA to anything in ff02::/120
         //   drop
         // if keepalive ack
         //   drop
@@ -1495,7 +1495,7 @@
      * <li>Drop all broadcast non-IP non-ARP packets.
      * <li>Pass all non-ICMPv6 IPv6 packets,
      * <li>Pass all non-IPv4 and non-IPv6 packets,
-     * <li>Drop IPv6 ICMPv6 NAs to ff02::1 or ff02::2.
+     * <li>Drop IPv6 ICMPv6 NAs to anything in ff02::/120.
      * <li>Drop IPv6 ICMPv6 RSs.
      * <li>Filter IPv4 packets (see generateIPv4FilterLocked())
      * <li>Filter IPv6 packets (see generateIPv6FilterLocked())
diff --git a/src/android/net/ip/IpClient.java b/src/android/net/ip/IpClient.java
index a57e99d..445f915 100644
--- a/src/android/net/ip/IpClient.java
+++ b/src/android/net/ip/IpClient.java
@@ -61,6 +61,7 @@
 import android.net.metrics.IpManagerEvent;
 import android.net.networkstack.aidl.dhcp.DhcpOption;
 import android.net.shared.InitialConfiguration;
+import android.net.shared.Layer2Information;
 import android.net.shared.ProvisioningConfiguration;
 import android.net.shared.ProvisioningConfiguration.ScanResultInfo;
 import android.net.shared.ProvisioningConfiguration.ScanResultInfo.InformationElement;
@@ -147,6 +148,7 @@
  * @hide
  */
 public class IpClient extends StateMachine {
+    private static final String TAG = IpClient.class.getSimpleName();
     private static final boolean DBG = false;
 
     // For message logging.
@@ -872,26 +874,28 @@
                 false /* defaultEnabled */);
     }
 
-    private void setInitialBssid(final ProvisioningConfiguration req) {
-        final ScanResultInfo scanResultInfo = req.mScanResultInfo;
-        mCurrentBssid = null;
+    @VisibleForTesting
+    static MacAddress getInitialBssid(final Layer2Information layer2Info,
+            final ScanResultInfo scanResultInfo, boolean isAtLeastS) {
+        MacAddress bssid = null;
         // http://b/185202634
         // ScanResultInfo is not populated in some situations.
         // On S and above, prefer getting the BSSID from the Layer2Info.
         // On R and below, get the BSSID from the ScanResultInfo and fall back to
         // getting it from the Layer2Info. This ensures no regressions if any R
         // devices pass in a null or meaningless BSSID in the Layer2Info.
-        if (!ShimUtils.isAtLeastS() && scanResultInfo != null) {
+        if (!isAtLeastS && scanResultInfo != null) {
             try {
-                mCurrentBssid = MacAddress.fromString(scanResultInfo.getBssid());
+                bssid = MacAddress.fromString(scanResultInfo.getBssid());
             } catch (IllegalArgumentException e) {
-                Log.wtf(mTag, "Invalid BSSID: " + scanResultInfo.getBssid()
+                Log.wtf(TAG, "Invalid BSSID: " + scanResultInfo.getBssid()
                         + " in provisioning configuration", e);
             }
         }
-        if (mCurrentBssid == null && req.mLayer2Info != null) {
-            mCurrentBssid = req.mLayer2Info.mBssid;
+        if (bssid == null && layer2Info != null) {
+            bssid = layer2Info.mBssid;
         }
+        return bssid;
     }
 
     private boolean shouldDisableAcceptRaOnProvisioningLoss() {
@@ -922,7 +926,8 @@
             return;
         }
 
-        setInitialBssid(req);
+        mCurrentBssid = getInitialBssid(req.mLayer2Info, req.mScanResultInfo,
+                ShimUtils.isAtLeastS());
         if (req.mLayer2Info != null) {
             mL2Key = req.mLayer2Info.mL2Key;
             mCluster = req.mLayer2Info.mCluster;
diff --git a/tests/integration/src/android/net/ip/IpClientIntegrationTestCommon.java b/tests/integration/src/android/net/ip/IpClientIntegrationTestCommon.java
index c121b3d..e40db77 100644
--- a/tests/integration/src/android/net/ip/IpClientIntegrationTestCommon.java
+++ b/tests/integration/src/android/net/ip/IpClientIntegrationTestCommon.java
@@ -3007,119 +3007,4 @@
         assertEquals(0, naList.size());
         assertEquals(1, arpList.size());
     }
-
-    private void doInitialBssidSetupTest(final Layer2Information layer2Info,
-            final ScanResultInfo scanResultInfo) throws Exception {
-        ProvisioningConfiguration.Builder prov = new ProvisioningConfiguration.Builder()
-                .withoutIpReachabilityMonitor()
-                .withLayer2Information(layer2Info)
-                .withScanResultInfo(scanResultInfo)
-                .withDisplayName("\"0001docomo\"")
-                .withoutIPv6();
-
-        setDhcpFeatures(false /* isDhcpLeaseCacheEnabled */, true /* shouldReplyRapidCommitAck */,
-                false /* isDhcpIpConflictDetectEnabled */, false /* isIPv6OnlyPreferredEnabled */);
-        startIpClientProvisioning(prov.build());
-
-        handleDhcpPackets(true /* isSuccessLease */, TEST_LEASE_DURATION_S,
-                true /* shouldReplyRapidCommitAck */, TEST_DEFAULT_MTU, null /* serverSentUrl */);
-        verifyIPv4OnlyProvisioningSuccess(Collections.singletonList(CLIENT_ADDR));
-        forceLayer2Roaming();
-    }
-
-    @Test @IgnoreUpTo(Build.VERSION_CODES.R)
-    public void testSetInitialBssidFromLayer2Info() throws Exception {
-        final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
-                MacAddress.fromString(TEST_DEFAULT_BSSID));
-
-        doInitialBssidSetupTest(layer2Info, null /* scanResultInfo */);
-
-        // Initial BSSID comes from layer2Info, it's different with target roaming bssid,
-        // then verify that DHCPREQUEST packet is sent after roaming.
-        final DhcpPacket packet = getNextDhcpPacket();
-        assertTrue(packet instanceof DhcpRequestPacket);
-    }
-
-    @Test @IgnoreUpTo(Build.VERSION_CODES.R)
-    public void testSetInitialBssidFromLayer2Info_NullBssid() throws Exception {
-        final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
-                null /* bssid */);
-        final ScanResultInfo scanResultInfo =
-                makeScanResultInfo(TEST_DEFAULT_SSID, TEST_DHCP_ROAM_BSSID);
-
-        doInitialBssidSetupTest(layer2Info, scanResultInfo);
-
-        // Initial BSSID comes from layer2Info, it's null, no DHCPREQUEST packet
-        // will be sent after roaming.
-        final DhcpPacket packet = getNextDhcpPacket(TEST_TIMEOUT_MS);
-        assertNull(packet);
-    }
-
-    @Test @IgnoreUpTo(Build.VERSION_CODES.R)
-    public void testSetInitialBssidFromLayer2Info_SameRoamingBssid() throws Exception {
-        final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
-                MacAddress.fromString(TEST_DHCP_ROAM_BSSID));
-
-        doInitialBssidSetupTest(layer2Info, null /* scanResultInfo */);
-
-        // Initial BSSID comes from layer2Info, it's same with target roaming bssid,
-        // no DHCPREQUEST packet will be sent after roaming.
-        final DhcpPacket packet = getNextDhcpPacket(TEST_TIMEOUT_MS);
-        assertNull(packet);
-    }
-
-    @Test @IgnoreAfter(Build.VERSION_CODES.R)
-    public void testSetInitialBssidFromScanResultInfo() throws Exception {
-        final ScanResultInfo scanResultInfo =
-                makeScanResultInfo(TEST_DEFAULT_SSID, TEST_DEFAULT_BSSID);
-
-        doInitialBssidSetupTest(null /* layer2Info */, scanResultInfo);
-
-        // Initial BSSID comes from ScanResultInfo, it's different with target roaming bssid,
-        // then verify that DHCPREQUEST packet is sent after roaming.
-        final DhcpPacket packet = getNextDhcpPacket();
-        assertTrue(packet instanceof DhcpRequestPacket);
-    }
-
-    @Test @IgnoreAfter(Build.VERSION_CODES.R)
-    public void testSetInitialBssidFromScanResultInfo_SameRoamingBssid() throws Exception {
-        final ScanResultInfo scanResultInfo =
-                makeScanResultInfo(TEST_DEFAULT_SSID, TEST_DHCP_ROAM_BSSID);
-
-        doInitialBssidSetupTest(null /* layer2Info */, scanResultInfo);
-
-        // Initial BSSID comes from ScanResultInfo, it's same with target roaming bssid,
-        // no DHCPREQUEST packet will be sent after roaming.
-        final DhcpPacket packet = getNextDhcpPacket(TEST_TIMEOUT_MS);
-        assertNull(packet);
-    }
-
-    @Test @IgnoreAfter(Build.VERSION_CODES.R)
-    public void testSetInitialBssidFromScanResultInfo_BrokenInitialBssid() throws Exception {
-        final ScanResultInfo scanResultInfo =
-                makeScanResultInfo(TEST_DEFAULT_SSID, "00:11:22:33:44:");
-
-        doInitialBssidSetupTest(null /* layer2Info */, scanResultInfo);
-
-        // Initial BSSID comes from ScanResultInfo, it's broken MAC address format and fallback
-        // to null layer2Info, no DHCPREQUEST packet will be sent after roaming.
-        final DhcpPacket packet = getNextDhcpPacket(TEST_TIMEOUT_MS);
-        assertNull(packet);
-    }
-
-    @Test @IgnoreAfter(Build.VERSION_CODES.R)
-    public void testSetInitialBssidFromScanResultInfo_BrokenInitialBssidFallback()
-            throws Exception {
-        final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
-                MacAddress.fromString(TEST_DEFAULT_BSSID));
-        final ScanResultInfo scanResultInfo =
-                makeScanResultInfo(TEST_DEFAULT_SSID, "00:11:22:33:44:");
-
-        doInitialBssidSetupTest(layer2Info, scanResultInfo);
-
-        // Initial BSSID comes from ScanResultInfo, it's broken MAC address format and fallback
-        // to check layer2Info, then verify DHCPREQUEST packet will be sent after roaming.
-        final DhcpPacket packet = getNextDhcpPacket();
-        assertTrue(packet instanceof DhcpRequestPacket);
-    }
 }
diff --git a/tests/unit/src/android/net/ip/IpClientTest.java b/tests/unit/src/android/net/ip/IpClientTest.java
index 7260332..c9e486b 100644
--- a/tests/unit/src/android/net/ip/IpClientTest.java
+++ b/tests/unit/src/android/net/ip/IpClientTest.java
@@ -21,6 +21,7 @@
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.Mockito.any;
@@ -55,7 +56,9 @@
 import android.net.ipmemorystore.NetworkAttributes;
 import android.net.metrics.IpConnectivityLog;
 import android.net.shared.InitialConfiguration;
+import android.net.shared.Layer2Information;
 import android.net.shared.ProvisioningConfiguration;
+import android.net.shared.ProvisioningConfiguration.ScanResultInfo;
 import android.net.util.InterfaceParams;
 import android.os.Build;
 
@@ -83,9 +86,12 @@
 import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.InetAddress;
+import java.nio.ByteBuffer;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Random;
 import java.util.Set;
 
 
@@ -107,6 +113,8 @@
     private static final int TEST_TIMEOUT_MS = 400;
     private static final String TEST_L2KEY = "some l2key";
     private static final String TEST_CLUSTER = "some cluster";
+    private static final String TEST_SSID = "test_ssid";
+    private static final String TEST_BSSID = "00:11:22:33:44:55";
 
     private static final String TEST_GLOBAL_ADDRESS = "1234:4321::548d:2db2:4fcf:ef75/64";
     private static final String[] TEST_LOCAL_ADDRESSES = {
@@ -709,6 +717,107 @@
         verifyShutdown(ipc);
     }
 
+    private ScanResultInfo makeScanResultInfo(final String ssid, final String bssid) {
+        final ByteBuffer payload = ByteBuffer.allocate(14 /* oui + type + data */);
+        final byte[] data = new byte[10];
+        new Random().nextBytes(data);
+        payload.put(new byte[] { 0x00, 0x1A, 0x11 });
+        payload.put((byte) 0x06);
+        payload.put(data);
+
+        final ScanResultInfo.InformationElement ie =
+                new ScanResultInfo.InformationElement(0xdd /* IE id */, payload);
+        return new ScanResultInfo(ssid, bssid, Collections.singletonList(ie));
+    }
+
+    @Test
+    public void testGetInitialBssidOnSOrAbove() throws Exception {
+        final IpClient ipc = makeIpClient(TEST_IFNAME);
+        final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
+                MacAddress.fromString(TEST_BSSID));
+        final MacAddress bssid = ipc.getInitialBssid(layer2Info, null /* ScanReqsultInfo */,
+                true /* isAtLeastS */);
+        assertEquals(bssid, MacAddress.fromString(TEST_BSSID));
+    }
+
+    @Test
+    public void testGetInitialBssidOnSOrAbove_NullBssid() throws Exception {
+        final IpClient ipc = makeIpClient(TEST_IFNAME);
+        final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
+                null /* bssid */);
+        final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, TEST_BSSID);
+        final MacAddress bssid = ipc.getInitialBssid(layer2Info, scanResultInfo,
+                true /* isAtLeastS */);
+        assertNull(bssid);
+    }
+
+    @Test
+    public void testGetInitialBssidOnSOrAbove_NullLayer2Info() throws Exception {
+        final IpClient ipc = makeIpClient(TEST_IFNAME);
+        final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, TEST_BSSID);
+        final MacAddress bssid = ipc.getInitialBssid(null /* layer2Info */, scanResultInfo,
+                true /* isAtLeastS */);
+        assertNull(bssid);
+    }
+
+    @Test
+    public void testGetInitialBssidBeforeS() throws Exception {
+        final IpClient ipc = makeIpClient(TEST_IFNAME);
+        final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
+                MacAddress.fromString(TEST_BSSID));
+        final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, TEST_BSSID);
+        final MacAddress bssid = ipc.getInitialBssid(layer2Info, scanResultInfo,
+                false /* isAtLeastS */);
+        assertEquals(bssid, MacAddress.fromString(TEST_BSSID));
+    }
+
+    @Test
+    public void testGetInitialBssidBeforeS_NullLayer2Info() throws Exception {
+        final IpClient ipc = makeIpClient(TEST_IFNAME);
+        final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, TEST_BSSID);
+        final MacAddress bssid = ipc.getInitialBssid(null /* layer2Info */, scanResultInfo,
+                false /* isAtLeastS */);
+        assertEquals(bssid, MacAddress.fromString(TEST_BSSID));
+    }
+
+    @Test
+    public void testGetInitialBssidBeforeS_BrokenInitialBssid() throws Exception {
+        final IpClient ipc = makeIpClient(TEST_IFNAME);
+        final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, "00:11:22:33:44:");
+        final MacAddress bssid = ipc.getInitialBssid(null /* layer2Info */, scanResultInfo,
+                false /* isAtLeastS */);
+        assertNull(bssid);
+    }
+
+    @Test
+    public void testGetInitialBssidBeforeS_BrokenInitialBssidFallback() throws Exception {
+        final IpClient ipc = makeIpClient(TEST_IFNAME);
+        final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
+                MacAddress.fromString(TEST_BSSID));
+        final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, "00:11:22:33:44:");
+        final MacAddress bssid = ipc.getInitialBssid(layer2Info, scanResultInfo,
+                false /* isAtLeastS */);
+        assertEquals(bssid, MacAddress.fromString(TEST_BSSID));
+    }
+
+    @Test
+    public void testGetInitialBssidBeforeS_NullScanResultInfoFallback() throws Exception {
+        final IpClient ipc = makeIpClient(TEST_IFNAME);
+        final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
+                MacAddress.fromString(TEST_BSSID));
+        final MacAddress bssid = ipc.getInitialBssid(layer2Info, null /* scanResultInfo */,
+                false /* isAtLeastS */);
+        assertEquals(bssid, MacAddress.fromString(TEST_BSSID));
+    }
+
+    @Test
+    public void testGetInitialBssidBeforeS_NullScanResultInfoAndLayer2Info() throws Exception {
+        final IpClient ipc = makeIpClient(TEST_IFNAME);
+        final MacAddress bssid = ipc.getInitialBssid(null /* layer2Info */,
+                null /* scanResultInfo */, false /* isAtLeastS */);
+        assertNull(bssid);
+    }
+
     interface Fn<A,B> {
         B call(A a) throws Exception;
     }