Merge changes from topic "dump_map_status"

* changes:
  Move Interface index name map dump to NetworkStatsService
  Move stats map A/B dump to NetworkStatsService
  Add BpfInterfaceMapUpdater#getIfNameByIndex
This commit is contained in:
Motomu Utsumi
2022-09-14 01:27:49 +00:00
committed by Gerrit Code Review
8 changed files with 246 additions and 63 deletions

View File

@@ -16,7 +16,14 @@
package com.android.server.net;
import static android.system.OsConstants.EPERM;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
@@ -27,6 +34,8 @@ import android.net.MacAddress;
import android.os.Build;
import android.os.Handler;
import android.os.test.TestLooper;
import android.system.ErrnoException;
import android.util.IndentingPrintWriter;
import androidx.test.filters.SmallTest;
@@ -36,6 +45,7 @@ import com.android.net.module.util.InterfaceParams;
import com.android.net.module.util.Struct.U32;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
import com.android.testutils.TestBpfMap;
import org.junit.Before;
import org.junit.Test;
@@ -44,6 +54,9 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.io.PrintWriter;
import java.io.StringWriter;
@SmallTest
@RunWith(DevSdkIgnoreRunner.class)
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
@@ -56,7 +69,8 @@ public final class BpfInterfaceMapUpdaterTest {
private final TestLooper mLooper = new TestLooper();
private BaseNetdUnsolicitedEventListener mListener;
private BpfInterfaceMapUpdater mUpdater;
@Mock private IBpfMap<U32, InterfaceMapValue> mBpfMap;
private IBpfMap<U32, InterfaceMapValue> mBpfMap =
spy(new TestBpfMap<>(U32.class, InterfaceMapValue.class));
@Mock private INetd mNetd;
@Mock private Context mContext;
@@ -118,4 +132,43 @@ public final class BpfInterfaceMapUpdaterTest {
mLooper.dispatchAll();
verifyNoMoreInteractions(mBpfMap);
}
@Test
public void testGetIfNameByIndex() throws Exception {
mBpfMap.updateEntry(new U32(TEST_INDEX), new InterfaceMapValue(TEST_INTERFACE_NAME));
assertEquals(TEST_INTERFACE_NAME, mUpdater.getIfNameByIndex(TEST_INDEX));
}
@Test
public void testGetIfNameByIndexNoEntry() {
assertNull(mUpdater.getIfNameByIndex(TEST_INDEX));
}
@Test
public void testGetIfNameByIndexException() throws Exception {
doThrow(new ErrnoException("", EPERM)).when(mBpfMap).getValue(new U32(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");
}
}

View File

@@ -0,0 +1,68 @@
/*
* 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.
*/
package com.android.server.net;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class InterfaceMapValueTest {
private static final String IF_NAME = "wlan0";
private static final byte[] IF_NAME_BYTE = new byte[]{'w', 'l', 'a', 'n', '0'};
private static final byte[] IF_NAME_BYTE_WITH_PADDING =
new byte[]{'w', 'l', 'a', 'n', '0', 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0}; // IF_NAME_BYTE_WITH_PADDING.length = 16
private static final byte[] IF_NAME_BYTE_LONG =
new byte[]{'w', 'l', 'a', 'n', '0', 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0}; // IF_NAME_BYTE_LONG.length = 24
@Test
public void testInterfaceMapValueFromString() {
final InterfaceMapValue value = new InterfaceMapValue(IF_NAME);
assertArrayEquals(IF_NAME_BYTE_WITH_PADDING, value.interfaceName);
}
@Test
public void testInterfaceMapValueFromByte() {
final InterfaceMapValue value = new InterfaceMapValue(IF_NAME_BYTE_WITH_PADDING);
assertArrayEquals(IF_NAME_BYTE_WITH_PADDING, value.interfaceName);
}
@Test
public void testInterfaceMapValueFromByteShort() {
final InterfaceMapValue value = new InterfaceMapValue(IF_NAME_BYTE);
assertArrayEquals(IF_NAME_BYTE_WITH_PADDING, value.interfaceName);
}
@Test
public void testInterfaceMapValueFromByteLong() {
final InterfaceMapValue value = new InterfaceMapValue(IF_NAME_BYTE_LONG);
assertArrayEquals(IF_NAME_BYTE_WITH_PADDING, value.interfaceName);
}
@Test
public void testGetInterfaceNameString() {
final InterfaceMapValue value = new InterfaceMapValue(IF_NAME_BYTE_WITH_PADDING);
assertEquals(IF_NAME, value.getInterfaceNameString());
}
}

View File

@@ -2528,4 +2528,28 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
assertDumpContains(dump, "uid rxBytes rxPackets txBytes txPackets");
assertDumpContains(dump, "1002 10000 10 6000 6");
}
private void doTestDumpStatsMap(final String expectedIfaceName) throws ErrnoException {
initBpfMapsWithTagData(UID_BLUE);
final String dump = getDump();
assertDumpContains(dump, "mStatsMapA: OK");
assertDumpContains(dump, "mStatsMapB: OK");
assertDumpContains(dump,
"ifaceIndex ifaceName tag_hex uid_int cnt_set rxBytes rxPackets txBytes txPackets");
assertDumpContains(dump, "10 " + expectedIfaceName + " 0x2 1002 0 5000 5 3000 3");
assertDumpContains(dump, "10 " + expectedIfaceName + " 0x1 1002 0 5000 5 3000 3");
}
@Test
public void testDumpStatsMap() throws ErrnoException {
doReturn("wlan0").when(mBpfInterfaceMapUpdater).getIfNameByIndex(10 /* index */);
doTestDumpStatsMap("wlan0");
}
@Test
public void testDumpStatsMapUnknownInterface() throws ErrnoException {
doReturn(null).when(mBpfInterfaceMapUpdater).getIfNameByIndex(10 /* index */);
doTestDumpStatsMap("unknown");
}
}