Use netlink to set MTU in IpClient(1/2)
Currently IpClient uses netd to set MTU for interfaces while the
usage of netd can bring some unexpected side effects and execute in
slower speed.
This change moves forward with one less usage of netd to use netlink
directly set MTU in IpClient.
This patch adds support in netlink utils to set MTU for interfaces.
Bug: 383663804
Test: Manually call and make sure interface MTU is updated
Test: atest NetworkStaticLibTests
Change-Id: Id73d78156d1a560262e42540a3503d059a172e34
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 1afe3b8..91fc5cd 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkLinkMessage.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkLinkMessage.java
@@ -363,6 +363,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 8104e3a..5a9b265 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.