[Thread] avoid kernel-generated lla on thread-wpan
OpenThread generates the link-local address randomly, so the kernel shound't generate another lla again. Bug: 305605130 Change-Id: I0ec79adf0de4edc6921703c3cc50cfcfe63b853b
This commit is contained in:
parent
0aeee52ac1
commit
8658ef364d
5 changed files with 95 additions and 6 deletions
|
|
@ -41,6 +41,10 @@ public class RtNetlinkLinkMessage extends NetlinkMessage {
|
|||
public static final short IFLA_ADDRESS = 1;
|
||||
public static final short IFLA_IFNAME = 3;
|
||||
public static final short IFLA_MTU = 4;
|
||||
public static final short IFLA_INET6_ADDR_GEN_MODE = 8;
|
||||
public static final short IFLA_AF_SPEC = 26;
|
||||
|
||||
public static final short IN6_ADDR_GEN_MODE_NONE = 1;
|
||||
|
||||
private int mMtu;
|
||||
@NonNull
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ public class StructIfinfoMsg extends Struct {
|
|||
@Field(order = 4, type = Type.U32)
|
||||
public final long change;
|
||||
|
||||
StructIfinfoMsg(short family, int type, int index, long flags, long change) {
|
||||
public StructIfinfoMsg(short family, int type, int index, long flags, long change) {
|
||||
this.family = family;
|
||||
this.type = type;
|
||||
this.index = index;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,18 @@
|
|||
|
||||
package com.android.server.thread;
|
||||
|
||||
import static android.system.OsConstants.AF_INET6;
|
||||
import static android.system.OsConstants.EADDRINUSE;
|
||||
import static android.system.OsConstants.IFF_MULTICAST;
|
||||
import static android.system.OsConstants.IFF_NOARP;
|
||||
import static android.system.OsConstants.NETLINK_ROUTE;
|
||||
|
||||
import static com.android.net.module.util.netlink.NetlinkConstants.RTM_NEWLINK;
|
||||
import static com.android.net.module.util.netlink.RtNetlinkLinkMessage.IFLA_AF_SPEC;
|
||||
import static com.android.net.module.util.netlink.RtNetlinkLinkMessage.IFLA_INET6_ADDR_GEN_MODE;
|
||||
import static com.android.net.module.util.netlink.RtNetlinkLinkMessage.IN6_ADDR_GEN_MODE_NONE;
|
||||
import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_ACK;
|
||||
import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REQUEST;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.net.IpPrefix;
|
||||
|
|
@ -29,8 +40,12 @@ import android.system.ErrnoException;
|
|||
import android.system.Os;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.net.module.util.HexDump;
|
||||
import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
|
||||
import com.android.net.module.util.netlink.NetlinkUtils;
|
||||
import com.android.net.module.util.netlink.StructIfinfoMsg;
|
||||
import com.android.net.module.util.netlink.StructNlAttr;
|
||||
import com.android.net.module.util.netlink.StructNlMsgHdr;
|
||||
import com.android.server.thread.openthread.Ipv6AddressInfo;
|
||||
import com.android.server.thread.openthread.OnMeshPrefixConfig;
|
||||
|
||||
|
|
@ -42,12 +57,15 @@ import java.net.MulticastSocket;
|
|||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/** Controller for virtual/tunnel network interfaces. */
|
||||
public class TunInterfaceController {
|
||||
private static final String TAG = "TunIfController";
|
||||
private static final boolean DBG = false;
|
||||
private static final long INFINITE_LIFETIME = 0xffffffffL;
|
||||
static final int MTU = 1280;
|
||||
|
||||
|
|
@ -89,6 +107,8 @@ public class TunInterfaceController {
|
|||
} catch (SocketException e) {
|
||||
throw new IOException("Failed to get NetworkInterface", e);
|
||||
}
|
||||
|
||||
setAddrGenModeToNone();
|
||||
}
|
||||
|
||||
public void destroyTunInterface() {
|
||||
|
|
@ -339,4 +359,66 @@ public class TunInterfaceController {
|
|||
Log.e(TAG, "failed to leave group " + address.getHostAddress(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the address generation mode to {@code IN6_ADDR_GEN_MODE_NONE}.
|
||||
*
|
||||
* <p>So that the "thread-wpan" interface has only one IPv6 link local address which is
|
||||
* generated by OpenThread.
|
||||
*/
|
||||
private void setAddrGenModeToNone() {
|
||||
StructNlMsgHdr header = new StructNlMsgHdr();
|
||||
header.nlmsg_type = RTM_NEWLINK;
|
||||
header.nlmsg_pid = 0;
|
||||
header.nlmsg_seq = 0;
|
||||
header.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
|
||||
StructIfinfoMsg ifInfo =
|
||||
new StructIfinfoMsg(
|
||||
(short) 0 /* family */,
|
||||
0 /* type */,
|
||||
Os.if_nametoindex(mIfName),
|
||||
(IFF_MULTICAST | IFF_NOARP) /* flags */,
|
||||
0xffffffff /* change */);
|
||||
|
||||
// Nested attributes
|
||||
// IFLA_AF_SPEC
|
||||
// AF_INET6
|
||||
// IFLA_INET6_ADDR_GEN_MODE
|
||||
StructNlAttr addrGenMode =
|
||||
new StructNlAttr(IFLA_INET6_ADDR_GEN_MODE, (byte) IN6_ADDR_GEN_MODE_NONE);
|
||||
StructNlAttr afInet6 = new StructNlAttr((short) AF_INET6, addrGenMode);
|
||||
StructNlAttr afSpec = new StructNlAttr(IFLA_AF_SPEC, afInet6);
|
||||
|
||||
final int msgLength =
|
||||
StructNlMsgHdr.STRUCT_SIZE
|
||||
+ StructIfinfoMsg.STRUCT_SIZE
|
||||
+ afSpec.getAlignedLength();
|
||||
byte[] msg = new byte[msgLength];
|
||||
ByteBuffer buf = ByteBuffer.wrap(msg);
|
||||
buf.order(ByteOrder.nativeOrder());
|
||||
|
||||
header.nlmsg_len = msgLength;
|
||||
header.pack(buf);
|
||||
ifInfo.pack(buf);
|
||||
afSpec.pack(buf);
|
||||
|
||||
if (buf.position() != msgLength) {
|
||||
throw new AssertionError(
|
||||
String.format(
|
||||
"Unexpected netlink message size (actual = %d, expected = %d)",
|
||||
buf.position(), msgLength));
|
||||
}
|
||||
|
||||
if (DBG) {
|
||||
Log.d(TAG, "ADDR_GEN_MODE message is:");
|
||||
Log.d(TAG, HexDump.dumpHexString(msg));
|
||||
}
|
||||
|
||||
try {
|
||||
NetlinkUtils.sendOneShotKernelMessage(NETLINK_ROUTE, msg);
|
||||
} catch (ErrnoException e) {
|
||||
Log.e(TAG, "Failed to set ADDR_GEN_MODE to NONE", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ public class ThreadIntegrationTest {
|
|||
|
||||
// TODO (b/323300829): add test for removing an OT address
|
||||
@Test
|
||||
public void tunInterface_joinedNetwork_otAddressesAddedToTunInterface() throws Exception {
|
||||
public void tunInterface_joinedNetwork_otAndTunAddressesMatch() throws Exception {
|
||||
mController.joinAndWait(DEFAULT_DATASET);
|
||||
|
||||
List<Inet6Address> otAddresses = mOtCtl.getAddresses();
|
||||
|
|
@ -185,9 +185,12 @@ public class ThreadIntegrationTest {
|
|||
// that we can write assertThat() in the Predicate
|
||||
waitFor(
|
||||
() -> {
|
||||
String ifconfig = runShellCommand("ifconfig thread-wpan");
|
||||
return otAddresses.stream()
|
||||
.allMatch(addr -> ifconfig.contains(addr.getHostAddress()));
|
||||
List<Inet6Address> tunAddresses =
|
||||
getIpv6LinkAddresses("thread-wpan").stream()
|
||||
.map(linkAddr -> (Inet6Address) linkAddr.getAddress())
|
||||
.toList();
|
||||
return otAddresses.containsAll(tunAddresses)
|
||||
&& tunAddresses.containsAll(otAddresses);
|
||||
},
|
||||
TUN_ADDR_UPDATE_TIMEOUT);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ public final class IntegrationTestUtils {
|
|||
return false;
|
||||
}
|
||||
|
||||
public static List<LinkAddress> getIpv6LinkAddresses(String interfaceName) throws IOException {
|
||||
public static List<LinkAddress> getIpv6LinkAddresses(String interfaceName) {
|
||||
List<LinkAddress> addresses = new ArrayList<>();
|
||||
final String cmd = " ip -6 addr show dev " + interfaceName;
|
||||
final String output = runShellCommandOrThrow(cmd);
|
||||
|
|
|
|||
Loading…
Reference in a new issue