From 5efd907d853717d2a96c55867b3b79d1634d7e1c Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Thu, 27 Apr 2017 14:52:53 +0900 Subject: [PATCH] NetworkStatsFactory: no double looping on stats + stacked interfaces This patch uses the associative structure of the stacked/base interface collection to avoid the two nested for loops over stacked/base interfaces and all stats entries when correcting 464xlat traffic stats. Consequently the list of stats entries is iterated only once. Test: runtest -x frameworks/base/../NetworkStatsFactoryTest.java Bug: 33681750 Change-Id: I84ae997fb693b909f431764697627b9957131732 --- .../internal/net/NetworkStatsFactory.java | 63 +++++++++---------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index 2fb3532c8f..3d3e148fb3 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -192,46 +192,43 @@ public class NetworkStatsFactory { NetworkStats lastStats) throws IOException { final NetworkStats stats = readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag, lastStats); - NetworkStats.Entry entry = null; // for recycling - + final ArrayMap stackedIfaces; synchronized (sStackedIfaces) { - // For 464xlat traffic, xt_qtaguid sees every IPv4 packet twice, once as a native IPv4 - // packet on the stacked interface, and once as translated to an IPv6 packet on the - // base interface. For correct stats accounting on the base interface, every 464xlat - // packet needs to be subtracted from the root UID on the base interface both for tx - // and rx traffic (http://b/12249687, http:/b/33681750). - final int size = sStackedIfaces.size(); - for (int i = 0; i < size; i++) { - final String stackedIface = sStackedIfaces.keyAt(i); - final String baseIface = sStackedIfaces.valueAt(i); - if (!stackedIface.startsWith(CLATD_INTERFACE_PREFIX)) { - continue; - } - - NetworkStats.Entry adjust = - new NetworkStats.Entry(baseIface, 0, 0, 0, 0L, 0L, 0L, 0L, 0L); - for (int j = 0; j < stats.size(); j++) { - entry = stats.getValues(j, entry); - if (Objects.equals(entry.iface, stackedIface)) { - adjust.rxBytes -= (entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA); - adjust.txBytes -= (entry.txBytes + entry.txPackets * IPV4V6_HEADER_DELTA); - adjust.rxPackets -= entry.rxPackets; - adjust.txPackets -= entry.txPackets; - } - } - stats.combineValues(adjust); - } + stackedIfaces = new ArrayMap<>(sStackedIfaces); } + // Total 464xlat traffic to subtract from uid 0 on all base interfaces. + final NetworkStats adjustments = new NetworkStats(0, stackedIfaces.size()); - // For 464xlat traffic, xt_qtaguid only counts the bytes of the inner IPv4 packet sent on - // the stacked interface with prefix "v4-" and drops the IPv6 header size after unwrapping. - // To account correctly for on-the-wire traffic, add the 20 additional bytes difference - // for all packets (http://b/12249687, http:/b/33681750). + NetworkStats.Entry entry = null; // For recycling + + // For 464xlat traffic, xt_qtaguid sees every IPv4 packet twice, once as a native IPv4 + // packet on the stacked interface, and once as translated to an IPv6 packet on the + // base interface. For correct stats accounting on the base interface, every 464xlat + // packet needs to be subtracted from the root UID on the base interface both for tx + // and rx traffic (http://b/12249687, http:/b/33681750). for (int i = 0; i < stats.size(); i++) { entry = stats.getValues(i, entry); if (entry.iface == null || !entry.iface.startsWith(CLATD_INTERFACE_PREFIX)) { continue; } + final String baseIface = stackedIfaces.get(entry.iface); + if (baseIface == null) { + continue; + } + + NetworkStats.Entry adjust = + new NetworkStats.Entry(baseIface, 0, 0, 0, 0L, 0L, 0L, 0L, 0L); + // Subtract any 464lat traffic seen for the root UID on the current base interface. + adjust.rxBytes -= (entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA); + adjust.txBytes -= (entry.txBytes + entry.txPackets * IPV4V6_HEADER_DELTA); + adjust.rxPackets -= entry.rxPackets; + adjust.txPackets -= entry.txPackets; + adjustments.combineValues(adjust); + + // For 464xlat traffic, xt_qtaguid only counts the bytes of the native IPv4 packet sent + // on the stacked interface with prefix "v4-" and drops the IPv6 header size after + // unwrapping. To account correctly for on-the-wire traffic, add the 20 additional bytes + // difference for all packets (http://b/12249687, http:/b/33681750). entry.rxBytes = entry.rxPackets * IPV4V6_HEADER_DELTA; entry.txBytes = entry.txPackets * IPV4V6_HEADER_DELTA; entry.rxPackets = 0; @@ -239,6 +236,8 @@ public class NetworkStatsFactory { stats.combineValues(entry); } + stats.combineAllValues(adjustments); + return stats; }