Merge "BpfMap: simplify .init() mMapFd assignment"
diff --git a/staticlibs/device/com/android/net/module/util/FdEventsReader.java b/staticlibs/device/com/android/net/module/util/FdEventsReader.java
index 71ae13d..ecf8e77 100644
--- a/staticlibs/device/com/android/net/module/util/FdEventsReader.java
+++ b/staticlibs/device/com/android/net/module/util/FdEventsReader.java
@@ -211,7 +211,7 @@
         return true;
     }
 
-    private boolean isRunning() {
+    protected boolean isRunning() {
         return (mFd != null) && mFd.valid();
     }
 
diff --git a/staticlibs/device/com/android/net/module/util/Ipv6Utils.java b/staticlibs/device/com/android/net/module/util/Ipv6Utils.java
index fe7c89b..d538221 100644
--- a/staticlibs/device/com/android/net/module/util/Ipv6Utils.java
+++ b/staticlibs/device/com/android/net/module/util/Ipv6Utils.java
@@ -20,6 +20,7 @@
 
 import static com.android.net.module.util.IpUtils.icmpv6Checksum;
 import static com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV6;
+import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ECHO_REPLY_TYPE;
 import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ECHO_REQUEST_TYPE;
 import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NEIGHBOR_ADVERTISEMENT;
 import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NEIGHBOR_SOLICITATION;
@@ -45,29 +46,23 @@
  */
 public class Ipv6Utils {
     /**
-     * Build a generic ICMPv6 packet(e.g., packet used in the neighbor discovery protocol).
+     * Build a generic ICMPv6 packet without Ethernet header.
      */
-    public static ByteBuffer buildIcmpv6Packet(final MacAddress srcMac, final MacAddress dstMac,
-            final Inet6Address srcIp, final Inet6Address dstIp, short type, short code,
-            final ByteBuffer... options) {
-        final int etherHeaderLen = Struct.getSize(EthernetHeader.class);
+    public static ByteBuffer buildIcmpv6Packet(final Inet6Address srcIp, final Inet6Address dstIp,
+            short type, short code, final ByteBuffer... options) {
         final int ipv6HeaderLen = Struct.getSize(Ipv6Header.class);
         final int icmpv6HeaderLen = Struct.getSize(Icmpv6Header.class);
         int payloadLen = 0;
         for (ByteBuffer option: options) {
             payloadLen += option.limit();
         }
-        final ByteBuffer packet = ByteBuffer.allocate(etherHeaderLen + ipv6HeaderLen
-                + icmpv6HeaderLen + payloadLen);
-        final EthernetHeader ethHeader =
-                new EthernetHeader(dstMac, srcMac, (short) ETHER_TYPE_IPV6);
+        final ByteBuffer packet = ByteBuffer.allocate(ipv6HeaderLen + icmpv6HeaderLen + payloadLen);
         final Ipv6Header ipv6Header =
                 new Ipv6Header((int) 0x60000000 /* version, traffic class, flowlabel */,
                 icmpv6HeaderLen + payloadLen /* payload length */,
                 (byte) IPPROTO_ICMPV6 /* next header */, (byte) 0xff /* hop limit */, srcIp, dstIp);
         final Icmpv6Header icmpv6Header = new Icmpv6Header(type, code, (short) 0 /* checksum */);
 
-        ethHeader.writeToByteBuffer(packet);
         ipv6Header.writeToByteBuffer(packet);
         icmpv6Header.writeToByteBuffer(packet);
         for (ByteBuffer option : options) {
@@ -79,11 +74,31 @@
         packet.flip();
 
         // Populate the ICMPv6 checksum field.
-        packet.putShort(etherHeaderLen + ipv6HeaderLen + 2, icmpv6Checksum(packet,
-                etherHeaderLen /* ipOffset */,
-                (int) (etherHeaderLen + ipv6HeaderLen) /* transportOffset */,
+        packet.putShort(ipv6HeaderLen + 2, icmpv6Checksum(packet, 0 /* ipOffset */,
+                ipv6HeaderLen /* transportOffset */,
                 (short) (icmpv6HeaderLen + payloadLen) /* transportLen */));
         return packet;
+
+    }
+
+    /**
+     * Build a generic ICMPv6 packet(e.g., packet used in the neighbor discovery protocol).
+     */
+    public static ByteBuffer buildIcmpv6Packet(final MacAddress srcMac, final MacAddress dstMac,
+            final Inet6Address srcIp, final Inet6Address dstIp, short type, short code,
+            final ByteBuffer... options) {
+        final ByteBuffer payload = buildIcmpv6Packet(srcIp, dstIp, type, code, options);
+
+        final int etherHeaderLen = Struct.getSize(EthernetHeader.class);
+        final ByteBuffer packet = ByteBuffer.allocate(etherHeaderLen + payload.limit());
+        final EthernetHeader ethHeader =
+                new EthernetHeader(dstMac, srcMac, (short) ETHER_TYPE_IPV6);
+
+        ethHeader.writeToByteBuffer(packet);
+        packet.put(payload);
+        packet.flip();
+
+        return packet;
     }
 
     /**
@@ -159,4 +174,14 @@
         return buildIcmpv6Packet(srcMac, dstMac, srcIp, dstIp,
                 (byte) ICMPV6_ECHO_REQUEST_TYPE /* type */, (byte) 0 /* code */, payload);
     }
+
+    /**
+     * Build an ICMPv6 Echo Reply packet without ethernet header.
+     */
+    public static ByteBuffer buildEchoReplyPacket(final Inet6Address srcIp,
+            final Inet6Address dstIp) {
+        final ByteBuffer payload = ByteBuffer.allocate(4); // ID and Sequence number may be zero.
+        return buildIcmpv6Packet(srcIp, dstIp, (byte) ICMPV6_ECHO_REPLY_TYPE /* type */,
+                (byte) 0 /* code */, payload);
+    }
 }
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/TestNetworkTracker.kt b/staticlibs/testutils/devicetests/com/android/testutils/TestNetworkTracker.kt
index 40731ea..bdea6c7 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/TestNetworkTracker.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/TestNetworkTracker.kt
@@ -23,6 +23,7 @@
 import android.net.Network
 import android.net.NetworkCapabilities
 import android.net.NetworkRequest
+import android.net.LinkProperties
 import android.net.TestNetworkInterface
 import android.net.TestNetworkManager
 import android.os.Binder
@@ -32,6 +33,7 @@
 
 /**
  * Create a test network based on a TUN interface with a LinkAddress.
+ * TODO: remove this function after fixing all the callers.
  *
  * This method will block until the test network is available. Requires
  * [android.Manifest.permission.CHANGE_NETWORK_STATE] and
@@ -42,11 +44,13 @@
     interfaceAddr: LinkAddress,
     setupTimeoutMs: Long = 10_000L
 ): TestNetworkTracker {
-    return initTestNetwork(context, listOf(interfaceAddr), setupTimeoutMs)
+    val lp = LinkProperties()
+    lp.addLinkAddress(interfaceAddr)
+    return initTestNetwork(context, lp, setupTimeoutMs)
 }
 
 /**
- * Create a test network based on a TUN interface with giving LinkAddress list.
+ * Create a test network based on a TUN interface
  *
  * This method will block until the test network is available. Requires
  * [android.Manifest.permission.CHANGE_NETWORK_STATE] and
@@ -54,13 +58,14 @@
  */
 fun initTestNetwork(
     context: Context,
-    linkAddrs: List<LinkAddress>,
+    lp: LinkProperties,
     setupTimeoutMs: Long = 10_000L
 ): TestNetworkTracker {
     val tnm = context.getSystemService(TestNetworkManager::class.java)
-    val iface = if (isAtLeastS()) tnm.createTunInterface(linkAddrs)
-            else tnm.createTunInterface(linkAddrs.toTypedArray())
-    return TestNetworkTracker(context, iface, tnm, setupTimeoutMs)
+    val iface = if (isAtLeastS()) tnm.createTunInterface(lp.getLinkAddresses())
+            else tnm.createTunInterface(lp.getLinkAddresses().toTypedArray())
+    lp.setInterfaceName(iface.interfaceName)
+    return TestNetworkTracker(context, iface, tnm, lp, setupTimeoutMs)
 }
 
 /**
@@ -72,6 +77,7 @@
     val context: Context,
     val iface: TestNetworkInterface,
     val tnm: TestNetworkManager,
+    val lp: LinkProperties,
     setupTimeoutMs: Long
 ) {
     private val cm = context.getSystemService(ConnectivityManager::class.java)
@@ -98,7 +104,7 @@
         cm.requestNetwork(networkRequest, networkCallback)
 
         try {
-            tnm.setupTestNetwork(iface.interfaceName, binder)
+            tnm.setupTestNetwork(lp, true /* isMetered */, binder)
             network = networkFuture.get(setupTimeoutMs, TimeUnit.MILLISECONDS)
         } catch (e: Throwable) {
             teardown()
@@ -112,4 +118,4 @@
         cm.unregisterNetworkCallback(networkCallback)
         tnm.teardownTestNetwork(network)
     }
-}
\ No newline at end of file
+}