Merge "Change creation methods in RtNetlinkLinkMessage to take index(1/2)" into main

This commit is contained in:
Chuwei He 2025-05-14 00:15:03 -07:00 • committed by Android (Google) Code Review
commit 38f66bdf9b
4 changed files with 56 additions and 124 deletions

View file

@ -45,6 +45,7 @@ import android.os.ConditionVariable;
import android.os.Handler;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.system.Os;
import android.system.OsConstants;
import android.text.TextUtils;
import android.util.ArrayMap;
@ -872,7 +873,8 @@ public class EthernetTracker {
}
private void setInterfaceUpState(@NonNull String interfaceName, boolean up) {
if (!NetlinkUtils.setInterfaceFlags(interfaceName, up ? IFF_UP : ~IFF_UP)) {
if (!NetlinkUtils.setInterfaceFlags(Os.if_nametoindex(interfaceName),
up ? IFF_UP : ~IFF_UP)) {
Log.e(TAG, "Failed to set interface " + interfaceName + (up ? " up" : " down"));
}
}

View file

@ -474,18 +474,18 @@ public class NetlinkUtils {
/**
* Sends a netlink request to set flags for given interface
*
* @param interfaceName The name of the network interface to query.
* @param ifIndex The index of the network interface to configure.
* @param flags power-of-two integer flags to set or unset. A flag to set should be passed as
* is as a power-of-two value, and a flag to remove should be passed inversed as -1 with
* a single bit down. For example: IFF_UP, ~IFF_BROADCAST...
* @return true if the request finished successfully, otherwise false.
*/
public static boolean setInterfaceFlags(@NonNull String interfaceName, int... flags) {
public static boolean setInterfaceFlags(int ifIndex, int... flags) {
final RtNetlinkLinkMessage ntMsg =
RtNetlinkLinkMessage.createSetFlagsMessage(interfaceName, /*seqNo*/ 0, flags);
RtNetlinkLinkMessage.createSetFlagsMessage(ifIndex, /*seqNo*/ 0, flags);
if (ntMsg == null) {
Log.e(TAG, "Failed to create message to set interface flags for interface "
+ interfaceName + ", input flags are: " + Arrays.toString(flags));
Log.e(TAG, "Failed to create message to set interface flags for interface with index: "
+ ifIndex + ", input flags are: " + Arrays.toString(flags));
return false;
}
final byte[] msg = ntMsg.pack(ByteOrder.nativeOrder());
@ -493,7 +493,7 @@ public class NetlinkUtils {
NetlinkUtils.sendOneShotKernelMessage(NETLINK_ROUTE, msg);
return true;
} catch (ErrnoException e) {
Log.e(TAG, "Failed to set flags for: " + interfaceName, e);
Log.e(TAG, "Failed to set flags for interface with index: " + ifIndex, e);
return false;
}
}
@ -501,20 +501,20 @@ public class NetlinkUtils {
/**
* Sends a netlink request to set MTU for given interface
*
* @param interfaceName The name of the network interface to query.
* @param ifIndex The index of the network interface to configure.
* @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) {
public static boolean setInterfaceMtu(int ifIndex, 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);
RtNetlinkLinkMessage.createSetMtuMessage(ifIndex, /*seqNo*/ 0, mtu);
if (ntMsg == null) {
Log.e(TAG, "Failed to create message to set MTU to " + mtu
+ "for interface " + interfaceName);
+ "for interface with index: " + ifIndex);
return false;
}
final byte[] msg = ntMsg.pack(ByteOrder.nativeOrder());
@ -522,7 +522,7 @@ public class NetlinkUtils {
NetlinkUtils.sendOneShotKernelMessage(NETLINK_ROUTE, msg);
return true;
} catch (ErrnoException e) {
Log.e(TAG, "Failed to set MTU to " + mtu + " for: " + interfaceName, e);
Log.e(TAG, "Failed to set MTU to " + mtu + " for interface with index: " + ifIndex, e);
return false;
}
}

View file

@ -227,58 +227,44 @@ public class RtNetlinkLinkMessage extends NetlinkMessage {
/**
* Create a link message to set the operational state (up or down) of a network interface.
*
* @param interfaceName The network interface name.
* @param ifIndex The network interface index of the network interface to set state.
* @param sequenceNumber The sequence number to use for the Netlink message.
* @param isUp {@code true} to set the interface up, {@code false} to set it down.
* @return A `RtNetlinkLinkMessage` instance configured to set the link state.
* @return A `RtNetlinkLinkMessage` instance configured to set the link state, or return null
* in case of an error.
*/
@Nullable
public static RtNetlinkLinkMessage createSetLinkStateMessage(@NonNull String interfaceName,
public static RtNetlinkLinkMessage createSetLinkStateMessage(int ifIndex,
int sequenceNumber, boolean isUp) {
return createSetLinkStateMessage(interfaceName, sequenceNumber, isUp, new OsAccess());
}
@VisibleForTesting
@Nullable
protected static RtNetlinkLinkMessage createSetLinkStateMessage(@NonNull String interfaceName,
int sequenceNumber, boolean isUp, OsAccess osAccess) {
final int interfaceIndex = osAccess.if_nametoindex(interfaceName);
if (interfaceIndex == OsAccess.INVALID_INTERFACE_INDEX) {
if (ifIndex <= 0) {
return null;
}
return RtNetlinkLinkMessage.build(
new StructNlMsgHdr(0, RTM_NEWLINK, NLM_F_REQUEST_ACK, sequenceNumber),
new StructIfinfoMsg((short) AF_UNSPEC, (short) 0, interfaceIndex,
new StructIfinfoMsg((short) AF_UNSPEC, (short) 0, ifIndex,
isUp ? IFF_UP : 0, IFF_UP), DEFAULT_MTU, null, null);
}
/**
* Create a link message to rename the network interface.
*
* @param interfaceName The network interface name.
* @param ifIndex The network interface index of the network interface to rename.
* @param sequenceNumber The sequence number to use for the Netlink message.
* @param newName The new name of the network interface.
* @return A `RtNetlinkLinkMessage` instance configured to rename the network interface.
* @return A `RtNetlinkLinkMessage` instance configured to rename the network interface,
* or return null in case of an error.
*/
@Nullable
public static RtNetlinkLinkMessage createSetLinkNameMessage(@NonNull String interfaceName,
public static RtNetlinkLinkMessage createSetLinkNameMessage(int ifIndex,
int sequenceNumber, @NonNull String newName) {
return createSetLinkNameMessage(interfaceName, sequenceNumber, newName, new OsAccess());
}
@VisibleForTesting
@Nullable
protected static RtNetlinkLinkMessage createSetLinkNameMessage(@NonNull String interfaceName,
int sequenceNumber, @NonNull String newName, OsAccess osAccess) {
final int interfaceIndex = osAccess.if_nametoindex(interfaceName);
if (interfaceIndex == OsAccess.INVALID_INTERFACE_INDEX) {
if (ifIndex <= 0) {
return null;
}
return RtNetlinkLinkMessage.build(
new StructNlMsgHdr(0, RTM_NEWLINK, NLM_F_REQUEST_ACK, sequenceNumber),
new StructIfinfoMsg((short) AF_UNSPEC, (short) 0, interfaceIndex, 0, 0),
new StructIfinfoMsg((short) AF_UNSPEC, (short) 0, ifIndex, 0, 0),
DEFAULT_MTU, null, newName);
}
@ -286,28 +272,21 @@ public class RtNetlinkLinkMessage extends NetlinkMessage {
* Creates an {@link RtNetlinkLinkMessage} instance that can be used to get the link information
* of a network interface.
*
* @param interfaceName The name of the network interface to query.
* @param ifIndex The index of the network interface to query.
* @param sequenceNumber The sequence number for the Netlink message.
* @return An `RtNetlinkLinkMessage` instance representing the request to query the interface.
* @return An `RtNetlinkLinkMessage` instance representing the request to query the interface,
* or return null in case of an error.
*/
@Nullable
public static RtNetlinkLinkMessage createGetLinkMessage(@NonNull String interfaceName,
public static RtNetlinkLinkMessage createGetLinkMessage(int ifIndex,
int sequenceNumber) {
return createGetLinkMessage(interfaceName, sequenceNumber, new OsAccess());
}
@VisibleForTesting
@Nullable
protected static RtNetlinkLinkMessage createGetLinkMessage(@NonNull String interfaceName,
int sequenceNumber, @NonNull OsAccess osAccess) {
final int interfaceIndex = osAccess.if_nametoindex(interfaceName);
if (interfaceIndex == OsAccess.INVALID_INTERFACE_INDEX) {
if (ifIndex <= 0) {
return null;
}
return RtNetlinkLinkMessage.build(
new StructNlMsgHdr(0, RTM_GETLINK, NLM_F_REQUEST_ACK, sequenceNumber),
new StructIfinfoMsg((short) AF_UNSPEC, (short) 0, interfaceIndex, 0, 0),
new StructIfinfoMsg((short) AF_UNSPEC, (short) 0, ifIndex, 0, 0),
DEFAULT_MTU, null, null);
}
@ -315,27 +294,18 @@ public class RtNetlinkLinkMessage extends NetlinkMessage {
* Creates an {@link RtNetlinkLinkMessage} instance that can be used to set the flags of a
* network interface.
*
* @param interfaceName The name of the network interface to query.
* @param ifIndex The index of the network interface to configure.
* @param sequenceNumber The sequence number for the Netlink message.
* @param flags power-of-two integer flags to set or unset. A flag to set should be passed as
* is as a power-of-two value, and a flag to remove should be passed inversed as -1 with
* a single bit down. For example: IFF_UP, ~IFF_BROADCAST...
* @return An `RtNetlinkLinkMessage` instance representing the request to query the interface.
* @return An `RtNetlinkLinkMessage` instance representing the request to query the interface,
* or return null in case of an error.
*/
@Nullable
public static RtNetlinkLinkMessage createSetFlagsMessage(@NonNull String interfaceName,
public static RtNetlinkLinkMessage createSetFlagsMessage(int ifIndex,
int sequenceNumber, int... flags) {
return createSetFlagsMessage(
interfaceName, sequenceNumber, new OsAccess(), flags);
}
@VisibleForTesting
@Nullable
protected static RtNetlinkLinkMessage createSetFlagsMessage(
@NonNull String interfaceName, int sequenceNumber, @NonNull OsAccess osAccess,
int... flags) {
final int interfaceIndex = osAccess.if_nametoindex(interfaceName);
if (interfaceIndex == OsAccess.INVALID_INTERFACE_INDEX) {
if (ifIndex <= 0) {
return null;
}
@ -358,7 +328,7 @@ public class RtNetlinkLinkMessage extends NetlinkMessage {
return RtNetlinkLinkMessage.build(
new StructNlMsgHdr(
/*payloadLen*/ 0, RTM_NEWLINK, NLM_F_REQUEST_ACK, sequenceNumber),
new StructIfinfoMsg((short) AF_UNSPEC, /*type*/ 0, interfaceIndex,
new StructIfinfoMsg((short) AF_UNSPEC, /*type*/ 0, ifIndex,
flagsBits, changeBits),
DEFAULT_MTU, /*hardwareAddress*/ null, /*interfaceName*/ null);
}
@ -367,29 +337,21 @@ public class RtNetlinkLinkMessage extends NetlinkMessage {
* 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 ifIndex The index of the network interface to configure.
* @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.
* @return An `RtNetlinkLinkMessage` instance representing the request to query the interface,
* or return null in case of an error.
*/
@Nullable
public static RtNetlinkLinkMessage createSetMtuMessage(@NonNull String interfaceName,
public static RtNetlinkLinkMessage createSetMtuMessage(int ifIndex,
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) {
if (ifIndex <= 0) {
return null;
}
return RtNetlinkLinkMessage.build(
new StructNlMsgHdr(/*payloadLen*/ 0, RTM_NEWLINK, NLM_F_REQUEST_ACK , sequenceNumber),
new StructIfinfoMsg((short) AF_UNSPEC, /*type*/ 0, interfaceIndex,
new StructIfinfoMsg((short) AF_UNSPEC, /*type*/ 0, ifIndex,
/*flags*/ 0, /*change*/ 0),
mtu, /*hardwareAddress*/ null, /*interfaceName*/ null);
}

View file

@ -24,7 +24,6 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
import android.net.MacAddress;
import android.system.OsConstants;
@ -35,7 +34,6 @@ import com.android.net.module.util.HexDump;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.nio.ByteBuffer;
@ -44,9 +42,6 @@ import java.nio.ByteOrder;
@RunWith(MockitoJUnitRunner.class)
@SmallTest
public class RtNetlinkLinkMessageTest {
@Mock
private OsAccess mOsAccess;
// An example of the full RTM_NEWLINK message.
private static final String RTM_NEWLINK_HEX =
"64000000100000000000000000000000" // struct nlmsghr
@ -194,15 +189,12 @@ public class RtNetlinkLinkMessageTest {
final String expectedHexBytes =
"20000000100005006824000000000000" // struct nlmsghdr
+ "00000000080000000100000001000000"; // struct ifinfomsg
final String interfaceName = "wlan0";
final int interfaceIndex = 8;
final int sequenceNumber = 0x2468;
final boolean isUp = true;
when(mOsAccess.if_nametoindex(interfaceName)).thenReturn(interfaceIndex);
final RtNetlinkLinkMessage msg = RtNetlinkLinkMessage.createSetLinkStateMessage(
interfaceName, sequenceNumber, isUp, mOsAccess);
interfaceIndex, sequenceNumber, isUp);
assertNotNull(msg);
final byte[] bytes = msg.pack(ByteOrder.LITTLE_ENDIAN); // For testing.
assertEquals(expectedHexBytes, HexDump.toHexString(bytes));
@ -213,15 +205,12 @@ public class RtNetlinkLinkMessageTest {
final String expectedHexBytes =
"20000000100005006824000000000000" // struct nlmsghdr
+ "00000000080000000000000001000000"; // struct ifinfomsg
final String interfaceName = "wlan0";
final int interfaceIndex = 8;
final int sequenceNumber = 0x2468;
final boolean isUp = false;
when(mOsAccess.if_nametoindex(interfaceName)).thenReturn(interfaceIndex);
final RtNetlinkLinkMessage msg = RtNetlinkLinkMessage.createSetLinkStateMessage(
interfaceName, sequenceNumber, isUp, mOsAccess);
interfaceIndex, sequenceNumber, isUp);
assertNotNull(msg);
final byte[] bytes = msg.pack(ByteOrder.LITTLE_ENDIAN); // For testing.
assertEquals(expectedHexBytes, HexDump.toHexString(bytes));
@ -229,14 +218,12 @@ public class RtNetlinkLinkMessageTest {
@Test
public void testCreateSetLinkStateMessage_InvalidInterface() {
final String interfaceName = "wlan0";
final int interfaceIndex = OsAccess.INVALID_INTERFACE_INDEX;
final int sequenceNumber = 0x2468;
final boolean isUp = false;
when(mOsAccess.if_nametoindex(interfaceName)).thenReturn(OsAccess.INVALID_INTERFACE_INDEX);
final RtNetlinkLinkMessage msg = RtNetlinkLinkMessage.createSetLinkStateMessage(
interfaceName, sequenceNumber, isUp, mOsAccess);
interfaceIndex, sequenceNumber, isUp);
assertNull(msg);
}
@ -246,15 +233,12 @@ public class RtNetlinkLinkMessageTest {
"2C000000100005006824000000000000" // struct nlmsghdr
+ "00000000080000000000000000000000" // struct ifinfomsg
+ "0A000300776C616E31000000"; // IFLA_IFNAME(wlan1)
final String interfaceName = "wlan0";
final int interfaceIndex = 8;
final int sequenceNumber = 0x2468;
final String newName = "wlan1";
when(mOsAccess.if_nametoindex(interfaceName)).thenReturn(interfaceIndex);
final RtNetlinkLinkMessage msg = RtNetlinkLinkMessage.createSetLinkNameMessage(
interfaceName, sequenceNumber, newName, mOsAccess);
interfaceIndex, sequenceNumber, newName);
assertNotNull(msg);
final byte[] bytes = msg.pack(ByteOrder.LITTLE_ENDIAN); // For testing.
assertEquals(expectedHexBytes, HexDump.toHexString(bytes));
@ -262,28 +246,23 @@ public class RtNetlinkLinkMessageTest {
@Test
public void testCreateSetLinkNameMessage_InterfaceNotFound() {
final String interfaceName = "wlan0";
final int interfaceIndex = OsAccess.INVALID_INTERFACE_INDEX;
final int sequenceNumber = 0x2468;
final String newName = "wlan1";
when(mOsAccess.if_nametoindex(interfaceName)).thenReturn(OsAccess.INVALID_INTERFACE_INDEX);
assertNull(RtNetlinkLinkMessage.createSetLinkNameMessage(
interfaceName, sequenceNumber, newName, mOsAccess));
interfaceIndex, sequenceNumber, newName));
}
@Test
public void testCreateSetLinkNameMessage_InvalidNewName() {
final String interfaceName = "wlan0";
final int interfaceIndex = 8;
final int sequenceNumber = 0x2468;
when(mOsAccess.if_nametoindex(interfaceName)).thenReturn(interfaceIndex);
final String[] invalidNames = {"", "interface_name_longer_than_limit"};
for (String invalidName : invalidNames) {
assertNull(RtNetlinkLinkMessage.createSetLinkNameMessage(
interfaceName, sequenceNumber, invalidName, mOsAccess));
interfaceIndex, sequenceNumber, invalidName));
}
}
@ -292,14 +271,11 @@ public class RtNetlinkLinkMessageTest {
final String expectedHexBytes =
"20000000120005006824000000000000" // struct nlmsghdr
+ "00000000080000000000000000000000"; // struct ifinfomsg
final String interfaceName = "wlan0";
final int interfaceIndex = 8;
final int sequenceNumber = 0x2468;
when(mOsAccess.if_nametoindex(interfaceName)).thenReturn(interfaceIndex);
final RtNetlinkLinkMessage msg = RtNetlinkLinkMessage.createGetLinkMessage(
interfaceName, sequenceNumber, mOsAccess);
interfaceIndex, sequenceNumber);
assertNotNull(msg);
final byte[] bytes = msg.pack(ByteOrder.LITTLE_ENDIAN); // For testing.
assertEquals(expectedHexBytes, HexDump.toHexString(bytes));
@ -310,16 +286,12 @@ public class RtNetlinkLinkMessageTest {
final String expectedHexBytes =
"20000000100005006824000000000000" // struct nlmsghdr
+ "00000000080000000100000001000100"; // struct ifinfomsg
final String interfaceName = "wlan0";
final int interfaceIndex = 8;
final int sequenceNumber = 0x2468;
when(mOsAccess.if_nametoindex(interfaceName)).thenReturn(interfaceIndex);
final RtNetlinkLinkMessage msg = RtNetlinkLinkMessage.createSetFlagsMessage(
interfaceName,
interfaceIndex,
sequenceNumber,
mOsAccess,
NetlinkConstants.IFF_UP,
~NetlinkConstants.IFF_LOWER_UP);
assertNotNull(msg);
@ -332,18 +304,14 @@ public class RtNetlinkLinkMessageTest {
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,
interfaceIndex,
sequenceNumber,
mtu,
mOsAccess);
mtu);
assertNotNull(msg);
final byte[] bytes = msg.pack(ByteOrder.LITTLE_ENDIAN); // For testing.
assertEquals(expectedHexBytes, HexDump.toHexString(bytes));