NetworkStatsFactory: fix double accounting on IPv6 only networks
For 464xlat scenarios on IPv6 networks, the clatd interface setup
introduces double counting of apps ipv4 traffic. NetworkStatsFactory was
accounting for this on the tx path, but not on the rx path. Also it did
not accounted for the 20 bytes added by the IPv6 header.
This patch subtract correctly the rx and tx traffic from the root uid on
the underlying interface, and also adds correctly the 20 bytes cost per
packet on the stacked interface for 464xlat traffic.
Test: added several new unit tests, based on synthetic data and real
data also.
Bug: 33681750
Change-Id: I2675643b220acbc6110179fa937d4c313b6f5e32
This commit is contained in:
@@ -28,6 +28,7 @@ import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
|
||||
import android.content.res.Resources;
|
||||
import android.net.NetworkStats;
|
||||
import android.net.TrafficStats;
|
||||
import android.support.test.filters.SmallTest;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
import com.android.frameworks.tests.net.R;
|
||||
@@ -44,6 +45,7 @@ import libcore.io.Streams;
|
||||
/**
|
||||
* Tests for {@link NetworkStatsFactory}.
|
||||
*/
|
||||
@SmallTest
|
||||
public class NetworkStatsFactoryTest extends AndroidTestCase {
|
||||
private File mTestProc;
|
||||
private NetworkStatsFactory mFactory;
|
||||
@@ -72,9 +74,8 @@ public class NetworkStatsFactoryTest extends AndroidTestCase {
|
||||
}
|
||||
|
||||
public void testNetworkStatsDetail() throws Exception {
|
||||
stageFile(R.raw.xt_qtaguid_typical, new File(mTestProc, "net/xt_qtaguid/stats"));
|
||||
final NetworkStats stats = parseDetailedStats(R.raw.xt_qtaguid_typical);
|
||||
|
||||
final NetworkStats stats = mFactory.readNetworkStatsDetail();
|
||||
assertEquals(70, stats.size());
|
||||
assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, 18621L, 2898L);
|
||||
assertStatsEntry(stats, "wlan0", 10011, SET_DEFAULT, 0x0, 35777L, 5718L);
|
||||
@@ -98,9 +99,7 @@ public class NetworkStatsFactoryTest extends AndroidTestCase {
|
||||
}
|
||||
|
||||
public void testNetworkStatsWithSet() throws Exception {
|
||||
stageFile(R.raw.xt_qtaguid_typical, new File(mTestProc, "net/xt_qtaguid/stats"));
|
||||
|
||||
final NetworkStats stats = mFactory.readNetworkStatsDetail();
|
||||
final NetworkStats stats = parseDetailedStats(R.raw.xt_qtaguid_typical);
|
||||
assertEquals(70, stats.size());
|
||||
assertStatsEntry(stats, "rmnet1", 10021, SET_DEFAULT, 0x30100000, 219110L, 578L, 227423L,
|
||||
676L);
|
||||
@@ -108,8 +107,7 @@ public class NetworkStatsFactoryTest extends AndroidTestCase {
|
||||
}
|
||||
|
||||
public void testNetworkStatsSingle() throws Exception {
|
||||
stageFile(R.raw.xt_qtaguid_iface_typical,
|
||||
new File(mTestProc, "net/xt_qtaguid/iface_stat_all"));
|
||||
stageFile(R.raw.xt_qtaguid_iface_typical, file("net/xt_qtaguid/iface_stat_all"));
|
||||
|
||||
final NetworkStats stats = mFactory.readNetworkStatsSummaryDev();
|
||||
assertEquals(6, stats.size());
|
||||
@@ -119,8 +117,7 @@ public class NetworkStatsFactoryTest extends AndroidTestCase {
|
||||
}
|
||||
|
||||
public void testNetworkStatsXt() throws Exception {
|
||||
stageFile(R.raw.xt_qtaguid_iface_fmt_typical,
|
||||
new File(mTestProc, "net/xt_qtaguid/iface_stat_fmt"));
|
||||
stageFile(R.raw.xt_qtaguid_iface_fmt_typical, file("net/xt_qtaguid/iface_stat_fmt"));
|
||||
|
||||
final NetworkStats stats = mFactory.readNetworkStatsSummaryXt();
|
||||
assertEquals(3, stats.size());
|
||||
@@ -130,6 +127,67 @@ public class NetworkStatsFactoryTest extends AndroidTestCase {
|
||||
assertStatsEntry(stats, "rmnet2", UID_ALL, SET_ALL, TAG_NONE, 4968L, 35L, 3081L, 39L);
|
||||
}
|
||||
|
||||
public void testDoubleClatAccounting() throws Exception {
|
||||
NetworkStatsFactory.noteStackedIface("v4-wlan0", "wlan0");
|
||||
|
||||
// xt_qtaguid_with_clat_simple is a synthetic file that simulates
|
||||
// - 213 received 464xlat packets of size 200 bytes
|
||||
// - 41 sent 464xlat packets of size 100 bytes
|
||||
// - no other traffic on base interface for root uid.
|
||||
NetworkStats stats = parseDetailedStats(R.raw.xt_qtaguid_with_clat_simple);
|
||||
assertEquals(4, stats.size());
|
||||
|
||||
assertStatsEntry(stats, "v4-wlan0", 10060, SET_DEFAULT, 0x0, 46860L, 4920L);
|
||||
assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, 0L, 0L);
|
||||
|
||||
stats = parseDetailedStats(R.raw.xt_qtaguid_with_clat);
|
||||
assertEquals(42, stats.size());
|
||||
|
||||
assertStatsEntry(stats, "v4-wlan0", 0, SET_DEFAULT, 0x0, 356L, 276L);
|
||||
assertStatsEntry(stats, "v4-wlan0", 1000, SET_DEFAULT, 0x0, 30812L, 2310L);
|
||||
assertStatsEntry(stats, "v4-wlan0", 10102, SET_DEFAULT, 0x0, 10022L, 3330L);
|
||||
assertStatsEntry(stats, "v4-wlan0", 10060, SET_DEFAULT, 0x0, 9532772L, 254112L);
|
||||
assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, 15229L, 5766L);
|
||||
assertStatsEntry(stats, "wlan0", 1000, SET_DEFAULT, 0x0, 6126L, 2013L);
|
||||
assertStatsEntry(stats, "wlan0", 10013, SET_DEFAULT, 0x0, 0L, 144L);
|
||||
assertStatsEntry(stats, "wlan0", 10018, SET_DEFAULT, 0x0, 5980263L, 167667L);
|
||||
assertStatsEntry(stats, "wlan0", 10060, SET_DEFAULT, 0x0, 134356L, 8705L);
|
||||
assertStatsEntry(stats, "wlan0", 10079, SET_DEFAULT, 0x0, 10926L, 1507L);
|
||||
assertStatsEntry(stats, "wlan0", 10102, SET_DEFAULT, 0x0, 25038L, 8245L);
|
||||
assertStatsEntry(stats, "wlan0", 10103, SET_DEFAULT, 0x0, 0L, 192L);
|
||||
assertStatsEntry(stats, "dummy0", 0, SET_DEFAULT, 0x0, 0L, 168L);
|
||||
assertStatsEntry(stats, "lo", 0, SET_DEFAULT, 0x0, 1288L, 1288L);
|
||||
|
||||
NetworkStatsFactory.noteStackedIface("v4-wlan0", null);
|
||||
}
|
||||
|
||||
public void testDoubleClatAccounting100MBDownload() throws Exception {
|
||||
// Downloading 100mb from an ipv4 only destination in a foreground activity
|
||||
|
||||
long appRxBytesBefore = 328684029L;
|
||||
long appRxBytesAfter = 439237478L;
|
||||
assertEquals("App traffic should be ~100MB", 110553449, appRxBytesAfter - appRxBytesBefore);
|
||||
|
||||
long rootRxBytesBefore = 1394011L;
|
||||
long rootRxBytesAfter = 1398634L;
|
||||
assertEquals("UID 0 traffic should be ~0", 4623, rootRxBytesAfter - rootRxBytesBefore);
|
||||
|
||||
NetworkStatsFactory.noteStackedIface("v4-wlan0", "wlan0");
|
||||
NetworkStats stats;
|
||||
|
||||
// Stats snapshot before the download
|
||||
stats = parseDetailedStats(R.raw.xt_qtaguid_with_clat_100mb_download_before);
|
||||
assertStatsEntry(stats, "v4-wlan0", 10106, SET_FOREGROUND, 0x0, appRxBytesBefore, 5199872L);
|
||||
assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, rootRxBytesBefore, 647888L);
|
||||
|
||||
// Stats snapshot after the download
|
||||
stats = parseDetailedStats(R.raw.xt_qtaguid_with_clat_100mb_download_after);
|
||||
assertStatsEntry(stats, "v4-wlan0", 10106, SET_FOREGROUND, 0x0, appRxBytesAfter, 7867488L);
|
||||
assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, rootRxBytesAfter, 647587L);
|
||||
|
||||
NetworkStatsFactory.noteStackedIface("v4-wlan0", null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a {@link Resources#openRawResource(int)} into {@link File} for
|
||||
* testing purposes.
|
||||
@@ -159,9 +217,22 @@ public class NetworkStatsFactoryTest extends AndroidTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
private File file(String path) throws Exception {
|
||||
return new File(mTestProc, path);
|
||||
}
|
||||
|
||||
private NetworkStats parseDetailedStats(int resourceId) throws Exception {
|
||||
stageFile(resourceId, file("net/xt_qtaguid/stats"));
|
||||
return mFactory.readNetworkStatsDetail();
|
||||
}
|
||||
|
||||
private static void assertStatsEntry(NetworkStats stats, String iface, int uid, int set,
|
||||
int tag, long rxBytes, long txBytes) {
|
||||
final int i = stats.findIndex(iface, uid, set, tag, METERED_NO, ROAMING_NO);
|
||||
if (i < 0) {
|
||||
fail(String.format("no NetworkStats for (iface: %s, uid: %d, set: %d, tag: %d)",
|
||||
iface, uid, set, tag));
|
||||
}
|
||||
final NetworkStats.Entry entry = stats.getValues(i, null);
|
||||
assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
|
||||
assertEquals("unexpected txBytes", txBytes, entry.txBytes);
|
||||
@@ -170,6 +241,10 @@ public class NetworkStatsFactoryTest extends AndroidTestCase {
|
||||
private static void assertStatsEntry(NetworkStats stats, String iface, int uid, int set,
|
||||
int tag, long rxBytes, long rxPackets, long txBytes, long txPackets) {
|
||||
final int i = stats.findIndex(iface, uid, set, tag, METERED_NO, ROAMING_NO);
|
||||
if (i < 0) {
|
||||
fail(String.format("no NetworkStats for (iface: %s, uid: %d, set: %d, tag: %d)",
|
||||
iface, uid, set, tag));
|
||||
}
|
||||
final NetworkStats.Entry entry = stats.getValues(i, null);
|
||||
assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
|
||||
assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets);
|
||||
|
||||
Reference in New Issue
Block a user