summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/net/NetworkStats.java75
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.
*/