diff options
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/net/NetworkStats.java | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 292bf8e19664..f0dd2629f93c 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -31,6 +31,7 @@ import java.io.CharArrayWriter; import java.io.PrintWriter; import java.util.Arrays; import java.util.HashSet; +import java.util.Map; import java.util.Objects; /** @@ -97,6 +98,11 @@ public class NetworkStats implements Parcelable { /** Denotes a request for stats at the interface and UID level. */ public static final int STATS_PER_UID = 1; + private static final String CLATD_INTERFACE_PREFIX = "v4-"; + // Delta between IPv4 header (20b) and IPv6 header (40b). + // Used for correct stats accounting on clatd interfaces. + private static final int IPV4V6_HEADER_DELTA = 20; + // TODO: move fields to "mVariable" notation /** @@ -759,6 +765,75 @@ public class NetworkStats implements Parcelable { } /** + * Calculate and apply adjustments to captured statistics for 464xlat traffic counted twice. + * + * <p>This mutates both base and stacked traffic stats, to account respectively for + * double-counted traffic and IPv4/IPv6 header size difference. + * + * <p>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). + * + * <p>This method will behave fine if {@code stackedIfaces} is an non-synchronized but add-only + * {@code ConcurrentHashMap} + * @param baseTraffic Traffic on the base interfaces. Will be mutated. + * @param stackedTraffic Stats with traffic stacked on top of our ifaces. Will also be mutated. + * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both. + */ + public static void apply464xlatAdjustments(NetworkStats baseTraffic, + NetworkStats stackedTraffic, Map<String, String> stackedIfaces) { + // Total 464xlat traffic to subtract from uid 0 on all base interfaces. + // stackedIfaces may grow afterwards, but NetworkStats will just be resized automatically. + final NetworkStats adjustments = new NetworkStats(0, stackedIfaces.size()); + + // For recycling + Entry entry = null; + Entry adjust = new NetworkStats.Entry(IFACE_ALL, 0, 0, 0, 0, 0, 0, 0L, 0L, 0L, 0L, 0L); + + for (int i = 0; i < stackedTraffic.size; i++) { + entry = stackedTraffic.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; + } + // Subtract any 464lat traffic seen for the root UID on the current base interface. + adjust.iface = baseIface; + 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; + stackedTraffic.setValues(i, entry); + } + + baseTraffic.combineAllValues(adjustments); + } + + /** + * Calculate and apply adjustments to captured statistics for 464xlat traffic counted twice. + * + * <p>This mutates the object this method is called on. Equivalent to calling + * {@link #apply464xlatAdjustments(NetworkStats, NetworkStats, Map)} with {@code this} as + * base and stacked traffic. + * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both. + */ + public void apply464xlatAdjustments(Map<String, String> stackedIfaces) { + apply464xlatAdjustments(this, this, stackedIfaces); + } + + /** * Return total statistics grouped by {@link #iface}; doesn't mutate the * original structure. */ |
