diff --git a/framework/src/android/net/TestNetworkManager.java b/framework/src/android/net/TestNetworkManager.java index b64299f44a..416c6de51c 100644 --- a/framework/src/android/net/TestNetworkManager.java +++ b/framework/src/android/net/TestNetworkManager.java @@ -260,7 +260,7 @@ public class TestNetworkManager { /** * Create a tap interface with or without carrier for testing purposes. * - * Note: setting carrierUp = false is not supported until kernel version 5.0. + * Note: setting carrierUp = false is not supported until kernel version 6.0. * * @param carrierUp whether the created interface has a carrier or not. * @param bringUp whether to bring up the interface before returning it. @@ -280,6 +280,8 @@ public class TestNetworkManager { /** * Create a tap interface for testing purposes. * + * Note: setting carrierUp = false is not supported until kernel version 6.0. + * * @param carrierUp whether the created interface has a carrier or not. * @param bringUp whether to bring up the interface before returning it. * @param disableIpv6ProvisioningDelay whether to disable DAD and RS delay. diff --git a/service/jni/com_android_server_TestNetworkService.cpp b/service/jni/com_android_server_TestNetworkService.cpp index 7aeecfa967..3e4c4de492 100644 --- a/service/jni/com_android_server_TestNetworkService.cpp +++ b/service/jni/com_android_server_TestNetworkService.cpp @@ -38,9 +38,14 @@ #include "jni.h" #include #include +#include #include #include +#ifndef IFF_NO_CARRIER +#define IFF_NO_CARRIER 0x0040 +#endif + namespace android { //------------------------------------------------------------------------------ @@ -66,17 +71,21 @@ static int createTunTapImpl(JNIEnv* env, bool isTun, bool hasCarrier, bool setIf // Allocate interface. ifr.ifr_flags = (isTun ? IFF_TUN : IFF_TAP) | IFF_NO_PI; + if (!hasCarrier) { + // Using IFF_NO_CARRIER is supported starting in kernel version >= 6.0 + // Up until then, unsupported flags are ignored. + if (!bpf::isAtLeastKernelVersion(6, 0, 0)) { + throwException(env, EOPNOTSUPP, "IFF_NO_CARRIER not supported", ifr.ifr_name); + return -1; + } + ifr.ifr_flags |= IFF_NO_CARRIER; + } strlcpy(ifr.ifr_name, iface, IFNAMSIZ); if (ioctl(tun.get(), TUNSETIFF, &ifr)) { throwException(env, errno, "allocating", ifr.ifr_name); return -1; } - if (!hasCarrier) { - // disable carrier before setting IFF_UP - setTunTapCarrierEnabledImpl(env, iface, tun.get(), hasCarrier); - } - // Mark some TAP interfaces as supporting multicast if (setIffMulticast && !isTun) { base::unique_fd inet6CtrlSock(socket(AF_INET6, SOCK_DGRAM, 0)); diff --git a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt index 67bdd172f6..732a42b60e 100644 --- a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt +++ b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt @@ -392,7 +392,15 @@ class EthernetManagerTest { } // Setting the carrier up / down relies on TUNSETCARRIER which was added in kernel version 5.0. - private fun assumeChangingCarrierSupported() = assumeTrue(isKernelVersionAtLeast("5.0.0")) + private fun assumeChangingCarrierSupported() { + assumeTrue(isKernelVersionAtLeast("5.0.0")) + } + + // Configuring a tap interface without carrier relies on IFF_NO_CARRIER + // which was added in kernel version 6.0. + private fun assumeCreateInterfaceWithoutCarrierSupported() { + assumeTrue(isKernelVersionAtLeast("6.0.0")) + } private fun isAdbOverEthernet(): Boolean { // If no ethernet interface is available, adb is not connected over ethernet. @@ -417,7 +425,7 @@ class EthernetManagerTest { } // WARNING: setting hasCarrier to false requires kernel support. Call - // assumeChangingCarrierSupported() at the top of your test. + // assumeCreateInterfaceWithoutCarrierSupported() at the top of your test. private fun createInterface(hasCarrier: Boolean = true): EthernetTestInterface { val iface = EthernetTestInterface( context, @@ -791,15 +799,13 @@ class EthernetManagerTest { @Test fun testNetworkRequest_forInterfaceWhileTogglingCarrier() { + assumeCreateInterfaceWithoutCarrierSupported() assumeChangingCarrierSupported() val iface = createInterface(false /* hasCarrier */) val cb = requestNetwork(ETH_REQUEST) - // TUNSETCARRIER races with the bring up code, so the network *can* become available despite - // it being "created with no carrier". - // TODO(b/249611919): re-enable assertion once kernel supports IFF_NO_CARRIER. - // cb.assertNeverAvailable() + cb.assertNeverAvailable() iface.setCarrierEnabled(true) cb.expect()