diff --git a/service/native/TrafficController.cpp b/service/native/TrafficController.cpp index 81ddd5a3c2..8320a8a548 100644 --- a/service/native/TrafficController.cpp +++ b/service/native/TrafficController.cpp @@ -697,26 +697,6 @@ void TrafficController::dump(int fd, bool verbose) { dw.println("mConfigurationMap read stats map configure failed with error: %s", configuration.error().message().c_str()); } - dumpBpfMap("mUidOwnerMap", dw, ""); - const auto printUidMatchInfo = [&dw, this](const uint32_t& key, const UidOwnerValue& value, - const BpfMap&) { - if (value.rule & IIF_MATCH) { - auto ifname = mIfaceIndexNameMap.readValue(value.iif); - if (ifname.ok()) { - dw.println("%u %s %s", key, uidMatchTypeToString(value.rule).c_str(), - ifname.value().name); - } else { - dw.println("%u %s %u", key, uidMatchTypeToString(value.rule).c_str(), value.iif); - } - } else { - dw.println("%u %s", key, uidMatchTypeToString(value.rule).c_str()); - } - return base::Result(); - }; - res = mUidOwnerMap.iterateWithValue(printUidMatchInfo); - if (!res.ok()) { - dw.println("mUidOwnerMap print end with error: %s", res.error().message().c_str()); - } } } // namespace net diff --git a/service/native/TrafficControllerTest.cpp b/service/native/TrafficControllerTest.cpp index a9b45381ab..6e45ef3348 100644 --- a/service/native/TrafficControllerTest.cpp +++ b/service/native/TrafficControllerTest.cpp @@ -793,11 +793,6 @@ TEST_F(TrafficControllerTest, TestDumpsys) { "mCookieTagMap:", fmt::format("cookie={} tag={:#x} uid={}", TEST_COOKIE, TEST_TAG, TEST_UID)}; - ASSERT_TRUE(isOk(updateUidOwnerMaps({TEST_UID}, HAPPY_BOX_MATCH, - TrafficController::IptOpInsert))); - expectedLines.emplace_back("mUidOwnerMap:"); - expectedLines.emplace_back(fmt::format("{} HAPPY_BOX_MATCH", TEST_UID)); - EXPECT_TRUE(expectDumpsysContains(expectedLines)); } @@ -815,51 +810,10 @@ TEST_F(TrafficControllerTest, dumpsysInvalidMaps) { fmt::format("mCookieTagMap {}", kErrIterate), fmt::format("mIfaceStatsMap {}", kErrIterate), fmt::format("mConfigurationMap {}", kErrReadRulesConfig), - fmt::format("mConfigurationMap {}", kErrReadStatsMapConfig), - fmt::format("mUidOwnerMap {}", kErrIterate)}; + fmt::format("mConfigurationMap {}", kErrReadStatsMapConfig)}; EXPECT_TRUE(expectDumpsysContains(expectedLines)); } -TEST_F(TrafficControllerTest, uidMatchTypeToString) { - // NO_MATCH(0) can't be verified because match type flag is added by OR operator. - // See TrafficController::addRule() - static const struct TestConfig { - UidOwnerMatchType uidOwnerMatchType; - std::string expected; - } testConfigs[] = { - // clang-format off - {HAPPY_BOX_MATCH, "HAPPY_BOX_MATCH"}, - {DOZABLE_MATCH, "DOZABLE_MATCH"}, - {STANDBY_MATCH, "STANDBY_MATCH"}, - {POWERSAVE_MATCH, "POWERSAVE_MATCH"}, - {HAPPY_BOX_MATCH, "HAPPY_BOX_MATCH"}, - {RESTRICTED_MATCH, "RESTRICTED_MATCH"}, - {LOW_POWER_STANDBY_MATCH, "LOW_POWER_STANDBY_MATCH"}, - {IIF_MATCH, "IIF_MATCH"}, - {LOCKDOWN_VPN_MATCH, "LOCKDOWN_VPN_MATCH"}, - {OEM_DENY_1_MATCH, "OEM_DENY_1_MATCH"}, - {OEM_DENY_2_MATCH, "OEM_DENY_2_MATCH"}, - {OEM_DENY_3_MATCH, "OEM_DENY_3_MATCH"}, - // clang-format on - }; - - for (const auto& config : testConfigs) { - SCOPED_TRACE(fmt::format("testConfig: [{}, {}]", config.uidOwnerMatchType, - config.expected)); - - // Test private function uidMatchTypeToString() via dumpsys. - ASSERT_TRUE(isOk(updateUidOwnerMaps({TEST_UID}, config.uidOwnerMatchType, - TrafficController::IptOpInsert))); - std::vector expectedLines; - expectedLines.emplace_back(fmt::format("{} {}", TEST_UID, config.expected)); - EXPECT_TRUE(expectDumpsysContains(expectedLines)); - - // Clean up the stubs. - ASSERT_TRUE(isOk(updateUidOwnerMaps({TEST_UID}, config.uidOwnerMatchType, - TrafficController::IptOpDelete))); - } -} - TEST_F(TrafficControllerTest, getFirewallType) { static const struct TestConfig { ChildChain childChain; diff --git a/service/src/com/android/server/BpfNetMaps.java b/service/src/com/android/server/BpfNetMaps.java index 0015da26b1..e5714159c6 100644 --- a/service/src/com/android/server/BpfNetMaps.java +++ b/service/src/com/android/server/BpfNetMaps.java @@ -145,6 +145,20 @@ public class BpfNetMaps { Pair.create(PERMISSION_INTERNET, "PERMISSION_INTERNET"), Pair.create(PERMISSION_UPDATE_DEVICE_STATS, "PERMISSION_UPDATE_DEVICE_STATS") ); + private static final List> MATCH_LIST = Arrays.asList( + Pair.create(HAPPY_BOX_MATCH, "HAPPY_BOX_MATCH"), + Pair.create(PENALTY_BOX_MATCH, "PENALTY_BOX_MATCH"), + Pair.create(DOZABLE_MATCH, "DOZABLE_MATCH"), + Pair.create(STANDBY_MATCH, "STANDBY_MATCH"), + Pair.create(POWERSAVE_MATCH, "POWERSAVE_MATCH"), + Pair.create(RESTRICTED_MATCH, "RESTRICTED_MATCH"), + Pair.create(LOW_POWER_STANDBY_MATCH, "LOW_POWER_STANDBY_MATCH"), + Pair.create(IIF_MATCH, "IIF_MATCH"), + Pair.create(LOCKDOWN_VPN_MATCH, "LOCKDOWN_VPN_MATCH"), + Pair.create(OEM_DENY_1_MATCH, "OEM_DENY_1_MATCH"), + Pair.create(OEM_DENY_2_MATCH, "OEM_DENY_2_MATCH"), + Pair.create(OEM_DENY_3_MATCH, "OEM_DENY_3_MATCH") + ); /** * Set sEnableJavaBpfMap for test. @@ -950,6 +964,26 @@ public class BpfNetMaps { return sj.toString(); } + private String matchToString(long matchMask) { + if (matchMask == NO_MATCH) { + return "NO_MATCH"; + } + + final StringJoiner sj = new StringJoiner(" "); + for (Pair match: MATCH_LIST) { + final long matchFlag = match.first; + final String matchName = match.second; + if ((matchMask & matchFlag) != 0) { + sj.add(matchName); + matchMask &= ~matchFlag; + } + } + if (matchMask != 0) { + sj.add("UNKNOWN_MATCH(" + matchMask + ")"); + } + return sj.toString(); + } + /** * Dump BPF maps * @@ -969,6 +1003,15 @@ public class BpfNetMaps { mDeps.nativeDump(fd, verbose); if (verbose) { + BpfDump.dumpMap(sUidOwnerMap, pw, "sUidOwnerMap", + (uid, match) -> { + if ((match.rule & IIF_MATCH) != 0) { + // TODO: convert interface index to interface name by IfaceIndexNameMap + return uid.val + " " + matchToString(match.rule) + " " + match.iif; + } else { + return uid.val + " " + matchToString(match.rule); + } + }); BpfDump.dumpMap(sUidPermissionMap, pw, "sUidPermissionMap", (uid, permission) -> uid.val + " " + permissionToString(permission.val)); } diff --git a/tests/unit/java/com/android/server/BpfNetMapsTest.java b/tests/unit/java/com/android/server/BpfNetMapsTest.java index 7c316074aa..7a2db89d87 100644 --- a/tests/unit/java/com/android/server/BpfNetMapsTest.java +++ b/tests/unit/java/com/android/server/BpfNetMapsTest.java @@ -37,10 +37,15 @@ import static com.android.server.BpfNetMaps.DOZABLE_MATCH; import static com.android.server.BpfNetMaps.HAPPY_BOX_MATCH; import static com.android.server.BpfNetMaps.IIF_MATCH; import static com.android.server.BpfNetMaps.LOCKDOWN_VPN_MATCH; +import static com.android.server.BpfNetMaps.LOW_POWER_STANDBY_MATCH; import static com.android.server.BpfNetMaps.NO_MATCH; +import static com.android.server.BpfNetMaps.OEM_DENY_1_MATCH; +import static com.android.server.BpfNetMaps.OEM_DENY_2_MATCH; +import static com.android.server.BpfNetMaps.OEM_DENY_3_MATCH; import static com.android.server.BpfNetMaps.PENALTY_BOX_MATCH; import static com.android.server.BpfNetMaps.POWERSAVE_MATCH; import static com.android.server.BpfNetMaps.RESTRICTED_MATCH; +import static com.android.server.BpfNetMaps.STANDBY_MATCH; import static com.android.server.ConnectivityStatsLog.NETWORK_BPF_MAP_INFO; import static org.junit.Assert.assertEquals; @@ -963,4 +968,53 @@ public final class BpfNetMapsTest { doTestDumpUidPermissionMap(PERMISSION_INTERNET | 1 << 6, "PERMISSION_INTERNET PERMISSION_UNKNOWN(64)"); } + + void doTestDumpUidOwnerMap(final int iif, final long match, final String matchString) + throws Exception { + mUidOwnerMap.updateEntry(new S32(TEST_UID), new UidOwnerValue(iif, match)); + assertDumpContains(getDump(), TEST_UID + " " + matchString); + } + + void doTestDumpUidOwnerMap(final long match, final String matchString) throws Exception { + doTestDumpUidOwnerMap(0 /* iif */, match, matchString); + } + + @Test + @IgnoreUpTo(Build.VERSION_CODES.S_V2) + public void testDumpUidOwnerMap() throws Exception { + doTestDumpUidOwnerMap(HAPPY_BOX_MATCH, "HAPPY_BOX_MATCH"); + doTestDumpUidOwnerMap(PENALTY_BOX_MATCH, "PENALTY_BOX_MATCH"); + doTestDumpUidOwnerMap(DOZABLE_MATCH, "DOZABLE_MATCH"); + doTestDumpUidOwnerMap(STANDBY_MATCH, "STANDBY_MATCH"); + doTestDumpUidOwnerMap(POWERSAVE_MATCH, "POWERSAVE_MATCH"); + doTestDumpUidOwnerMap(RESTRICTED_MATCH, "RESTRICTED_MATCH"); + doTestDumpUidOwnerMap(LOW_POWER_STANDBY_MATCH, "LOW_POWER_STANDBY_MATCH"); + doTestDumpUidOwnerMap(LOCKDOWN_VPN_MATCH, "LOCKDOWN_VPN_MATCH"); + doTestDumpUidOwnerMap(OEM_DENY_1_MATCH, "OEM_DENY_1_MATCH"); + doTestDumpUidOwnerMap(OEM_DENY_2_MATCH, "OEM_DENY_2_MATCH"); + doTestDumpUidOwnerMap(OEM_DENY_3_MATCH, "OEM_DENY_3_MATCH"); + + doTestDumpUidOwnerMap(HAPPY_BOX_MATCH | POWERSAVE_MATCH, + "HAPPY_BOX_MATCH POWERSAVE_MATCH"); + doTestDumpUidOwnerMap(DOZABLE_MATCH | LOCKDOWN_VPN_MATCH | OEM_DENY_1_MATCH, + "DOZABLE_MATCH LOCKDOWN_VPN_MATCH OEM_DENY_1_MATCH"); + } + + @Test + @IgnoreUpTo(Build.VERSION_CODES.S_V2) + public void testDumpUidOwnerMapWithIifMatch() throws Exception { + doTestDumpUidOwnerMap(TEST_IF_INDEX, IIF_MATCH, "IIF_MATCH " + TEST_IF_INDEX); + doTestDumpUidOwnerMap(TEST_IF_INDEX, + IIF_MATCH | DOZABLE_MATCH | LOCKDOWN_VPN_MATCH | OEM_DENY_1_MATCH, + "DOZABLE_MATCH IIF_MATCH LOCKDOWN_VPN_MATCH OEM_DENY_1_MATCH " + TEST_IF_INDEX); + } + + @Test + @IgnoreUpTo(Build.VERSION_CODES.S_V2) + public void testDumpUidOwnerMapWithInvalidMatch() throws Exception { + final long invalid_match = 1L << 31; + doTestDumpUidOwnerMap(invalid_match, "UNKNOWN_MATCH(" + invalid_match + ")"); + doTestDumpUidOwnerMap(DOZABLE_MATCH | invalid_match, + "DOZABLE_MATCH UNKNOWN_MATCH(" + invalid_match + ")"); + } }