Loading services/core/java/com/android/server/net/NetworkStatsFactory.java +2 −3 Original line number Diff line number Diff line Loading @@ -385,10 +385,9 @@ public class NetworkStatsFactory { // Migrate data usage over a VPN to the TUN network. for (VpnInfo info : vpnArray) { delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); } // Filter out debug entries as that may lead to over counting. delta.filterDebugEntries(); } // Update mTunAnd464xlatAdjustedStats with migrated delta. mTunAnd464xlatAdjustedStats.combineAllValues(delta); Loading tests/net/java/com/android/server/net/NetworkStatsBaseTest.java +7 −2 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ abstract class NetworkStatsBaseTest { static final String TEST_IFACE = "test0"; static final String TEST_IFACE2 = "test1"; static final String TUN_IFACE = "test_nss_tun0"; static final String TUN_IFACE2 = "test_nss_tun1"; static final int UID_RED = 1001; static final int UID_BLUE = 1002; Loading Loading @@ -107,10 +108,14 @@ abstract class NetworkStatsBaseTest { assertEquals("unexpected operations", operations, entry.operations); } VpnInfo createVpnInfo(String[] underlyingIfaces) { static VpnInfo createVpnInfo(String[] underlyingIfaces) { return createVpnInfo(TUN_IFACE, underlyingIfaces); } static VpnInfo createVpnInfo(String vpnIface, String[] underlyingIfaces) { VpnInfo info = new VpnInfo(); info.ownerUid = UID_VPN; info.vpnIface = TUN_IFACE; info.vpnIface = vpnIface; info.underlyingIfaces = underlyingIfaces; return info; } Loading tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java +40 −0 Original line number Diff line number Diff line Loading @@ -263,6 +263,46 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { assertValues(tunStats, TEST_IFACE2, UID_VPN, 1200L, 100L, 1200L, 100L); } @Test public void testConcurrentVpns() throws Exception { // Assume two VPNs are connected on two different network interfaces. VPN1 is using // TEST_IFACE and VPN2 is using TEST_IFACE2. final VpnInfo[] vpnInfos = new VpnInfo[] { createVpnInfo(TUN_IFACE, new String[] {TEST_IFACE}), createVpnInfo(TUN_IFACE2, new String[] {TEST_IFACE2})}; mFactory.updateVpnInfos(vpnInfos); // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption // overhead per packet): // 1000 bytes (100 packets) were sent, and 2000 bytes (200 packets) were received by UID_RED // over VPN1. // 700 bytes (70 packets) were sent, and 3000 bytes (300 packets) were received by UID_RED // over VPN2. // 500 bytes (50 packets) were sent, and 1000 bytes (100 packets) were received by UID_BLUE // over VPN1. // 250 bytes (25 packets) were sent, and 500 bytes (50 packets) were received by UID_BLUE // over VPN2. // VPN1 sent 1650 bytes (150 packets), and received 3300 (300 packets) over TEST_IFACE. // Of 1650 bytes sent over WiFi, expect 1000 bytes attributed to UID_RED, 500 bytes // attributed to UID_BLUE, and 150 bytes attributed to UID_VPN. // Of 3300 bytes received over WiFi, expect 2000 bytes attributed to UID_RED, 1000 bytes // attributed to UID_BLUE, and 300 bytes attributed to UID_VPN. // VPN2 sent 1045 bytes (95 packets), and received 3850 (350 packets) over TEST_IFACE2. // Of 1045 bytes sent over Cell, expect 700 bytes attributed to UID_RED, 250 bytes // attributed to UID_BLUE, and 95 bytes attributed to UID_VPN. // Of 3850 bytes received over Cell, expect 3000 bytes attributed to UID_RED, 500 bytes // attributed to UID_BLUE, and 350 bytes attributed to UID_VPN. final NetworkStats tunStats = parseDetailedStats(R.raw.xt_qtaguid_vpn_one_underlying_two_vpn); assertValues(tunStats, TEST_IFACE, UID_RED, 2000L, 200L, 1000L, 100L); assertValues(tunStats, TEST_IFACE, UID_BLUE, 1000L, 100L, 500L, 50L); assertValues(tunStats, TEST_IFACE2, UID_RED, 3000L, 300L, 700L, 70L); assertValues(tunStats, TEST_IFACE2, UID_BLUE, 500L, 50L, 250L, 25L); assertValues(tunStats, TEST_IFACE, UID_VPN, 300L, 0L, 150L, 0L); assertValues(tunStats, TEST_IFACE2, UID_VPN, 350L, 0L, 95L, 0L); } @Test public void testVpnWithTwoUnderlyingIfaces_splitTraffic() throws Exception { // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and Loading tests/net/res/raw/xt_qtaguid_vpn_one_underlying_two_vpn 0 → 100644 +9 −0 Original line number Diff line number Diff line idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets 2 test_nss_tun0 0x0 1001 0 2000 200 1000 100 0 0 0 0 0 0 0 0 0 0 0 0 3 test_nss_tun0 0x0 1002 0 1000 100 500 50 0 0 0 0 0 0 0 0 0 0 0 0 4 test_nss_tun1 0x0 1001 0 3000 300 700 70 0 0 0 0 0 0 0 0 0 0 0 0 5 test_nss_tun1 0x0 1002 0 500 50 250 25 0 0 0 0 0 0 0 0 0 0 0 0 6 test0 0x0 1004 0 3300 300 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 test0 0x0 1004 1 0 0 1650 150 0 0 0 0 0 0 0 0 0 0 0 0 8 test1 0x0 1004 0 3850 350 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 test1 0x0 1004 1 0 0 1045 95 0 0 0 0 0 0 0 0 0 0 0 0 No newline at end of file Loading
services/core/java/com/android/server/net/NetworkStatsFactory.java +2 −3 Original line number Diff line number Diff line Loading @@ -385,10 +385,9 @@ public class NetworkStatsFactory { // Migrate data usage over a VPN to the TUN network. for (VpnInfo info : vpnArray) { delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); } // Filter out debug entries as that may lead to over counting. delta.filterDebugEntries(); } // Update mTunAnd464xlatAdjustedStats with migrated delta. mTunAnd464xlatAdjustedStats.combineAllValues(delta); Loading
tests/net/java/com/android/server/net/NetworkStatsBaseTest.java +7 −2 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ abstract class NetworkStatsBaseTest { static final String TEST_IFACE = "test0"; static final String TEST_IFACE2 = "test1"; static final String TUN_IFACE = "test_nss_tun0"; static final String TUN_IFACE2 = "test_nss_tun1"; static final int UID_RED = 1001; static final int UID_BLUE = 1002; Loading Loading @@ -107,10 +108,14 @@ abstract class NetworkStatsBaseTest { assertEquals("unexpected operations", operations, entry.operations); } VpnInfo createVpnInfo(String[] underlyingIfaces) { static VpnInfo createVpnInfo(String[] underlyingIfaces) { return createVpnInfo(TUN_IFACE, underlyingIfaces); } static VpnInfo createVpnInfo(String vpnIface, String[] underlyingIfaces) { VpnInfo info = new VpnInfo(); info.ownerUid = UID_VPN; info.vpnIface = TUN_IFACE; info.vpnIface = vpnIface; info.underlyingIfaces = underlyingIfaces; return info; } Loading
tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java +40 −0 Original line number Diff line number Diff line Loading @@ -263,6 +263,46 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { assertValues(tunStats, TEST_IFACE2, UID_VPN, 1200L, 100L, 1200L, 100L); } @Test public void testConcurrentVpns() throws Exception { // Assume two VPNs are connected on two different network interfaces. VPN1 is using // TEST_IFACE and VPN2 is using TEST_IFACE2. final VpnInfo[] vpnInfos = new VpnInfo[] { createVpnInfo(TUN_IFACE, new String[] {TEST_IFACE}), createVpnInfo(TUN_IFACE2, new String[] {TEST_IFACE2})}; mFactory.updateVpnInfos(vpnInfos); // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption // overhead per packet): // 1000 bytes (100 packets) were sent, and 2000 bytes (200 packets) were received by UID_RED // over VPN1. // 700 bytes (70 packets) were sent, and 3000 bytes (300 packets) were received by UID_RED // over VPN2. // 500 bytes (50 packets) were sent, and 1000 bytes (100 packets) were received by UID_BLUE // over VPN1. // 250 bytes (25 packets) were sent, and 500 bytes (50 packets) were received by UID_BLUE // over VPN2. // VPN1 sent 1650 bytes (150 packets), and received 3300 (300 packets) over TEST_IFACE. // Of 1650 bytes sent over WiFi, expect 1000 bytes attributed to UID_RED, 500 bytes // attributed to UID_BLUE, and 150 bytes attributed to UID_VPN. // Of 3300 bytes received over WiFi, expect 2000 bytes attributed to UID_RED, 1000 bytes // attributed to UID_BLUE, and 300 bytes attributed to UID_VPN. // VPN2 sent 1045 bytes (95 packets), and received 3850 (350 packets) over TEST_IFACE2. // Of 1045 bytes sent over Cell, expect 700 bytes attributed to UID_RED, 250 bytes // attributed to UID_BLUE, and 95 bytes attributed to UID_VPN. // Of 3850 bytes received over Cell, expect 3000 bytes attributed to UID_RED, 500 bytes // attributed to UID_BLUE, and 350 bytes attributed to UID_VPN. final NetworkStats tunStats = parseDetailedStats(R.raw.xt_qtaguid_vpn_one_underlying_two_vpn); assertValues(tunStats, TEST_IFACE, UID_RED, 2000L, 200L, 1000L, 100L); assertValues(tunStats, TEST_IFACE, UID_BLUE, 1000L, 100L, 500L, 50L); assertValues(tunStats, TEST_IFACE2, UID_RED, 3000L, 300L, 700L, 70L); assertValues(tunStats, TEST_IFACE2, UID_BLUE, 500L, 50L, 250L, 25L); assertValues(tunStats, TEST_IFACE, UID_VPN, 300L, 0L, 150L, 0L); assertValues(tunStats, TEST_IFACE2, UID_VPN, 350L, 0L, 95L, 0L); } @Test public void testVpnWithTwoUnderlyingIfaces_splitTraffic() throws Exception { // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and Loading
tests/net/res/raw/xt_qtaguid_vpn_one_underlying_two_vpn 0 → 100644 +9 −0 Original line number Diff line number Diff line idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets 2 test_nss_tun0 0x0 1001 0 2000 200 1000 100 0 0 0 0 0 0 0 0 0 0 0 0 3 test_nss_tun0 0x0 1002 0 1000 100 500 50 0 0 0 0 0 0 0 0 0 0 0 0 4 test_nss_tun1 0x0 1001 0 3000 300 700 70 0 0 0 0 0 0 0 0 0 0 0 0 5 test_nss_tun1 0x0 1002 0 500 50 250 25 0 0 0 0 0 0 0 0 0 0 0 0 6 test0 0x0 1004 0 3300 300 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 test0 0x0 1004 1 0 0 1650 150 0 0 0 0 0 0 0 0 0 0 0 0 8 test1 0x0 1004 0 3850 350 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 test1 0x0 1004 1 0 0 1045 95 0 0 0 0 0 0 0 0 0 0 0 0 No newline at end of file