Merge "BpfMap.h - hide dangerous stuff behind #ifdef BPF_MAP_MAKE_VISIBLE_FOR_TESTING"
diff --git a/staticlibs/device/com/android/net/module/util/SharedLog.java b/staticlibs/device/com/android/net/module/util/SharedLog.java
index 37c6f6d..17b061e 100644
--- a/staticlibs/device/com/android/net/module/util/SharedLog.java
+++ b/staticlibs/device/com/android/net/module/util/SharedLog.java
@@ -26,6 +26,7 @@
 import java.time.LocalDateTime;
 import java.util.ArrayDeque;
 import java.util.Deque;
+import java.util.Iterator;
 import java.util.StringJoiner;
 
 
@@ -94,6 +95,15 @@
         mLocalLog.dump(writer);
     }
 
+    /**
+     * Reverse dump the contents of this log.
+     *
+     * <p>This method may be called on any thread.
+     */
+    public void reverseDump(PrintWriter writer) {
+        mLocalLog.reverseDump(writer);
+    }
+
     //////
     // Methods that both log an entry and emit it to the system log.
     //////
@@ -228,5 +238,12 @@
                 pw.println(s);
             }
         }
+
+        synchronized void reverseDump(PrintWriter pw) {
+            final Iterator<String> itr = mLog.descendingIterator();
+            while (itr.hasNext()) {
+                pw.println(itr.next());
+            }
+        }
     }
 }
diff --git a/staticlibs/device/com/android/net/module/util/ip/NetlinkMonitor.java b/staticlibs/device/com/android/net/module/util/ip/NetlinkMonitor.java
index 8589876..942aaf1 100644
--- a/staticlibs/device/com/android/net/module/util/ip/NetlinkMonitor.java
+++ b/staticlibs/device/com/android/net/module/util/ip/NetlinkMonitor.java
@@ -18,6 +18,7 @@
 
 import static android.net.util.SocketUtils.makeNetlinkSocketAddress;
 import static android.system.OsConstants.AF_NETLINK;
+import static android.system.OsConstants.ENOBUFS;
 import static android.system.OsConstants.SOCK_DGRAM;
 import static android.system.OsConstants.SOCK_NONBLOCK;
 import static android.system.OsConstants.SOL_SOCKET;
@@ -102,7 +103,11 @@
         try {
             fd = Os.socket(AF_NETLINK, SOCK_DGRAM | SOCK_NONBLOCK, mFamily);
             if (mSockRcvbufSize != DEFAULT_SOCKET_RECV_BUFSIZE) {
-                Os.setsockoptInt(fd, SOL_SOCKET, SO_RCVBUF, mSockRcvbufSize);
+                try {
+                    Os.setsockoptInt(fd, SOL_SOCKET, SO_RCVBUF, mSockRcvbufSize);
+                } catch (ErrnoException e) {
+                    Log.wtf(mTag, "Failed to set SO_RCVBUF to " + mSockRcvbufSize, e);
+                }
             }
             Os.bind(fd, makeNetlinkSocketAddress(0, mBindGroups));
             NetlinkSocket.connectToKernel(fd);
@@ -148,6 +153,32 @@
         }
     }
 
+    @Override
+    protected void logError(String msg, Exception e) {
+        mLog.e(msg, e);
+    }
+
+    // Ignoring ENOBUFS may miss any important netlink messages, there are some messages which
+    // cannot be recovered by dumping current state once missed since kernel doesn't keep state
+    // for it. In addition, dumping current state will not result in any RTM_DELxxx messages, so
+    // reconstructing current state from a dump will be difficult. However, for those netlink
+    // messages don't cause any state changes, e.g. RTM_NEWLINK with current link state, maybe
+    // it's okay to ignore them, because these netlink messages won't cause any changes on the
+    // LinkProperties. Given the above trade-offs, try to ignore ENOBUFS and that's similar to
+    // what netd does today.
+    //
+    // TODO: log metrics when ENOBUFS occurs, or even force a disconnect, it will help see how
+    // often this error occurs on fields with the associated socket receive buffer size.
+    @Override
+    protected boolean handleReadError(ErrnoException e) {
+        logError("readPacket error: ", e);
+        if (e.errno == ENOBUFS) {
+            Log.wtf(mTag, "Errno: ENOBUFS");
+            return false;
+        }
+        return true;
+    }
+
     // TODO: move NetworkStackUtils to frameworks/libs/net for NetworkStackUtils#closeSocketQuietly.
     private void closeSocketQuietly(FileDescriptor fd) {
         try {