Move Interface index name map dump to NetworkStatsService

Map status dump will do access check if map is null.
This could show different message from the current dump output.

Information in map content dump does not change
$ dumpsys connectivity trafficcontroller
....
     mIfaceIndexNameMap:
      ifaceIndex=5 ifaceName=ip6_vti0
      ifaceIndex=19 ifaceName=r_rmnet_data3
      ifaceIndex=17 ifaceName=r_rmnet_data1
      ifaceIndex=18 ifaceName=r_rmnet_data2
      ifaceIndex=23 ifaceName=wifi-aware0
....

$ dumpsys netstats
....
  BPF map content:
    ifaceIndex=5 ifaceName=ip6_vti0
    ifaceIndex=19 ifaceName=r_rmnet_data3
    ifaceIndex=17 ifaceName=r_rmnet_data1
    ifaceIndex=18 ifaceName=r_rmnet_data2
    ifaceIndex=8 ifaceName=rmnet_ipa0
....

Bug: 217624062
Test: dumpsys netstats, atest
com.android.server.net.BpfInterfaceMapUpdaterTest

Change-Id: If182bd97f72713b6347028668cf7bd4676b8aea4
This commit is contained in:
Motomu Utsumi
2022-08-16 06:41:50 +00:00
parent 608c32c782
commit fdb601603d
5 changed files with 53 additions and 20 deletions

View File

@@ -22,10 +22,12 @@ import android.os.IBinder;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ServiceSpecificException; import android.os.ServiceSpecificException;
import android.system.ErrnoException; import android.system.ErrnoException;
import android.util.IndentingPrintWriter;
import android.util.Log; import android.util.Log;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.net.module.util.BaseNetdUnsolicitedEventListener; import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
import com.android.net.module.util.BpfDump;
import com.android.net.module.util.BpfMap; import com.android.net.module.util.BpfMap;
import com.android.net.module.util.IBpfMap; import com.android.net.module.util.IBpfMap;
import com.android.net.module.util.InterfaceParams; import com.android.net.module.util.InterfaceParams;
@@ -151,4 +153,22 @@ public class BpfInterfaceMapUpdater {
return null; return null;
} }
} }
/**
* Dump BPF map
*
* @param pw print writer
*/
public void dump(final IndentingPrintWriter pw) {
pw.println("BPF map status:");
pw.increaseIndent();
BpfDump.dumpMapStatus(mBpfMap, pw, "IfaceIndexNameMap", IFACE_INDEX_NAME_MAP_PATH);
pw.decreaseIndent();
pw.println("BPF map content:");
pw.increaseIndent();
BpfDump.dumpMap(mBpfMap, pw, "IfaceIndexNameMap",
(key, value) -> "ifaceIndex=" + key.val
+ " ifaceName=" + value.getInterfaceNameString());
pw.decreaseIndent();
}
} }

View File

@@ -2740,6 +2740,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
pw.decreaseIndent(); pw.decreaseIndent();
} }
pw.println();
pw.println("InterfaceMapUpdater:");
pw.increaseIndent();
mInterfaceMapUpdater.dump(pw);
pw.decreaseIndent();
pw.println(); pw.println();
pw.println("BPF map status:"); pw.println("BPF map status:");
pw.increaseIndent(); pw.increaseIndent();

View File

@@ -647,19 +647,6 @@ void TrafficController::dump(int fd, bool verbose) {
dw.println("mCookieTagMap print end with error: %s", res.error().message().c_str()); dw.println("mCookieTagMap print end with error: %s", res.error().message().c_str());
} }
// Print ifaceIndexToNameMap content.
dumpBpfMap("mIfaceIndexNameMap", dw, "");
const auto printIfaceNameInfo = [&dw](const uint32_t& key, const IfaceValue& value,
const BpfMap<uint32_t, IfaceValue>&) {
const char* ifname = value.name;
dw.println("ifaceIndex=%u ifaceName=%s", key, ifname);
return base::Result<void>();
};
res = mIfaceIndexNameMap.iterateWithValue(printIfaceNameInfo);
if (!res.ok()) {
dw.println("mIfaceIndexNameMap print end with error: %s", res.error().message().c_str());
}
// Print ifaceStatsMap content // Print ifaceStatsMap content
std::string ifaceStatsHeader = StringPrintf("ifaceIndex ifaceName rxBytes rxPackets txBytes" std::string ifaceStatsHeader = StringPrintf("ifaceIndex ifaceName rxBytes rxPackets txBytes"
" txPackets"); " txPackets");

View File

@@ -60,7 +60,6 @@ constexpr uid_t TEST_UID3 = 98765;
constexpr uint32_t TEST_TAG = 42; constexpr uint32_t TEST_TAG = 42;
constexpr uint32_t TEST_COUNTERSET = 1; constexpr uint32_t TEST_COUNTERSET = 1;
constexpr int TEST_COOKIE = 1; constexpr int TEST_COOKIE = 1;
constexpr char TEST_IFNAME[] = "test0";
constexpr int TEST_IFINDEX = 999; constexpr int TEST_IFINDEX = 999;
constexpr int RXPACKETS = 1; constexpr int RXPACKETS = 1;
constexpr int RXBYTES = 100; constexpr int RXBYTES = 100;
@@ -794,11 +793,6 @@ TEST_F(TrafficControllerTest, TestDumpsys) {
"mCookieTagMap:", "mCookieTagMap:",
fmt::format("cookie={} tag={:#x} uid={}", TEST_COOKIE, TEST_TAG, TEST_UID)}; fmt::format("cookie={} tag={:#x} uid={}", TEST_COOKIE, TEST_TAG, TEST_UID)};
populateFakeIfaceIndexName(TEST_IFNAME, TEST_IFINDEX);
expectedLines.emplace_back("mIfaceIndexNameMap:");
expectedLines.emplace_back(fmt::format("ifaceIndex={} ifaceName={}",
TEST_IFINDEX, TEST_IFNAME));
ASSERT_TRUE(isOk(updateUidOwnerMaps({TEST_UID}, HAPPY_BOX_MATCH, ASSERT_TRUE(isOk(updateUidOwnerMaps({TEST_UID}, HAPPY_BOX_MATCH,
TrafficController::IptOpInsert))); TrafficController::IptOpInsert)));
expectedLines.emplace_back("mUidOwnerMap:"); expectedLines.emplace_back("mUidOwnerMap:");
@@ -824,7 +818,6 @@ TEST_F(TrafficControllerTest, dumpsysInvalidMaps) {
std::vector<std::string> expectedLines = { std::vector<std::string> expectedLines = {
fmt::format("mCookieTagMap {}", kErrIterate), fmt::format("mCookieTagMap {}", kErrIterate),
fmt::format("mIfaceIndexNameMap {}", kErrIterate),
fmt::format("mIfaceStatsMap {}", kErrIterate), fmt::format("mIfaceStatsMap {}", kErrIterate),
fmt::format("mConfigurationMap {}", kErrReadRulesConfig), fmt::format("mConfigurationMap {}", kErrReadRulesConfig),
fmt::format("mConfigurationMap {}", kErrReadStatsMapConfig), fmt::format("mConfigurationMap {}", kErrReadStatsMapConfig),

View File

@@ -20,6 +20,7 @@ import static android.system.OsConstants.EPERM;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.eq; import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
@@ -34,6 +35,7 @@ import android.os.Build;
import android.os.Handler; import android.os.Handler;
import android.os.test.TestLooper; import android.os.test.TestLooper;
import android.system.ErrnoException; import android.system.ErrnoException;
import android.util.IndentingPrintWriter;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
@@ -52,6 +54,9 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import java.io.PrintWriter;
import java.io.StringWriter;
@SmallTest @SmallTest
@RunWith(DevSdkIgnoreRunner.class) @RunWith(DevSdkIgnoreRunner.class)
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2) @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
@@ -144,4 +149,26 @@ public final class BpfInterfaceMapUpdaterTest {
doThrow(new ErrnoException("", EPERM)).when(mBpfMap).getValue(new U32(TEST_INDEX)); doThrow(new ErrnoException("", EPERM)).when(mBpfMap).getValue(new U32(TEST_INDEX));
assertNull(mUpdater.getIfNameByIndex(TEST_INDEX)); assertNull(mUpdater.getIfNameByIndex(TEST_INDEX));
} }
private void assertDumpContains(final String dump, final String message) {
assertTrue(String.format("dump(%s) does not contain '%s'", dump, message),
dump.contains(message));
}
private String getDump() {
final StringWriter sw = new StringWriter();
mUpdater.dump(new IndentingPrintWriter(new PrintWriter(sw), " "));
return sw.toString();
}
@Test
public void testDump() throws ErrnoException {
mBpfMap.updateEntry(new U32(TEST_INDEX), new InterfaceMapValue(TEST_INTERFACE_NAME));
mBpfMap.updateEntry(new U32(TEST_INDEX2), new InterfaceMapValue(TEST_INTERFACE_NAME2));
final String dump = getDump();
assertDumpContains(dump, "IfaceIndexNameMap: OK");
assertDumpContains(dump, "ifaceIndex=1 ifaceName=test1");
assertDumpContains(dump, "ifaceIndex=2 ifaceName=test2");
}
} }