Merge "Mock QuiConnectionCloser in ConnectivityServiceTest" into main
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 68cbdc7..97a78cf 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -15,6 +15,3 @@
hidden_api_txt_checksorted_hook = ${REPO_ROOT}/tools/platform-compat/hiddenapi/checksorted_sha.sh ${PREUPLOAD_COMMIT} ${REPO_ROOT}
python_hook = ${REPO_ROOT}/packages/modules/Connectivity/preupload_hook_script.py ${PREUPLOAD_FILES}
-
-# go/alint for details
-alint_hook = ${REPO_ROOT}/vendor/google/tools/alint
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
index 8f701ba..89edc32 100644
--- a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
+++ b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
@@ -501,6 +501,12 @@
lastMaxSessionCount);
}
+ /** Send a BpfCoordinatorShimInitError event. */
+ public void sendBpfCoordinatorShimInitError() {
+ ConnectivityStatsLog.write(ConnectivityStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED,
+ ConnectivityStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_BPF_COORDINATOR_SHIM_INIT_ERROR);
+ }
+
/**
* @see DeviceConfigUtils#isTetheringFeatureEnabled
*/
@@ -542,6 +548,7 @@
mBpfCoordinatorShim = BpfCoordinatorShim.getBpfCoordinatorShim(deps);
if (!mBpfCoordinatorShim.isInitialized()) {
mLog.e("Bpf shim not initialized");
+ mDeps.sendBpfCoordinatorShimInitError();
}
// BPF IPv4 forwarding only supports on S+.
diff --git a/bpf/loader/netbpfload.35rc b/bpf/loader/netbpfload.35rc
index 683abce..a23bd60 100644
--- a/bpf/loader/netbpfload.35rc
+++ b/bpf/loader/netbpfload.35rc
@@ -1,6 +1,8 @@
+# This takes effect on Android 15+ (V+ 25Q2+)
+# Note that 'capabilities SYSLOG' lacks sepolicy prior to 25Q4
service bpfloader /apex/com.android.tethering/bin/netbpfload
# netbpfload will do network bpf loading, then execute /system/bin/bpfloader
- capabilities CHOWN SYS_ADMIN NET_ADMIN
+ capabilities CHOWN SYS_ADMIN NET_ADMIN SYSLOG
# The following group memberships are a workaround for lack of DAC_OVERRIDE
# and allow us to open (among other things) files that we created and are
# no longer root owned (due to CHOWN) but still have group read access to
diff --git a/bpf/progs/Android.bp b/bpf/progs/Android.bp
index 555cfef..4712c35 100644
--- a/bpf/progs/Android.bp
+++ b/bpf/progs/Android.bp
@@ -117,10 +117,3 @@
include_dirs: ["packages/modules/Connectivity/bpf/progs/include"],
sub_dir: "mainline",
}
-
-bpf {
- name: "tcpAccECN.o",
- srcs: ["tcpAccECN.c"],
- include_dirs: ["packages/modules/Connectivity/bpf/progs/include"],
- sub_dir: "mainline",
-}
diff --git a/bpf/progs/netd.c b/bpf/progs/netd.c
index cb5ece7..e8299ef 100644
--- a/bpf/progs/netd.c
+++ b/bpf/progs/netd.c
@@ -902,4 +902,10 @@
return BPF_ALLOW;
}
+#undef BPFLOADER_MIN_VER
+#undef BPF_OBJ_NAME
+#undef DEFAULT_BPF_PIN_SUBDIR
+
+#include "tcpAccECN.c"
+
LICENSE("Apache 2.0");
diff --git a/bpf/progs/netd.h b/bpf/progs/netd.h
index 79c6e37..8b9486e 100644
--- a/bpf/progs/netd.h
+++ b/bpf/progs/netd.h
@@ -236,8 +236,6 @@
// Entry in the data saver enabled map that stores whether data saver is enabled or not.
#define DATA_SAVER_ENABLED_KEY 0
-#undef STRUCT_SIZE
-
// DROP_IF_SET is set of rules that DROP if rule is globally enabled, and per-uid bit is set
#define DROP_IF_SET (STANDBY_MATCH | OEM_DENY_1_MATCH | OEM_DENY_2_MATCH | OEM_DENY_3_MATCH)
// DROP_IF_UNSET is set of rules that should DROP if globally enabled, and per-uid bit is NOT set
diff --git a/bpf/progs/tcpAccECN.c b/bpf/progs/tcpAccECN.c
index 33a8917..ac90ace 100644
--- a/bpf/progs/tcpAccECN.c
+++ b/bpf/progs/tcpAccECN.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2025 Samsung Electronics.
+ * Copyright (C) 2025 Samsung Electronics.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,12 +20,8 @@
* Includes separate handling for Ethernet and raw IP packets.
*/
-// The resulting .o needs to load on Android T+
-#define BPFLOADER_MIN_VER BPFLOADER_MAINLINE_T_VERSION
-#define BPF_OBJ_NAME "tcpAccECN"
-#define DEFAULT_BPF_PIN_SUBDIR "netd_shared"
-
#include <linux/bpf.h>
+#include <linux/filter.h>
#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
@@ -33,30 +29,21 @@
#include <linux/in6.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
+#include <linux/pkt_cls.h>
#include <linux/tcp.h>
#include <stdint.h>
-#include "bpf_helpers.h"
-#include <tcpAccECN.h>
-#include <linux/pkt_cls.h>
-#include <linux/filter.h>
-// Offsets from beginning of L4 (TCP) header
-#define TCP_OFFSET(field) offsetof(struct tcphdr, field)
+// The resulting .o needs to load on Android 26Q2+
+#define BPFLOADER_MIN_VER BPFLOADER_MAINLINE_26Q2_VERSION
+#define BPF_OBJ_NAME "tcpAccECN"
+#define DEFAULT_BPF_PIN_SUBDIR "netd_shared"
-// Offsets from beginning of L3 (IPv4) header
-#define IP4_OFFSET(field) offsetof(struct iphdr, field)
-#define IP6_OFFSET(field) offsetof(struct ipv6hdr, field)
-#define IP4_TCP_OFFSET(field) (sizeof(struct iphdr) + TCP_OFFSET(field))
-#define IP6_TCP_OFFSET(field) (sizeof(struct ipv6hdr) + TCP_OFFSET(field))
+#include "bpf_net_helpers.h"
+#include "tcpAccECN.h"
-// Offsets from beginning of L2 (ie. Ethernet) header (which must be present)
-#define ETH_IP4_OFFSET(field) (ETH_HLEN + IP4_OFFSET(field))
-#define ETH_IP4_TCP_OFFSET(field) (ETH_HLEN + IP4_TCP_OFFSET(field))
-#define ETH_IP6_OFFSET(field) (ETH_HLEN + IP6_OFFSET(field))
-#define ETH_IP6_TCP_OFFSET(field) (ETH_HLEN + IP6_TCP_OFFSET(field))
-
-#define IP4_TCP_FLAGS_OFF (sizeof(struct iphdr) + 12)
-#define IP6_TCP_FLAGS_OFF (sizeof(struct ipv6hdr) + 12)
+#define TCP_FLAGS_OFF 12
+#define IP4_TCP_FLAGS_OFF (sizeof(struct iphdr) + TCP_FLAGS_OFF)
+#define IP6_TCP_FLAGS_OFF (sizeof(struct ipv6hdr) + TCP_FLAGS_OFF)
#define ETH_IP4_TCP_FLAGS_OFF (ETH_HLEN + IP4_TCP_FLAGS_OFF)
#define ETH_IP6_TCP_FLAGS_OFF (ETH_HLEN + IP6_TCP_FLAGS_OFF)
@@ -71,27 +58,10 @@
DEFINE_BPF_MAP(l4s_accecn_byte_map, LRU_HASH, uint32_t, EcnByteCounters, L4S_ACCECN_MAP_SIZE)
DEFINE_BPF_MAP(l4s_accecn_mss_map, LRU_HASH, uint32_t, uint16_t, L4S_ACCECN_MAP_SIZE)
-static int (*bpf_skb_store_bytes)(struct __sk_buff* skb, __u32 offset, const void* from, __u32 len,
- __u64 flags) = (void*)BPF_FUNC_skb_store_bytes;
-
-static int (*bpf_l4_csum_replace)(struct __sk_buff* skb, __u32 offset, __u64 from, __u64 to,
- __u64 flags) = (void*)BPF_FUNC_l4_csum_replace;
-
-static int (*bpf_l3_csum_replace)(struct __sk_buff* skb, __u32 offset, __u64 from, __u64 to,
- __u64 flags) = (void*)BPF_FUNC_l3_csum_replace;
-
-static int (*bpf_skb_load_bytes)(struct __sk_buff *skb, int off, void *to, int len) = (void *) BPF_FUNC_skb_load_bytes;
-static int64_t (*bpf_csum_diff)(__be32 *from, __u32 from_size, __be32 *to, __u32 to_size, __wsum seed) = (void*) BPF_FUNC_csum_diff;
static int (*bpf_sock_ops_cb_flags_set)(struct bpf_sock_ops *skops, int flags) = (void *) BPF_FUNC_sock_ops_cb_flags_set;
static int (*bpf_reserve_hdr_opt)(struct bpf_sock_ops *skops, int space, int flags) = (void *) BPF_FUNC_reserve_hdr_opt;
static int (*bpf_store_hdr_opt)(struct bpf_sock_ops *skops, void *from, int len, int flags) = (void *) BPF_FUNC_store_hdr_opt;
-// Android only supports little endian architectures
-#define htons(x) (__builtin_constant_p(x) ? ___constant_swab16(x) : __builtin_bswap16(x))
-#define htonl(x) (__builtin_constant_p(x) ? ___constant_swab32(x) : __builtin_bswap32(x))
-#define ntohs(x) htons(x)
-#define ntohl(x) htonl(x)
-
static inline __attribute__((always_inline)) int
find_accecn_options_offset(struct __sk_buff *skb, uint8_t offset) {
int ret;
@@ -729,5 +699,3 @@
}
return TC_ACT_PIPE;
}
-
-LICENSE("Apache 2.0");
diff --git a/bpf/progs/tcpAccECN.h b/bpf/progs/tcpAccECN.h
index ceb4a41..e927c6d 100644
--- a/bpf/progs/tcpAccECN.h
+++ b/bpf/progs/tcpAccECN.h
@@ -1,22 +1,13 @@
#pragma once
-// This header file is shared by eBPF kernel programs (C) and netd (C++) and
-// some of the maps are also accessed directly from Java mainline module code.
-//
-// Hence: explicitly pad all relevant structures and assert that their size
-// is the sum of the sizes of their fields.
-#define STRUCT_SIZE(name, size) _Static_assert(sizeof(name) == (size), "Incorrect struct size.")
-
-#define SS_BPF_PATH "/sys/fs/bpf/"
-
-#define L4S_INGRESS_ETHER_PROG_PATH SS_BPF_PATH "prog_tcpAccECN_schedcls_ingress_l4s_accecn_eth"
-#define L4S_EGRESS_ETHER_PROG_PATH SS_BPF_PATH "prog_tcpAccECN_schedcls_egress_l4s_accecn_eth"
-#define L4S_INGRESS_RAWIP_PROG_PATH SS_BPF_PATH "prog_tcpAccECN_schedcls_ingress_l4s_accecn_rawip"
-#define L4S_EGRESS_RAWIP_PROG_PATH SS_BPF_PATH "prog_tcpAccECN_schedcls_egress_l4s_accecn_rawip"
-#define L4S_OPTIONS_SOCKOPS_PROG_PATH SS_BPF_PATH "prog_tcpAccECN_sockops_l4s_accecn_option"
-#define L4S_ACCECN_CE_MAP_PATH SS_BPF_PATH "map_tcpAccECN_l4s_accecn_ce_map"
-#define L4S_ACCECN_BYTE_MAP_PATH SS_BPF_PATH "map_tcpAccECN_l4s_accecn_byte_map"
-#define L4S_ACCECN_MSS_MAP_PATH SS_BPF_PATH "map_tcpAccECN_l4s_accecn_mss_map"
+#define L4S_INGRESS_ETHER_PROG_PATH BPF_NETD_PATH "prog_tcpAccECN_schedcls_ingress_accecn_eth"
+#define L4S_EGRESS_ETHER_PROG_PATH BPF_NETD_PATH "prog_tcpAccECN_schedcls_egress_accecn_eth"
+#define L4S_INGRESS_RAWIP_PROG_PATH BPF_NETD_PATH "prog_tcpAccECN_schedcls_ingress_accecn_rawip"
+#define L4S_EGRESS_RAWIP_PROG_PATH BPF_NETD_PATH "prog_tcpAccECN_schedcls_egress_accecn_rawip"
+#define L4S_OPTIONS_SOCKOPS_PROG_PATH BPF_NETD_PATH "prog_tcpAccECN_sockops_l4s_accecn_option"
+#define L4S_ACCECN_CE_MAP_PATH BPF_NETD_PATH "map_tcpAccECN_l4s_accecn_ce_map"
+#define L4S_ACCECN_BYTE_MAP_PATH BPF_NETD_PATH "map_tcpAccECN_l4s_accecn_byte_map"
+#define L4S_ACCECN_MSS_MAP_PATH BPF_NETD_PATH "map_tcpAccECN_l4s_accecn_mss_map"
typedef struct{
uint64_t ceb;
diff --git a/bpf/tests/mts/bpf_existence_test.cpp b/bpf/tests/mts/bpf_existence_test.cpp
index 3a2d962..dc15e22 100644
--- a/bpf/tests/mts/bpf_existence_test.cpp
+++ b/bpf/tests/mts/bpf_existence_test.cpp
@@ -49,15 +49,6 @@
class BpfExistenceTest : public ::testing::Test {
};
-// Part of Android R platform (for 4.9+), but mainlined in S
-static const set<string> PLATFORM_ONLY_IN_R = {
- PLATFORM "map_offload_tether_ingress_map",
- PLATFORM "map_offload_tether_limit_map",
- PLATFORM "map_offload_tether_stats_map",
- PLATFORM "prog_offload_schedcls_ingress_tether_ether",
- PLATFORM "prog_offload_schedcls_ingress_tether_rawip",
-};
-
// Provided by *current* mainline module for S+ devices
static const set<string> MAINLINE_FOR_S_PLUS = {
TETHERING "map_kernel_bugs",
@@ -182,19 +173,14 @@
set<string> mustExist;
set<string> mustNotExist;
- // We do not actually check the platform P/Q (netd) and Q (clatd) things
- // and only verify the mainline module relevant R+ offload maps & progs.
+ // We only verify the mainline module relevant S+ offload maps & progs.
//
// The goal of this test is to verify compatibility with the tethering mainline module,
// and not to test the platform itself, which may have been modified by vendor or oems,
// so we should only test for the removal of stuff that was mainline'd,
// and for the presence of mainline stuff.
- // Note: Q is no longer supported by mainline
- ASSERT_TRUE(isAtLeastR);
-
- // R can potentially run on pre-4.9 kernel non-eBPF capable devices.
- DO_EXPECT(isAtLeastR && !isAtLeastS && isAtLeastKernelVersion(4, 9, 0), PLATFORM_ONLY_IN_R);
+ ASSERT_TRUE(isAtLeastS); // Q & R are no longer supported by mainline
// S requires Linux Kernel 4.9+ and thus requires eBPF support.
if (isAtLeastS) ASSERT_TRUE(isAtLeastKernelVersion(4, 9, 0));
diff --git a/service/src/com/android/metrics/SatelliteCoarseUsageMetricsCollector.java b/service/src/com/android/metrics/SatelliteCoarseUsageMetricsCollector.java
index 7e8e463..0dea382 100644
--- a/service/src/com/android/metrics/SatelliteCoarseUsageMetricsCollector.java
+++ b/service/src/com/android/metrics/SatelliteCoarseUsageMetricsCollector.java
@@ -299,12 +299,11 @@
private void handleStartMonitoring() {
// Note that in the constructor it is too early to get the managers.
mCm = mContext.getSystemService(ConnectivityManager.class);
+ // Note: there is no need to call setPollOnOpen(true) to obtain accurate data. This class
+ // collects data usage only when processing the onLost callback, and ConnectivityService
+ // calls onLost only after it calls notifyIfacesChangedForNetworkStats, which forces a poll.
+ // Also, it is not safe to call setPollOnOpen(true) inside system server. b/427909947 .
mNsm = mContext.getSystemService(NetworkStatsManager.class);
- // Note: This might create heavy workload on NetworkStatsService if queried with high
- // frequency, as the calling UID is system. Each query made with this manager
- // updates usage stored in files before returning the newest result.
- // This behavior is not rate-limited because the calling uid is the system UID.
- mNsm.setPollOnOpen(true);
// Get the first baseline.
updateStartTimestamp();
mSatelliteBaseline = mDeps.getSummary(mNsm, mStartTime);
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/SetFeatureFlagsRule.kt b/staticlibs/testutils/devicetests/com/android/testutils/SetFeatureFlagsRule.kt
index 0b239b4..1211260 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/SetFeatureFlagsRule.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/SetFeatureFlagsRule.kt
@@ -16,6 +16,7 @@
package com.android.testutils.com.android.testutils
+import com.android.testutils.tryTest
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
@@ -90,10 +91,12 @@
// Execute the test method, which includes methods annotated with
// @Before, @Test and @After.
- base.evaluate()
-
- valuesToBeRestored.forEach {
- setFlagsMethod(it.key, it.value)
+ tryTest {
+ base.evaluate()
+ } cleanup {
+ valuesToBeRestored.forEach {
+ setFlagsMethod(it.key, it.value)
+ }
}
}
}
diff --git a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
index 3b7d588..f795905 100644
--- a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
@@ -324,6 +324,12 @@
val cb = events.poll(NO_CALLBACK_TIMEOUT_MS)
assertNull(cb, "Expected no callback but got $cb")
}
+
+ fun assumeNoCallback() {
+ val cb = events.poll(0 /* timeout */)
+ // Note that assumeNull does not exist.
+ assumeTrue(cb == null)
+ }
}
private class TetheredInterfaceListener : TetheredInterfaceCallback {
@@ -617,7 +623,7 @@
// check is explicitly *not* using an interface state listener.
// Since restricted interfaces cannot be used for tethering,
// assumeNoInterfaceForTetheringAvailable() is an okay proxy.
- assumeNoInterfaceForTetheringAvailable()
+ assumeNoUnrestrictedInterfacesAvailable()
// If an interface exists when the callback is registered, it is reported on registration.
val iface = createInterface()
@@ -680,6 +686,15 @@
}
}
+ private fun assumeNoUnrestrictedInterfacesAvailable() {
+ val listener = EthernetStateListener()
+ addInterfaceStateListener(listener)
+
+ // Force interface state listener callbacks to be processed before proceeding.
+ setEthernetEnabled(ethernetEnabled)
+ listener.assumeNoCallback()
+ }
+
@Test
fun testCallbacks_forServerModeInterfaces() {
// do not run this test if an interface that can be used for tethering already exists.
diff --git a/tests/smoketest/Android.bp b/tests/smoketest/Android.bp
index 121efa1..0456c72 100644
--- a/tests/smoketest/Android.bp
+++ b/tests/smoketest/Android.bp
@@ -17,6 +17,7 @@
android_test {
name: "FrameworksNetSmokeTests",
+ min_sdk_version: "31",
defaults: ["FrameworksNetTests-jni-defaults"],
srcs: ["java/SmokeTest.java"],
test_suites: ["device-tests"],
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index 28d01c5..299d03e 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -147,6 +147,7 @@
android_test {
name: "FrameworksNetTests",
+ min_sdk_version: "31",
enabled: enable_frameworks_net_tests,
defaults: [
"framework-connectivity-internal-test-defaults",