Merge "Add createSetLinkStateMessage method at RtNetlinkLinkMessage" into main
This commit is contained in:
commit
dde0dc63d3
4 changed files with 134 additions and 6 deletions
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (C) 2024 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.
|
||||
*/
|
||||
|
||||
package com.android.net.module.util.netlink;
|
||||
|
||||
import android.system.Os;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* This class wraps the static methods of {@link android.system.Os} for mocking and testing.
|
||||
*/
|
||||
public class OsAccess {
|
||||
/**
|
||||
* Constant indicating that the {@code if_nametoindex()} function could not find the network
|
||||
* interface index corresponding to the given interface name.
|
||||
*/
|
||||
public static int INVALID_INTERFACE_INDEX = 0;
|
||||
|
||||
/** Wraps {@link Os#if_nametoindex(String)}. */
|
||||
public int if_nametoindex(@NonNull String name) {
|
||||
return Os.if_nametoindex(name);
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,12 @@
|
|||
|
||||
package com.android.net.module.util.netlink;
|
||||
|
||||
import static android.system.OsConstants.AF_UNSPEC;
|
||||
|
||||
import static com.android.net.module.util.NetworkStackConstants.ETHER_ADDR_LEN;
|
||||
import static com.android.net.module.util.netlink.NetlinkConstants.IFF_UP;
|
||||
import static com.android.net.module.util.netlink.NetlinkConstants.RTM_NEWLINK;
|
||||
import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REQUEST_ACK;
|
||||
|
||||
import android.net.MacAddress;
|
||||
import android.system.OsConstants;
|
||||
|
|
@ -218,6 +223,35 @@ public class RtNetlinkLinkMessage extends NetlinkMessage {
|
|||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a link message to set the operational state (up or down) of a network interface.
|
||||
*
|
||||
* @param interfaceName The network interface name.
|
||||
* @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.
|
||||
*/
|
||||
@Nullable
|
||||
public static RtNetlinkLinkMessage createSetLinkStateMessage(@NonNull String interfaceName,
|
||||
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) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return RtNetlinkLinkMessage.build(
|
||||
new StructNlMsgHdr(0, RTM_NEWLINK, NLM_F_REQUEST_ACK, sequenceNumber),
|
||||
new StructIfinfoMsg((short) AF_UNSPEC, (short) 0, interfaceIndex,
|
||||
isUp ? IFF_UP : 0, IFF_UP), DEFAULT_MTU, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RtNetlinkLinkMessage{ "
|
||||
|
|
|
|||
|
|
@ -32,10 +32,11 @@ public class StructNlMsgHdr {
|
|||
// Already aligned.
|
||||
public static final int STRUCT_SIZE = 16;
|
||||
|
||||
public static final short NLM_F_REQUEST = 0x0001;
|
||||
public static final short NLM_F_MULTI = 0x0002;
|
||||
public static final short NLM_F_ACK = 0x0004;
|
||||
public static final short NLM_F_ECHO = 0x0008;
|
||||
public static final short NLM_F_REQUEST = 0x0001;
|
||||
public static final short NLM_F_MULTI = 0x0002;
|
||||
public static final short NLM_F_ACK = 0x0004;
|
||||
public static final short NLM_F_ECHO = 0x0008;
|
||||
public static final short NLM_F_REQUEST_ACK = NLM_F_REQUEST | NLM_F_ACK;
|
||||
// Flags for a GET request.
|
||||
public static final short NLM_F_ROOT = 0x0100;
|
||||
public static final short NLM_F_MATCH = 0x0200;
|
||||
|
|
|
|||
|
|
@ -24,24 +24,29 @@ 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.annotation.SuppressLint;
|
||||
import android.net.MacAddress;
|
||||
import android.system.OsConstants;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
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;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@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 =
|
||||
|
|
@ -185,6 +190,57 @@ public class RtNetlinkLinkMessageTest {
|
|||
assertTrue(linkMsg.getInterfaceName().equals("wlan0"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateSetLinkUpMessage() {
|
||||
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);
|
||||
assertNotNull(msg);
|
||||
final byte[] bytes = msg.pack(ByteOrder.LITTLE_ENDIAN); // For testing.
|
||||
assertEquals(expectedHexBytes, HexDump.toHexString(bytes));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateSetLinkDownMessage() {
|
||||
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);
|
||||
assertNotNull(msg);
|
||||
final byte[] bytes = msg.pack(ByteOrder.LITTLE_ENDIAN); // For testing.
|
||||
assertEquals(expectedHexBytes, HexDump.toHexString(bytes));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateSetLinkStateMessage_InvalidInterface() {
|
||||
final String interfaceName = "wlan0";
|
||||
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);
|
||||
assertNull(msg);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToString() {
|
||||
final ByteBuffer byteBuffer = toByteBuffer(RTM_NEWLINK_HEX);
|
||||
|
|
|
|||
Loading…
Reference in a new issue