Merge "Merge "NetworkStatsFactory: fix double accounting on IPv6 only networks" am: ce730270bc am: 76dc14ec88 am: 1697d48faf" into oc-dev-plus-aosp

am: f8dbdba5a2

Change-Id: Ie09f2b4e04749e61923781f4b13e796054108fad
This commit is contained in:
Hugo Benichi
2017-05-10 02:06:06 +00:00
committed by android-build-merger

View File

@@ -50,6 +50,11 @@ public class NetworkStatsFactory {
private static final boolean USE_NATIVE_PARSING = true; private static final boolean USE_NATIVE_PARSING = true;
private static final boolean SANITY_CHECK_NATIVE = false; private static final boolean SANITY_CHECK_NATIVE = false;
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;
/** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */ /** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */
private final File mStatsXtIfaceAll; private final File mStatsXtIfaceAll;
/** Path to {@code /proc/net/xt_qtaguid/iface_stat_fmt}. */ /** Path to {@code /proc/net/xt_qtaguid/iface_stat_fmt}. */
@@ -57,6 +62,7 @@ public class NetworkStatsFactory {
/** Path to {@code /proc/net/xt_qtaguid/stats}. */ /** Path to {@code /proc/net/xt_qtaguid/stats}. */
private final File mStatsXtUid; private final File mStatsXtUid;
// TODO: to improve testability and avoid global state, do not use a static variable.
@GuardedBy("sStackedIfaces") @GuardedBy("sStackedIfaces")
private static final ArrayMap<String, String> sStackedIfaces = new ArrayMap<>(); private static final ArrayMap<String, String> sStackedIfaces = new ArrayMap<>();
@@ -124,9 +130,7 @@ public class NetworkStatsFactory {
stats.addValues(entry); stats.addValues(entry);
reader.finishLine(); reader.finishLine();
} }
} catch (NullPointerException e) { } catch (NullPointerException|NumberFormatException e) {
throw new ProtocolException("problem parsing stats", e);
} catch (NumberFormatException e) {
throw new ProtocolException("problem parsing stats", e); throw new ProtocolException("problem parsing stats", e);
} finally { } finally {
IoUtils.closeQuietly(reader); IoUtils.closeQuietly(reader);
@@ -171,9 +175,7 @@ public class NetworkStatsFactory {
stats.addValues(entry); stats.addValues(entry);
reader.finishLine(); reader.finishLine();
} }
} catch (NullPointerException e) { } catch (NullPointerException|NumberFormatException e) {
throw new ProtocolException("problem parsing stats", e);
} catch (NumberFormatException e) {
throw new ProtocolException("problem parsing stats", e); throw new ProtocolException("problem parsing stats", e);
} finally { } finally {
IoUtils.closeQuietly(reader); IoUtils.closeQuietly(reader);
@@ -188,26 +190,32 @@ public class NetworkStatsFactory {
public NetworkStats readNetworkStatsDetail(int limitUid, String[] limitIfaces, int limitTag, public NetworkStats readNetworkStatsDetail(int limitUid, String[] limitIfaces, int limitTag,
NetworkStats lastStats) throws IOException { NetworkStats lastStats) throws IOException {
final NetworkStats stats = readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag, final NetworkStats stats =
lastStats); readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag, lastStats);
NetworkStats.Entry entry = null; // for recycling
synchronized (sStackedIfaces) { synchronized (sStackedIfaces) {
// Sigh, xt_qtaguid ends up double-counting tx traffic going through // For 464xlat traffic, xt_qtaguid sees every IPv4 packet twice, once as a native IPv4
// clatd interfaces, so we need to subtract it here. // 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(); final int size = sStackedIfaces.size();
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
final String stackedIface = sStackedIfaces.keyAt(i); final String stackedIface = sStackedIfaces.keyAt(i);
final String baseIface = sStackedIfaces.valueAt(i); final String baseIface = sStackedIfaces.valueAt(i);
if (!stackedIface.startsWith(CLATD_INTERFACE_PREFIX)) {
continue;
}
// Count up the tx traffic and subtract from root UID on the NetworkStats.Entry adjust =
// base interface. new NetworkStats.Entry(baseIface, 0, 0, 0, 0L, 0L, 0L, 0L, 0L);
NetworkStats.Entry adjust = new NetworkStats.Entry(baseIface, 0, 0, 0, 0L, 0L, 0L,
0L, 0L);
NetworkStats.Entry entry = null;
for (int j = 0; j < stats.size(); j++) { for (int j = 0; j < stats.size(); j++) {
entry = stats.getValues(j, entry); entry = stats.getValues(j, entry);
if (Objects.equals(entry.iface, stackedIface)) { if (Objects.equals(entry.iface, stackedIface)) {
adjust.txBytes -= entry.txBytes; 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; adjust.txPackets -= entry.txPackets;
} }
} }
@@ -215,19 +223,20 @@ public class NetworkStatsFactory {
} }
} }
// Double sigh, all rx traffic on clat needs to be tweaked to // For 464xlat traffic, xt_qtaguid only counts the bytes of the inner IPv4 packet sent on
// account for the dropped IPv6 header size post-unwrap. // the stacked interface with prefix "v4-" and drops the IPv6 header size after unwrapping.
NetworkStats.Entry entry = null; // To account correctly for on-the-wire traffic, add the 20 additional bytes difference
// for all packets (http://b/12249687, http:/b/33681750).
for (int i = 0; i < stats.size(); i++) { for (int i = 0; i < stats.size(); i++) {
entry = stats.getValues(i, entry); entry = stats.getValues(i, entry);
if (entry.iface != null && entry.iface.startsWith("clat")) { if (entry.iface == null || !entry.iface.startsWith(CLATD_INTERFACE_PREFIX)) {
// Delta between IPv4 header (20b) and IPv6 header (40b) continue;
entry.rxBytes = entry.rxPackets * 20;
entry.rxPackets = 0;
entry.txBytes = 0;
entry.txPackets = 0;
stats.combineValues(entry);
} }
entry.rxBytes = entry.rxPackets * IPV4V6_HEADER_DELTA;
entry.txBytes = entry.txPackets * IPV4V6_HEADER_DELTA;
entry.rxPackets = 0;
entry.txPackets = 0;
stats.combineValues(entry);
} }
return stats; return stats;
@@ -305,9 +314,7 @@ public class NetworkStatsFactory {
reader.finishLine(); reader.finishLine();
} }
} catch (NullPointerException e) { } catch (NullPointerException|NumberFormatException e) {
throw new ProtocolException("problem parsing idx " + idx, e);
} catch (NumberFormatException e) {
throw new ProtocolException("problem parsing idx " + idx, e); throw new ProtocolException("problem parsing idx " + idx, e);
} finally { } finally {
IoUtils.closeQuietly(reader); IoUtils.closeQuietly(reader);