Merge "Add a physical local native network type."
diff --git a/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkAddressMessage.java b/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkAddressMessage.java
index 3748e46..c07cec0 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkAddressMessage.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkAddressMessage.java
@@ -17,7 +17,6 @@
 package com.android.net.module.util.netlink;
 
 import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_ACK;
-import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REPLACE;
 import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REQUEST;
 
 import android.system.OsConstants;
@@ -32,6 +31,7 @@
 import java.net.InetAddress;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
+import java.util.Objects;
 
 /**
  * A NetlinkMessage subclass for rtnetlink address messages.
@@ -154,21 +154,26 @@
     /**
      * A convenience method to create an RTM_NEWADDR message.
      */
-    public static byte[] newRtmNewAddressMessage(int seqNo, final InetAddress ip, short prefixlen,
-            byte flags, byte scope, int ifIndex, long preferred, long valid) {
+    public static byte[] newRtmNewAddressMessage(int seqNo, @NonNull final InetAddress ip,
+            short prefixlen, int flags, byte scope, int ifIndex, long preferred, long valid) {
+        Objects.requireNonNull(ip, "IP address to be set via netlink message cannot be null");
+
         final StructNlMsgHdr nlmsghdr = new StructNlMsgHdr();
         nlmsghdr.nlmsg_type = NetlinkConstants.RTM_NEWADDR;
-        nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE;
+        nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
         nlmsghdr.nlmsg_seq = seqNo;
 
         final RtNetlinkAddressMessage msg = new RtNetlinkAddressMessage(nlmsghdr);
         final byte family =
                 (byte) ((ip instanceof Inet6Address) ? OsConstants.AF_INET6 : OsConstants.AF_INET);
-        msg.mIfaddrmsg = new StructIfaddrMsg(family, prefixlen, flags, scope, ifIndex);
+        // IFA_FLAGS attribute is always present within this method, just set flags from
+        // ifaddrmsg to 0. kernel will prefer the flags from IFA_FLAGS attribute.
+        msg.mIfaddrmsg =
+                new StructIfaddrMsg(family, prefixlen, (short) 0 /* flags */, scope, ifIndex);
         msg.mIpAddress = ip;
         msg.mIfacacheInfo = new StructIfacacheInfo(preferred, valid, 0 /* cstamp */,
                 0 /* tstamp */);
-        msg.mFlags = (int) (flags & 0xFF);
+        msg.mFlags = flags;
 
         final byte[] bytes = new byte[msg.getRequiredSpace()];
         nlmsghdr.nlmsg_len = bytes.length;
@@ -180,15 +185,14 @@
 
     private int getRequiredSpace() {
         int spaceRequired = StructNlMsgHdr.STRUCT_SIZE + StructIfaddrMsg.STRUCT_SIZE;
-        if (mIpAddress != null) {
-            spaceRequired += NetlinkConstants.alignedLengthOf(
-                    StructNlAttr.NLA_HEADERLEN + mIpAddress.getAddress().length);
-        }
-        if (mIfacacheInfo != null) {
-            spaceRequired += NetlinkConstants.alignedLengthOf(
-                    StructNlAttr.NLA_HEADERLEN + StructIfacacheInfo.STRUCT_SIZE);
-        }
-        spaceRequired += StructNlAttr.NLA_HEADERLEN + 4; // IFA_FLAGS "u32" attr
+        // IFA_ADDRESS attr
+        spaceRequired += NetlinkConstants.alignedLengthOf(
+                StructNlAttr.NLA_HEADERLEN + mIpAddress.getAddress().length);
+        // IFA_CACHEINFO attr
+        spaceRequired += NetlinkConstants.alignedLengthOf(
+                StructNlAttr.NLA_HEADERLEN + StructIfacacheInfo.STRUCT_SIZE);
+        // IFA_FLAGS "u32" attr
+        spaceRequired += StructNlAttr.NLA_HEADERLEN + 4;
         return spaceRequired;
     }
 
diff --git a/staticlibs/framework/com/android/net/module/util/NetworkStackConstants.java b/staticlibs/framework/com/android/net/module/util/NetworkStackConstants.java
index 287473e..7b3943c 100644
--- a/staticlibs/framework/com/android/net/module/util/NetworkStackConstants.java
+++ b/staticlibs/framework/com/android/net/module/util/NetworkStackConstants.java
@@ -210,6 +210,17 @@
     public static final int DHCP4_CLIENT_PORT = 68;
 
     /**
+     * DHCPv6 constants.
+     *
+     * See also:
+     *     - https://datatracker.ietf.org/doc/html/rfc8415
+     */
+    public static final int DHCP6_CLIENT_PORT = 546;
+    public static final int DHCP6_SERVER_PORT = 547;
+    public static final Inet6Address ALL_DHCP_RELAY_AGENTS_AND_SERVERS =
+            (Inet6Address) InetAddresses.parseNumericAddress("ff02::1:2");
+
+    /**
      * IEEE802.11 standard constants.
      *
      * See also:
diff --git a/staticlibs/native/bpf_headers/Android.bp b/staticlibs/native/bpf_headers/Android.bp
index 98694b2..31adef9 100644
--- a/staticlibs/native/bpf_headers/Android.bp
+++ b/staticlibs/native/bpf_headers/Android.bp
@@ -38,12 +38,12 @@
     ],
 }
 
-
 cc_test {
     // TODO: Rename to bpf_map_test and modify .gcls as well.
     name: "libbpf_android_test",
     srcs: [
         "BpfMapTest.cpp",
+        "BpfRingbufTest.cpp",
     ],
     defaults: ["bpf_defaults"],
     cflags: [
diff --git a/staticlibs/native/bpf_headers/BpfRingbufTest.cpp b/staticlibs/native/bpf_headers/BpfRingbufTest.cpp
new file mode 100644
index 0000000..0785d62
--- /dev/null
+++ b/staticlibs/native/bpf_headers/BpfRingbufTest.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/file.h>
+#include <android-base/macros.h>
+#include <android-base/result-gmock.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "bpf/BpfUtils.h"
+
+namespace android {
+namespace bpf {
+using ::android::base::testing::HasError;
+using ::android::base::testing::HasValue;
+using ::android::base::testing::WithMessage;
+using ::testing::HasSubstr;
+
+class BpfRingbufTest : public ::testing::Test {
+ protected:
+  BpfRingbufTest()
+      : mProgPath("/sys/fs/bpf/prog_bpfRingbufProg_skfilter_ringbuf_test"),
+        mRingbufPath("/sys/fs/bpf/map_bpfRingbufProg_test_ringbuf") {}
+
+  void SetUp() {
+    if (!android::bpf::isAtLeastKernelVersion(5, 8, 0)) {
+      GTEST_SKIP() << "BPF ring buffers not supported";
+      return;
+    }
+
+    errno = 0;
+    mProgram.reset(retrieveProgram(mProgPath.c_str()));
+    EXPECT_EQ(errno, 0);
+    ASSERT_GE(mProgram.get(), 0)
+        << mProgPath << " was either not found or inaccessible.";
+  }
+
+  std::string mProgPath;
+  std::string mRingbufPath;
+  android::base::unique_fd mProgram;
+};
+
+TEST_F(BpfRingbufTest, CheckSetUp) {}
+
+}  // namespace bpf
+}  // namespace android
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/netlink/RtNetlinkAddressMessageTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/netlink/RtNetlinkAddressMessageTest.java
index b21e060..f845eb4 100644
--- a/staticlibs/tests/unit/src/com/android/net/module/util/netlink/RtNetlinkAddressMessageTest.java
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/netlink/RtNetlinkAddressMessageTest.java
@@ -19,6 +19,9 @@
 import static android.system.OsConstants.IFA_F_PERMANENT;
 import static android.system.OsConstants.NETLINK_ROUTE;
 import static android.system.OsConstants.RT_SCOPE_LINK;
+import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
+
+import static com.android.testutils.MiscAsserts.assertThrows;
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
@@ -48,6 +51,8 @@
 public class RtNetlinkAddressMessageTest {
     private static final Inet6Address TEST_LINK_LOCAL =
             (Inet6Address) InetAddresses.parseNumericAddress("FE80::2C41:5CFF:FE09:6665");
+    private static final Inet6Address TEST_GLOBAL_ADDRESS =
+            (Inet6Address) InetAddresses.parseNumericAddress("2001:DB8:1::100");
 
     // An example of the full RTM_NEWADDR message.
     private static final String RTM_NEWADDR_HEX =
@@ -139,13 +144,13 @@
                 // struct nlmsghdr
                 "48000000" +    // length = 72
                 "1400" +        // type = 20 (RTM_NEWADDR)
-                "0501" +        // flags = NLM_F_ACK | NLM_F_REQUEST | NLM_F_REPLACE
+                "0500" +        // flags = NLM_F_ACK | NLM_F_REQUEST
                 "01000000" +    // seqno = 1
                 "00000000" +    // pid = 0 (send to kernel)
                 // struct IfaddrMsg
                 "0A" +          // family = inet6
                 "40" +          // prefix len = 64
-                "80" +          // flags = IFA_F_PERMANENT
+                "00" +          // flags = 0
                 "FD" +          // scope = RT_SCOPE_LINK
                 "17000000" +    // ifindex = 23
                 // struct nlattr: IFA_ADDRESS
@@ -167,13 +172,65 @@
                 HexEncoding.decode(expectedNewAddressHex.toCharArray(), false);
 
         final byte[] bytes = RtNetlinkAddressMessage.newRtmNewAddressMessage(1 /* seqno */,
-                TEST_LINK_LOCAL, (short) 64 /* prefix len */, (byte) IFA_F_PERMANENT /* flags */,
+                TEST_LINK_LOCAL, (short) 64 /* prefix len */, IFA_F_PERMANENT /* flags */,
                 (byte) RT_SCOPE_LINK /* scope */, 23 /* ifindex */,
                 (long) 0xFFFFFFFF /* preferred */, (long) 0xFFFFFFFF /* valid */);
         assertArrayEquals(expectedNewAddress, bytes);
     }
 
     @Test
+    public void testCreateRtmNewAddressMessage_nullIpAddress() {
+        assertThrows(NullPointerException.class,
+                () -> RtNetlinkAddressMessage.newRtmNewAddressMessage(1 /* seqno */,
+                        null /* IP address */, (short) 0 /* prefix len */,
+                        IFA_F_PERMANENT /* flags */, (byte) RT_SCOPE_LINK /* scope */,
+                        23 /* ifindex */, (long) 0xFFFFFFFF /* preferred */,
+                        (long) 0xFFFFFFFF /* valid */));
+    }
+
+    @Test
+    public void testCreateRtmNewAddressMessage_u32Flags() {
+        // Hexadecimal representation of our created packet.
+        final String expectedNewAddressHex =
+                // struct nlmsghdr
+                "48000000" +    // length = 72
+                "1400" +        // type = 20 (RTM_NEWADDR)
+                "0500" +        // flags = NLM_F_ACK | NLM_F_REQUEST
+                "01000000" +    // seqno = 1
+                "00000000" +    // pid = 0 (send to kernel)
+                // struct IfaddrMsg
+                "0A" +          // family = inet6
+                "80" +          // prefix len = 128
+                "00" +          // flags = 0
+                "00" +          // scope = RT_SCOPE_UNIVERSE
+                "17000000" +    // ifindex = 23
+                // struct nlattr: IFA_ADDRESS
+                "1400" +        // len
+                "0100" +        // type
+                "20010DB8000100000000000000000100" + // IP address = 2001:db8:1::100
+                // struct nlattr: IFA_CACHEINFO
+                "1400" +        // len
+                "0600" +        // type
+                "FFFFFFFF" +    // preferred = infinite
+                "FFFFFFFF" +    // valid = infinite
+                "00000000" +    // cstamp
+                "00000000" +    // tstamp
+                // struct nlattr: IFA_FLAGS
+                "0800" +        // len
+                "0800" +        // type
+                "00030000";     // flags = IFA_F_MANAGETEMPADDR | IFA_F_NOPREFIXROUTE
+        final byte[] expectedNewAddress =
+                HexEncoding.decode(expectedNewAddressHex.toCharArray(), false);
+
+        final byte[] bytes = RtNetlinkAddressMessage.newRtmNewAddressMessage(1 /* seqno */,
+                TEST_GLOBAL_ADDRESS, (short) 128 /* prefix len */,
+                (int) 0x300 /* flags: IFA_F_MANAGETEMPADDR | IFA_F_NOPREFIXROUTE */,
+                (byte) RT_SCOPE_UNIVERSE /* scope */, 23 /* ifindex */,
+                (long) 0xFFFFFFFF /* preferred */, (long) 0xFFFFFFFF /* valid */);
+        assertArrayEquals(expectedNewAddress, bytes);
+    }
+
+    @Test
     public void testToString() {
         final ByteBuffer byteBuffer = toByteBuffer(RTM_NEWADDR_HEX);
         byteBuffer.order(ByteOrder.LITTLE_ENDIAN);  // For testing.
diff --git a/staticlibs/testutils/host/com/android/testutils/ConnectivityCheckTargetPreparer.kt b/staticlibs/testutils/host/com/android/testutils/ConnectivityCheckTargetPreparer.kt
index 85589ad..ccc4064 100644
--- a/staticlibs/testutils/host/com/android/testutils/ConnectivityCheckTargetPreparer.kt
+++ b/staticlibs/testutils/host/com/android/testutils/ConnectivityCheckTargetPreparer.kt
@@ -21,6 +21,7 @@
 import com.android.tradefed.result.CollectingTestListener
 import com.android.tradefed.result.ddmlib.DefaultRemoteAndroidTestRunner
 import com.android.tradefed.targetprep.BaseTargetPreparer
+import com.android.tradefed.targetprep.TargetSetupError
 import com.android.tradefed.targetprep.suite.SuiteApkInstaller
 
 private const val CONNECTIVITY_CHECKER_APK = "ConnectivityChecker.apk"
@@ -52,13 +53,14 @@
 
         val receiver = CollectingTestListener()
         if (!testInformation.device.runInstrumentationTests(runner, receiver)) {
-            throw AssertionError("Device state check failed to complete")
+            throw TargetSetupError("Device state check failed to complete",
+                    testInformation.device.deviceDescriptor)
         }
 
         val runResult = receiver.currentRunResults
         if (runResult.isRunFailure) {
-            throw AssertionError("Failed to check device state before the test: " +
-                    runResult.runFailureMessage)
+            throw TargetSetupError("Failed to check device state before the test: " +
+                    runResult.runFailureMessage, testInformation.device.deviceDescriptor)
         }
 
         if (!runResult.hasFailedTests()) return
@@ -67,7 +69,8 @@
             else "$testDescription: ${testResult.stackTrace}"
         }.joinToString("\n")
 
-        throw AssertionError("Device setup checks failed. Check the test bench: \n$errorMsg")
+        throw TargetSetupError("Device setup checks failed. Check the test bench: \n$errorMsg",
+                testInformation.device.deviceDescriptor)
     }
 
     override fun tearDown(testInformation: TestInformation?, e: Throwable?) {