Merge changes I95352711,I27bdb5d8,I7e1acc65,I7c95ff19
* changes:
BpfCoordinator: dump IPv6 BPF downstream rules
BpfCoordinator: change function name and format for dumping IPv6 rules
add header on ipv6 forwarding rulesdump
add header on ipv6 upstream bpf map dump
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index 75f63c8..5191bb7 100644
--- a/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -1975,6 +1975,10 @@
return;
}
+ if (arg1 == UpstreamNetworkMonitor.NOTIFY_TEST_NETWORK_AVAILABLE) {
+ chooseUpstreamType(false);
+ }
+
if (ns == null || !pertainsToCurrentUpstream(ns)) {
// TODO: In future, this is where upstream evaluation and selection
// could be handled for notifications which include sufficient data.
diff --git a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
index 16c031b..15df0c6 100644
--- a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
+++ b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
@@ -85,11 +85,12 @@
private static final boolean DBG = false;
private static final boolean VDBG = false;
- public static final int EVENT_ON_CAPABILITIES = 1;
- public static final int EVENT_ON_LINKPROPERTIES = 2;
- public static final int EVENT_ON_LOST = 3;
- public static final int EVENT_DEFAULT_SWITCHED = 4;
- public static final int NOTIFY_LOCAL_PREFIXES = 10;
+ public static final int EVENT_ON_CAPABILITIES = 1;
+ public static final int EVENT_ON_LINKPROPERTIES = 2;
+ public static final int EVENT_ON_LOST = 3;
+ public static final int EVENT_DEFAULT_SWITCHED = 4;
+ public static final int NOTIFY_LOCAL_PREFIXES = 10;
+ public static final int NOTIFY_TEST_NETWORK_AVAILABLE = 11;
// This value is used by deprecated preferredUpstreamIfaceTypes selection which is default
// disabled.
@VisibleForTesting
@@ -467,6 +468,17 @@
notifyTarget(EVENT_DEFAULT_SWITCHED, ns);
}
+ private void maybeHandleTestNetwork(@NonNull Network network) {
+ if (!mPreferTestNetworks) return;
+
+ final UpstreamNetworkState ns = mNetworkMap.get(network);
+ if (network.equals(mTetheringUpstreamNetwork) || !isTestNetwork(ns)) return;
+
+ // Test network is available. Notify tethering.
+ Log.d(TAG, "Handle test network: " + network);
+ notifyTarget(NOTIFY_TEST_NETWORK_AVAILABLE, ns);
+ }
+
private void recomputeLocalPrefixes() {
final HashSet<IpPrefix> localPrefixes = allLocalPrefixes(mNetworkMap.values());
if (!mLocalPrefixes.equals(localPrefixes)) {
@@ -549,6 +561,12 @@
// So it's not useful to do this work for non-LISTEN_ALL callbacks.
if (mCallbackType == CALLBACK_LISTEN_ALL) {
recomputeLocalPrefixes();
+
+ // When the LISTEN_ALL network callback calls onLinkPropertiesChanged, it means that
+ // all the network information for the network is known (because
+ // onLinkPropertiesChanged is called after onAvailable and onCapabilitiesChanged).
+ // Inform tethering that the test network might have changed.
+ maybeHandleTestNetwork(network);
}
}
diff --git a/Tethering/tests/integration/AndroidManifest.xml b/Tethering/tests/integration/AndroidManifest.xml
index c89c556..9303d0a 100644
--- a/Tethering/tests/integration/AndroidManifest.xml
+++ b/Tethering/tests/integration/AndroidManifest.xml
@@ -16,12 +16,13 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.networkstack.tethering.tests.integration">
- <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!-- The test need CHANGE_NETWORK_STATE permission to use requestNetwork API to setup test
network. Since R shell application don't have such permission, grant permission to the test
here. TODO: Remove CHANGE_NETWORK_STATE permission here and use adopt shell perssion to
obtain CHANGE_NETWORK_STATE for testing once R device is no longer supported. -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
+ <uses-permission android:name="android.permission.INTERNET"/>
<application android:debuggable="true">
<uses-library android:name="android.test.runner" />
diff --git a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
index 06586e2..c9b3686 100644
--- a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
+++ b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
@@ -16,8 +16,6 @@
package android.net;
-import static android.Manifest.permission.ACCESS_NETWORK_STATE;
-import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
import static android.Manifest.permission.DUMP;
import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
import static android.Manifest.permission.NETWORK_SETTINGS;
@@ -42,6 +40,7 @@
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT;
import static com.android.testutils.DeviceInfoUtils.KVersion;
import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork;
+import static com.android.testutils.TestPermissionUtil.runAsShell;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -129,6 +128,10 @@
private static final String TAG = EthernetTetheringTest.class.getSimpleName();
private static final int TIMEOUT_MS = 5000;
+ // Used to check if any tethering interface is available. Choose 200ms to be request timeout
+ // because the average interface requested time on cuttlefish@acloud is around 10ms.
+ // See TetheredInterfaceRequester.getInterface, isInterfaceForTetheringAvailable.
+ private static final int AVAILABLE_TETHER_IFACE_REQUEST_TIMEOUT_MS = 200;
private static final int TETHER_REACHABILITY_ATTEMPTS = 20;
private static final int DUMP_POLLING_MAX_RETRY = 100;
private static final int DUMP_POLLING_INTERVAL_MS = 50;
@@ -186,30 +189,25 @@
@Before
public void setUp() throws Exception {
- // Needed to create a TestNetworkInterface, to call requestTetheredInterface, and to receive
- // tethered client callbacks. The restricted networks permission is needed to ensure that
- // EthernetManager#isAvailable will correctly return true on devices where Ethernet is
- // marked restricted, like cuttlefish. The dump permission is needed to verify bpf related
- // functions via dumpsys output.
- mUiAutomation.adoptShellPermissionIdentity(
- MANAGE_TEST_NETWORKS, NETWORK_SETTINGS, TETHER_PRIVILEGED, ACCESS_NETWORK_STATE,
- CONNECTIVITY_USE_RESTRICTED_NETWORKS, DUMP);
mHandlerThread = new HandlerThread(getClass().getSimpleName());
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
- mRunTests = isEthernetTetheringSupported();
+ mRunTests = runAsShell(NETWORK_SETTINGS, TETHER_PRIVILEGED, () ->
+ mTm.isTetheringSupported());
assumeTrue(mRunTests);
mTetheredInterfaceRequester = new TetheredInterfaceRequester(mHandler, mEm);
}
private void cleanUp() throws Exception {
- mTm.setPreferTestNetworks(false);
+ setPreferTestNetworks(false);
if (mUpstreamTracker != null) {
- mUpstreamTracker.teardown();
- mUpstreamTracker = null;
+ runAsShell(MANAGE_TEST_NETWORKS, () -> {
+ mUpstreamTracker.teardown();
+ mUpstreamTracker = null;
+ });
}
if (mUpstreamReader != null) {
TapPacketReader reader = mUpstreamReader;
@@ -217,19 +215,25 @@
mUpstreamReader = null;
}
- mTm.stopTethering(TETHERING_ETHERNET);
- if (mTetheringEventCallback != null) {
- mTetheringEventCallback.awaitInterfaceUntethered();
- mTetheringEventCallback.unregister();
- mTetheringEventCallback = null;
- }
+ runAsShell(TETHER_PRIVILEGED, () -> {
+ mTm.stopTethering(TETHERING_ETHERNET);
+ // Binder call is an async call. Need to hold the shell permission until tethering
+ // stopped. This helps to avoid the test become flaky.
+ if (mTetheringEventCallback != null) {
+ mTetheringEventCallback.awaitInterfaceUntethered();
+ mTetheringEventCallback.unregister();
+ mTetheringEventCallback = null;
+ }
+ });
if (mDownstreamReader != null) {
TapPacketReader reader = mDownstreamReader;
mHandler.post(() -> reader.stop());
mDownstreamReader = null;
}
- mTetheredInterfaceRequester.release();
- mEm.setIncludeTestInterfaces(false);
+ runAsShell(NETWORK_SETTINGS, () -> {
+ mTetheredInterfaceRequester.release();
+ });
+ setIncludeTestInterfaces(false);
maybeDeleteTestInterface();
}
@@ -243,10 +247,44 @@
}
}
+ private boolean isInterfaceForTetheringAvailable() throws Exception {
+ // If previous test case doesn't release tethering interface successfully, the other tests
+ // after that test may be skipped as unexcepted.
+ // TODO: figure out a better way to check default tethering interface existenion.
+ final TetheredInterfaceRequester requester = new TetheredInterfaceRequester(mHandler, mEm);
+ try {
+ // Use short timeout (200ms) for requesting an existing interface, if any, because
+ // it should reurn faster than requesting a new tethering interface. Using default
+ // timeout (5000ms, TIMEOUT_MS) may make that total testing time is over 1 minute
+ // test module timeout on internal testing.
+ // TODO: if this becomes flaky, consider using default timeout (5000ms) and moving
+ // this check into #setUpOnce.
+ return requester.getInterface(AVAILABLE_TETHER_IFACE_REQUEST_TIMEOUT_MS) != null;
+ } catch (TimeoutException e) {
+ return false;
+ } finally {
+ runAsShell(NETWORK_SETTINGS, () -> {
+ requester.release();
+ });
+ }
+ }
+
+ private void setIncludeTestInterfaces(boolean include) {
+ runAsShell(NETWORK_SETTINGS, () -> {
+ mEm.setIncludeTestInterfaces(include);
+ });
+ }
+
+ private void setPreferTestNetworks(boolean prefer) {
+ runAsShell(NETWORK_SETTINGS, () -> {
+ mTm.setPreferTestNetworks(prefer);
+ });
+ }
+
@Test
public void testVirtualEthernetAlreadyExists() throws Exception {
// This test requires manipulating packets. Skip if there is a physical Ethernet connected.
- assumeFalse(mEm.isAvailable());
+ assumeFalse(isInterfaceForTetheringAvailable());
mDownstreamIface = createTestInterface();
// This must be done now because as soon as setIncludeTestInterfaces(true) is called, the
@@ -256,7 +294,7 @@
int mtu = getMTU(mDownstreamIface);
Log.d(TAG, "Including test interfaces");
- mEm.setIncludeTestInterfaces(true);
+ setIncludeTestInterfaces(true);
final String iface = mTetheredInterfaceRequester.getInterface();
assertEquals("TetheredInterfaceCallback for unexpected interface",
@@ -268,11 +306,11 @@
@Test
public void testVirtualEthernet() throws Exception {
// This test requires manipulating packets. Skip if there is a physical Ethernet connected.
- assumeFalse(mEm.isAvailable());
+ assumeFalse(isInterfaceForTetheringAvailable());
CompletableFuture<String> futureIface = mTetheredInterfaceRequester.requestInterface();
- mEm.setIncludeTestInterfaces(true);
+ setIncludeTestInterfaces(true);
mDownstreamIface = createTestInterface();
@@ -285,9 +323,9 @@
@Test
public void testStaticIpv4() throws Exception {
- assumeFalse(mEm.isAvailable());
+ assumeFalse(isInterfaceForTetheringAvailable());
- mEm.setIncludeTestInterfaces(true);
+ setIncludeTestInterfaces(true);
mDownstreamIface = createTestInterface();
@@ -363,9 +401,9 @@
@Test
public void testLocalOnlyTethering() throws Exception {
- assumeFalse(mEm.isAvailable());
+ assumeFalse(isInterfaceForTetheringAvailable());
- mEm.setIncludeTestInterfaces(true);
+ setIncludeTestInterfaces(true);
mDownstreamIface = createTestInterface();
@@ -397,7 +435,7 @@
@Test
public void testPhysicalEthernet() throws Exception {
- assumeTrue(mEm.isAvailable());
+ assumeTrue(isInterfaceForTetheringAvailable());
// Do not run this test if adb is over network and ethernet is connected.
// It is likely the adb run over ethernet, the adb would break when ethernet is switching
// from client mode to server mode. See b/160389275.
@@ -438,6 +476,7 @@
private final CountDownLatch mLocalOnlyStoppedLatch = new CountDownLatch(1);
private final CountDownLatch mClientConnectedLatch = new CountDownLatch(1);
private final CountDownLatch mUpstreamLatch = new CountDownLatch(1);
+ private final CountDownLatch mCallbackRegisteredLatch = new CountDownLatch(1);
private final TetheringInterface mIface;
private final Network mExpectedUpstream;
@@ -516,6 +555,22 @@
mLocalOnlyStartedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
}
+ // Used to check if the callback has registered. When the callback is registered,
+ // onSupportedTetheringTypes is celled in onCallbackStarted(). After
+ // onSupportedTetheringTypes called, drop the permission for registering callback.
+ // See MyTetheringEventCallback#register, TetheringManager#onCallbackStarted.
+ @Override
+ public void onSupportedTetheringTypes(Set<Integer> supportedTypes) {
+ // Used to check callback registered.
+ mCallbackRegisteredLatch.countDown();
+ }
+
+ public void awaitCallbackRegistered() throws Exception {
+ if (!mCallbackRegisteredLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+ fail("Did not receive callback registered signal after " + TIMEOUT_MS + "ms");
+ }
+ }
+
public void awaitInterfaceUntethered() throws Exception {
// Don't block teardown if the interface was never tethered.
// This is racy because the interface might become tethered right after this check, but
@@ -591,16 +646,34 @@
} else {
callback = new MyTetheringEventCallback(mTm, iface);
}
- mTm.registerTetheringEventCallback(mHandler::post, callback);
-
+ runAsShell(NETWORK_SETTINGS, () -> {
+ mTm.registerTetheringEventCallback(mHandler::post, callback);
+ // Need to hold the shell permission until callback is registered. This helps to avoid
+ // the test become flaky.
+ callback.awaitCallbackRegistered();
+ });
+ final CountDownLatch tetheringStartedLatch = new CountDownLatch(1);
StartTetheringCallback startTetheringCallback = new StartTetheringCallback() {
@Override
+ public void onTetheringStarted() {
+ Log.d(TAG, "Ethernet tethering started");
+ tetheringStartedLatch.countDown();
+ }
+
+ @Override
public void onTetheringFailed(int resultCode) {
fail("Unexpectedly got onTetheringFailed");
}
};
Log.d(TAG, "Starting Ethernet tethering");
- mTm.startTethering(request, mHandler::post /* executor */, startTetheringCallback);
+ runAsShell(TETHER_PRIVILEGED, () -> {
+ mTm.startTethering(request, mHandler::post /* executor */, startTetheringCallback);
+ // Binder call is an async call. Need to hold the shell permission until tethering
+ // started. This helps to avoid the test become flaky.
+ if (!tetheringStartedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+ fail("Did not receive tethering started callback after " + TIMEOUT_MS + "ms");
+ }
+ });
final int connectivityType = request.getConnectivityScope();
switch (connectivityType) {
@@ -708,12 +781,17 @@
public CompletableFuture<String> requestInterface() {
assertNull("BUG: more than one tethered interface request", mRequest);
Log.d(TAG, "Requesting tethered interface");
- mRequest = mEm.requestTetheredInterface(mHandler::post, this);
+ mRequest = runAsShell(NETWORK_SETTINGS, () ->
+ mEm.requestTetheredInterface(mHandler::post, this));
return mFuture;
}
+ public String getInterface(int timeout) throws Exception {
+ return requestInterface().get(timeout, TimeUnit.MILLISECONDS);
+ }
+
public String getInterface() throws Exception {
- return requestInterface().get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ return getInterface(TIMEOUT_MS);
}
public void release() {
@@ -764,8 +842,10 @@
}
private TestNetworkInterface createTestInterface() throws Exception {
- TestNetworkManager tnm = mContext.getSystemService(TestNetworkManager.class);
- TestNetworkInterface iface = tnm.createTapInterface();
+ TestNetworkManager tnm = runAsShell(MANAGE_TEST_NETWORKS, () ->
+ mContext.getSystemService(TestNetworkManager.class));
+ TestNetworkInterface iface = runAsShell(MANAGE_TEST_NETWORKS, () ->
+ tnm.createTapInterface());
Log.d(TAG, "Created test interface " + iface.getInterfaceName());
return iface;
}
@@ -780,14 +860,14 @@
private TestNetworkTracker createTestUpstream(final List<LinkAddress> addresses,
final List<InetAddress> dnses) throws Exception {
- mTm.setPreferTestNetworks(true);
+ setPreferTestNetworks(true);
final LinkProperties lp = new LinkProperties();
lp.setLinkAddresses(addresses);
lp.setDnsServers(dnses);
lp.setNat64Prefix(TEST_NAT64PREFIX);
- return initTestNetwork(mContext, lp, TIMEOUT_MS);
+ return runAsShell(MANAGE_TEST_NETWORKS, () -> initTestNetwork(mContext, lp, TIMEOUT_MS));
}
@Test
@@ -1091,7 +1171,7 @@
private TetheringTester initTetheringTester(List<LinkAddress> upstreamAddresses,
List<InetAddress> upstreamDnses) throws Exception {
- assumeFalse(mEm.isAvailable());
+ assumeFalse(isInterfaceForTetheringAvailable());
// MyTetheringEventCallback currently only support await first available upstream. Tethering
// may select internet network as upstream if test network is not available and not be
@@ -1099,7 +1179,7 @@
mUpstreamTracker = createTestUpstream(upstreamAddresses, upstreamDnses);
mDownstreamIface = createTestInterface();
- mEm.setIncludeTestInterfaces(true);
+ setIncludeTestInterfaces(true);
// Make sure EtherentTracker use "mDownstreamIface" as server mode interface.
assertEquals("TetheredInterfaceCallback for unexpected interface",
@@ -1224,7 +1304,8 @@
Class<K> keyClass, Class<V> valueClass, @NonNull String mapArg)
throws Exception {
final String[] args = new String[] {DUMPSYS_TETHERING_RAWMAP_ARG, mapArg};
- final String rawMapStr = DumpTestUtils.dumpService(Context.TETHERING_SERVICE, args);
+ final String rawMapStr = runAsShell(DUMP, () ->
+ DumpTestUtils.dumpService(Context.TETHERING_SERVICE, args));
final HashMap<K, V> map = new HashMap<>();
for (final String line : rawMapStr.split(LINE_DELIMITER)) {
@@ -1250,7 +1331,8 @@
}
private boolean isTetherConfigBpfOffloadEnabled() throws Exception {
- final String dumpStr = DumpTestUtils.dumpService(Context.TETHERING_SERVICE, "--short");
+ final String dumpStr = runAsShell(DUMP, () ->
+ DumpTestUtils.dumpService(Context.TETHERING_SERVICE, "--short"));
// BPF offload tether config can be overridden by "config_tether_enable_bpf_offload" in
// packages/modules/Connectivity/Tethering/res/values/config.xml. OEM may disable config by
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TestConnectivityManager.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TestConnectivityManager.java
index b2cbf75..e0d77ee 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TestConnectivityManager.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TestConnectivityManager.java
@@ -19,6 +19,7 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_TEST;
import static com.android.networkstack.apishim.common.ShimUtils.isAtLeastS;
@@ -329,6 +330,28 @@
this.legacyType = toLegacyType(networkCapabilities);
}
+ // Used for test network only because ConnectivityManager.networkCapabilitiesForType
+ // doesn't support "TRANSPORT_TEST -> TYPE_TEST" in #matchesLegacyType. Beware of
+ // satisfiedByNetworkCapabilities doesn't check on new |networkCapabilities| as
+ // #matchesLegacyType.
+ // TODO: refactor when tethering no longer uses CONNECTIVITY_ACTION.
+ private TestNetworkAgent(TestConnectivityManager cm) {
+ this.cm = cm;
+ networkId = new Network(cm.getNetworkId());
+ networkCapabilities = new NetworkCapabilities.Builder()
+ .addTransportType(TRANSPORT_TEST)
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .build();
+ linkProperties = new LinkProperties();
+ legacyType = TYPE_TEST;
+ }
+
+ // TODO: refactor when tethering no longer uses CONNECTIVITY_ACTION.
+ public static TestNetworkAgent buildTestNetworkAgentForTestNetwork(
+ TestConnectivityManager cm) {
+ return new TestNetworkAgent(cm);
+ }
+
private static int toLegacyType(NetworkCapabilities nc) {
for (int type = 0; type < ConnectivityManager.TYPE_TEST; type++) {
if (matchesLegacyType(nc, type)) return type;
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java
index 9b9507b..b0cb7f2 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java
@@ -449,6 +449,36 @@
}
@Test
+ public void testGetCurrentPreferredUpstream_TestNetworkPreferred() throws Exception {
+ mUNM.startTrackDefaultNetwork(mEntitleMgr);
+ mUNM.startObserveAllNetworks();
+ mUNM.setUpstreamConfig(true /* autoUpstream */, false /* dunRequired */);
+ mUNM.setTryCell(true);
+ mUNM.setPreferTestNetworks(true);
+
+ // [1] Mobile connects, DUN not required -> mobile selected.
+ final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, CELL_CAPABILITIES);
+ cellAgent.fakeConnect();
+ mCM.makeDefaultNetwork(cellAgent);
+ mLooper.dispatchAll();
+ assertEquals(cellAgent.networkId, mUNM.getCurrentPreferredUpstream().network);
+ assertEquals(0, mCM.mRequested.size());
+
+ // [2] Test network connects -> test network selected.
+ final TestNetworkAgent testAgent =
+ TestNetworkAgent.buildTestNetworkAgentForTestNetwork(mCM);
+ testAgent.fakeConnect();
+ mLooper.dispatchAll();
+ assertEquals(testAgent.networkId, mUNM.getCurrentPreferredUpstream().network);
+ assertEquals(0, mCM.mRequested.size());
+
+ // [3] Disable test networks preferred -> mobile selected.
+ mUNM.setPreferTestNetworks(false);
+ assertEquals(cellAgent.networkId, mUNM.getCurrentPreferredUpstream().network);
+ assertEquals(0, mCM.mRequested.size());
+ }
+
+ @Test
public void testLocalPrefixes() throws Exception {
mUNM.startTrackDefaultNetwork(mEntitleMgr);
mUNM.startObserveAllNetworks();
diff --git a/netd/BpfHandler.cpp b/netd/BpfHandler.cpp
index 2810d80..994db1d 100644
--- a/netd/BpfHandler.cpp
+++ b/netd/BpfHandler.cpp
@@ -134,18 +134,16 @@
int BpfHandler::tagSocket(int sockFd, uint32_t tag, uid_t chargeUid, uid_t realUid) {
std::lock_guard guard(mMutex);
- if (chargeUid != realUid && !hasUpdateDeviceStatsPermission(realUid)) {
- return -EPERM;
- }
+ if (!mCookieTagMap.isValid()) return -EPERM;
+
+ if (chargeUid != realUid && !hasUpdateDeviceStatsPermission(realUid)) return -EPERM;
// Note that tagging the socket to AID_CLAT is only implemented in JNI ClatCoordinator.
// The process is not allowed to tag socket to AID_CLAT via tagSocket() which would cause
// process data usage accounting to be bypassed. Tagging AID_CLAT is used for avoiding counting
// CLAT traffic data usage twice. See packages/modules/Connectivity/service/jni/
// com_android_server_connectivity_ClatCoordinator.cpp
- if (chargeUid == AID_CLAT) {
- return -EPERM;
- }
+ if (chargeUid == AID_CLAT) return -EPERM;
// The socket destroy listener only monitors on the group {INET_TCP, INET_UDP, INET6_TCP,
// INET6_UDP}. Tagging listener unsupported socket causes that the tag can't be removed from
@@ -180,6 +178,7 @@
uint64_t sock_cookie = getSocketCookie(sockFd);
if (sock_cookie == NONEXISTENT_COOKIE) return -errno;
+
UidTagValue newKey = {.uid = (uint32_t)chargeUid, .tag = tag};
uint32_t totalEntryCount = 0;
@@ -242,9 +241,11 @@
int BpfHandler::untagSocket(int sockFd) {
std::lock_guard guard(mMutex);
- uint64_t sock_cookie = getSocketCookie(sockFd);
+ uint64_t sock_cookie = getSocketCookie(sockFd);
if (sock_cookie == NONEXISTENT_COOKIE) return -errno;
+
+ if (!mCookieTagMap.isValid()) return -EPERM;
base::Result<void> res = mCookieTagMap.deleteValue(sock_cookie);
if (!res.ok()) {
ALOGE("Failed to untag socket: %s", strerror(res.error().code()));
diff --git a/netd/NetdUpdatable.cpp b/netd/NetdUpdatable.cpp
index f0997fc..41b1fdb 100644
--- a/netd/NetdUpdatable.cpp
+++ b/netd/NetdUpdatable.cpp
@@ -16,19 +16,20 @@
#define LOG_TAG "NetdUpdatable"
-#include "NetdUpdatable.h"
+#include "BpfHandler.h"
#include <android-base/logging.h>
#include <netdutils/Status.h>
#include "NetdUpdatablePublic.h"
+static android::net::BpfHandler sBpfHandler;
+
int libnetd_updatable_init(const char* cg2_path) {
android::base::InitLogging(/*argv=*/nullptr);
LOG(INFO) << __func__ << ": Initializing";
- android::net::gNetdUpdatable = android::net::NetdUpdatable::getInstance();
- android::netdutils::Status ret = android::net::gNetdUpdatable->mBpfHandler.init(cg2_path);
+ android::netdutils::Status ret = sBpfHandler.init(cg2_path);
if (!android::netdutils::isOk(ret)) {
LOG(ERROR) << __func__ << ": BPF handler init failed";
return -ret.code();
@@ -37,25 +38,9 @@
}
int libnetd_updatable_tagSocket(int sockFd, uint32_t tag, uid_t chargeUid, uid_t realUid) {
- if (android::net::gNetdUpdatable == nullptr) return -EPERM;
- return android::net::gNetdUpdatable->mBpfHandler.tagSocket(sockFd, tag, chargeUid, realUid);
+ return sBpfHandler.tagSocket(sockFd, tag, chargeUid, realUid);
}
int libnetd_updatable_untagSocket(int sockFd) {
- if (android::net::gNetdUpdatable == nullptr) return -EPERM;
- return android::net::gNetdUpdatable->mBpfHandler.untagSocket(sockFd);
+ return sBpfHandler.untagSocket(sockFd);
}
-
-namespace android {
-namespace net {
-
-NetdUpdatable* gNetdUpdatable = nullptr;
-
-NetdUpdatable* NetdUpdatable::getInstance() {
- // Instantiated on first use.
- static NetdUpdatable instance;
- return &instance;
-}
-
-} // namespace net
-} // namespace android
diff --git a/netd/NetdUpdatable.h b/netd/NetdUpdatable.h
deleted file mode 100644
index 333037f..0000000
--- a/netd/NetdUpdatable.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * Copyright (c) 2022, 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.
- */
-
-#pragma once
-
-#include "BpfHandler.h"
-
-namespace android {
-namespace net {
-
-class NetdUpdatable {
- public:
- NetdUpdatable() = default;
- NetdUpdatable(const NetdUpdatable&) = delete;
- NetdUpdatable& operator=(const NetdUpdatable&) = delete;
- static NetdUpdatable* getInstance();
-
- BpfHandler mBpfHandler;
-};
-
-extern NetdUpdatable* gNetdUpdatable;
-
-} // namespace net
-} // namespace android
\ No newline at end of file
diff --git a/service/src/com/android/server/connectivity/ClatCoordinator.java b/service/src/com/android/server/connectivity/ClatCoordinator.java
index 6c4a021..e1c7b64 100644
--- a/service/src/com/android/server/connectivity/ClatCoordinator.java
+++ b/service/src/com/android/server/connectivity/ClatCoordinator.java
@@ -17,6 +17,7 @@
package com.android.server.connectivity;
import static android.net.INetd.IF_STATE_UP;
+import static android.net.INetd.PERMISSION_NETWORK;
import static android.net.INetd.PERMISSION_SYSTEM;
import static android.system.OsConstants.ETH_P_IP;
import static android.system.OsConstants.ETH_P_IPV6;
@@ -386,9 +387,9 @@
static int getFwmark(int netId) {
// See union Fwmark in system/netd/include/Fwmark.h
return (netId & 0xffff)
- | 0x1 << 16 // protectedFromVpn: true
- | 0x1 << 17 // explicitlySelected: true
- | (PERMISSION_SYSTEM & 0x3) << 18;
+ | 0x1 << 16 // explicitlySelected: true
+ | 0x1 << 17 // protectedFromVpn: true
+ | ((PERMISSION_NETWORK | PERMISSION_SYSTEM) & 0x3) << 18; // 2 permission bits = 3
}
@VisibleForTesting
diff --git a/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java b/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java
index bbb61cd..7646c19 100644
--- a/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java
+++ b/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java
@@ -94,10 +94,10 @@
private static final int GOOGLE_DNS_4 = 0x08080808; // 8.8.8.8
private static final int NETID = 42;
- // The test fwmark means: PERMISSION_SYSTEM (0x2), protectedFromVpn: true,
+ // The test fwmark means: PERMISSION_NETWORK | PERMISSION_SYSTEM (0x3), protectedFromVpn: true,
// explicitlySelected: true, netid: 42. For bit field structure definition, see union Fwmark in
// system/netd/include/Fwmark.h
- private static final int MARK = 0xb002a;
+ private static final int MARK = 0xf002a;
private static final String XLAT_LOCAL_IPV4ADDR_STRING = "192.0.0.46";
private static final String XLAT_LOCAL_IPV6ADDR_STRING = "2001:db8:0:b11::464";
@@ -493,10 +493,10 @@
@Test
public void testGetFwmark() throws Exception {
- assertEquals(0xb0064, ClatCoordinator.getFwmark(100));
- assertEquals(0xb03e8, ClatCoordinator.getFwmark(1000));
- assertEquals(0xb2710, ClatCoordinator.getFwmark(10000));
- assertEquals(0xbffff, ClatCoordinator.getFwmark(65535));
+ assertEquals(0xf0064, ClatCoordinator.getFwmark(100));
+ assertEquals(0xf03e8, ClatCoordinator.getFwmark(1000));
+ assertEquals(0xf2710, ClatCoordinator.getFwmark(10000));
+ assertEquals(0xfffff, ClatCoordinator.getFwmark(65535));
}
@Test