Merge "Use netlink to set MTU in IpClient(1/2)" into main
diff --git a/staticlibs/device/com/android/net/module/util/netlink/NetlinkUtils.java b/staticlibs/device/com/android/net/module/util/netlink/NetlinkUtils.java
index 0d96fc4..2420e7a 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/NetlinkUtils.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/NetlinkUtils.java
@@ -497,4 +497,33 @@
             return false;
         }
     }
+
+    /**
+     * Sends a netlink request to set MTU for given interface
+     *
+     * @param interfaceName The name of the network interface to query.
+     * @param mtu MTU value to set for the interface.
+     * @return true if the request finished successfully, otherwise false.
+     */
+    public static boolean setInterfaceMtu(@NonNull String interfaceName, int mtu) {
+        if (mtu < 68) {
+            Log.e(TAG, "Invalid mtu: " + mtu + ", mtu should be greater than 68 referring RFC791");
+            return false;
+        }
+        final RtNetlinkLinkMessage ntMsg =
+                RtNetlinkLinkMessage.createSetMtuMessage(interfaceName, /*seqNo*/ 0, mtu);
+        if (ntMsg == null) {
+            Log.e(TAG, "Failed to create message to set MTU to " + mtu
+                    + "for interface " + interfaceName);
+            return false;
+        }
+        final byte[] msg = ntMsg.pack(ByteOrder.nativeOrder());
+        try {
+            NetlinkUtils.sendOneShotKernelMessage(NETLINK_ROUTE, msg);
+            return true;
+        } catch (ErrnoException e) {
+            Log.e(TAG, "Failed to set MTU to " + mtu + " for: " + interfaceName, e);
+            return false;
+        }
+    }
 }
diff --git a/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkLinkMessage.java b/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkLinkMessage.java
index f17a7ec..c19a124 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkLinkMessage.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkLinkMessage.java
@@ -364,6 +364,37 @@
                 DEFAULT_MTU, /*hardwareAddress*/ null, /*interfaceName*/ null);
     }
 
+    /**
+     * Creates an {@link RtNetlinkLinkMessage} instance that can be used to set the MTU of a
+     * network interface.
+     *
+     * @param interfaceName The name of the network interface to query.
+     * @param sequenceNumber The sequence number for the Netlink message.
+     * @param mtu MTU value to set for the interface.
+     * @return An `RtNetlinkLinkMessage` instance representing the request to query the interface.
+     */
+    @Nullable
+    public static RtNetlinkLinkMessage createSetMtuMessage(@NonNull String interfaceName,
+            int sequenceNumber, int mtu) {
+        return createSetMtuMessage(
+            interfaceName, sequenceNumber, mtu, new OsAccess());
+    }
+
+    @VisibleForTesting
+    @Nullable
+    protected static RtNetlinkLinkMessage createSetMtuMessage(@NonNull String interfaceName,
+            int sequenceNumber, int mtu, @NonNull OsAccess osAccess) {
+        final int interfaceIndex = osAccess.if_nametoindex(interfaceName);
+        if (interfaceIndex == OsAccess.INVALID_INTERFACE_INDEX) {
+            return null;
+        }
+        return RtNetlinkLinkMessage.build(
+            new StructNlMsgHdr(/*payloadLen*/ 0, RTM_NEWLINK, NLM_F_REQUEST_ACK , sequenceNumber),
+            new StructIfinfoMsg((short) AF_UNSPEC, /*type*/ 0, interfaceIndex,
+                /*flags*/ 0, /*change*/ 0),
+            mtu, /*hardwareAddress*/ null, /*interfaceName*/ null);
+    }
+
     @Override
     public String toString() {
         return "RtNetlinkLinkMessage{ "
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/netlink/RtNetlinkLinkMessageTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/netlink/RtNetlinkLinkMessageTest.java
index b29fc73..13710b1 100644
--- a/staticlibs/tests/unit/src/com/android/net/module/util/netlink/RtNetlinkLinkMessageTest.java
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/netlink/RtNetlinkLinkMessageTest.java
@@ -328,6 +328,28 @@
     }
 
     @Test
+    public void testCreateSetInterfaceMtuMessage() {
+        final String expectedHexBytes =
+                "280000001000050068240000000000000000000008000000"   // struct nlmsghdr
+                        + "000000000000000008000400DC050000"; // struct ifinfomsg
+        final String interfaceName = "wlan0";
+        final int interfaceIndex = 8;
+        final int sequenceNumber = 0x2468;
+        final int mtu = 1500;
+
+        when(mOsAccess.if_nametoindex(interfaceName)).thenReturn(interfaceIndex);
+
+        final RtNetlinkLinkMessage msg = RtNetlinkLinkMessage.createSetMtuMessage(
+                interfaceName,
+                sequenceNumber,
+                mtu,
+                mOsAccess);
+        assertNotNull(msg);
+        final byte[] bytes = msg.pack(ByteOrder.LITTLE_ENDIAN);  // For testing.
+        assertEquals(expectedHexBytes, HexDump.toHexString(bytes));
+    }
+
+    @Test
     public void testToString() {
         final ByteBuffer byteBuffer = toByteBuffer(RTM_NEWLINK_HEX);
         byteBuffer.order(ByteOrder.LITTLE_ENDIAN);  // For testing.