Merge "ethernet: replace netd link observer with NetlinkMonitor"
diff --git a/bpf_progs/bpf_tethering.h b/bpf_progs/bpf_tethering.h
index f9ef6ef..9dae6c9 100644
--- a/bpf_progs/bpf_tethering.h
+++ b/bpf_progs/bpf_tethering.h
@@ -26,31 +26,33 @@
// - The BPF programs in Tethering/bpf_progs/
// - JNI code that depends on the bpf_connectivity_headers library.
-#define BPF_TETHER_ERRORS \
- ERR(INVALID_IP_VERSION) \
- ERR(LOW_TTL) \
- ERR(INVALID_TCP_HEADER) \
- ERR(TCP_CONTROL_PACKET) \
- ERR(NON_GLOBAL_SRC) \
- ERR(NON_GLOBAL_DST) \
- ERR(LOCAL_SRC_DST) \
- ERR(NO_STATS_ENTRY) \
- ERR(NO_LIMIT_ENTRY) \
- ERR(BELOW_IPV4_MTU) \
- ERR(BELOW_IPV6_MTU) \
- ERR(LIMIT_REACHED) \
- ERR(CHANGE_HEAD_FAILED) \
- ERR(TOO_SHORT) \
- ERR(HAS_IP_OPTIONS) \
- ERR(IS_IP_FRAG) \
- ERR(CHECKSUM) \
- ERR(NON_TCP_UDP) \
- ERR(NON_TCP) \
- ERR(SHORT_L4_HEADER) \
- ERR(SHORT_TCP_HEADER) \
- ERR(SHORT_UDP_HEADER) \
- ERR(UDP_CSUM_ZERO) \
- ERR(TRUNCATED_IPV4) \
+#define BPF_TETHER_ERRORS \
+ ERR(INVALID_IPV4_VERSION) \
+ ERR(INVALID_IPV6_VERSION) \
+ ERR(LOW_TTL) \
+ ERR(INVALID_TCP_HEADER) \
+ ERR(TCPV4_CONTROL_PACKET) \
+ ERR(TCPV6_CONTROL_PACKET) \
+ ERR(NON_GLOBAL_SRC) \
+ ERR(NON_GLOBAL_DST) \
+ ERR(LOCAL_SRC_DST) \
+ ERR(NO_STATS_ENTRY) \
+ ERR(NO_LIMIT_ENTRY) \
+ ERR(BELOW_IPV4_MTU) \
+ ERR(BELOW_IPV6_MTU) \
+ ERR(LIMIT_REACHED) \
+ ERR(CHANGE_HEAD_FAILED) \
+ ERR(TOO_SHORT) \
+ ERR(HAS_IP_OPTIONS) \
+ ERR(IS_IP_FRAG) \
+ ERR(CHECKSUM) \
+ ERR(NON_TCP_UDP) \
+ ERR(NON_TCP) \
+ ERR(SHORT_L4_HEADER) \
+ ERR(SHORT_TCP_HEADER) \
+ ERR(SHORT_UDP_HEADER) \
+ ERR(UDP_CSUM_ZERO) \
+ ERR(TRUNCATED_IPV4) \
ERR(_MAX)
#define ERR(x) BPF_TETHER_ERR_ ##x,
diff --git a/bpf_progs/offload.c b/bpf_progs/offload.c
index 898f2e2..bb9fc34 100644
--- a/bpf_progs/offload.c
+++ b/bpf_progs/offload.c
@@ -155,7 +155,7 @@
if (is_ethernet && (eth->h_proto != htons(ETH_P_IPV6))) return TC_ACT_PIPE;
// IP version must be 6
- if (ip6->version != 6) TC_PUNT(INVALID_IP_VERSION);
+ if (ip6->version != 6) TC_PUNT(INVALID_IPV6_VERSION);
// Cannot decrement during forward if already zero or would be zero,
// Let the kernel's stack handle these cases and generate appropriate ICMP errors.
@@ -171,7 +171,7 @@
TC_PUNT(INVALID_TCP_HEADER);
// Do not offload TCP packets with any one of the SYN/FIN/RST flags
- if (tcph->syn || tcph->fin || tcph->rst) TC_PUNT(TCP_CONTROL_PACKET);
+ if (tcph->syn || tcph->fin || tcph->rst) TC_PUNT(TCPV6_CONTROL_PACKET);
}
// Protect against forwarding packets sourced from ::1 or fe80::/64 or other weirdness.
@@ -370,7 +370,7 @@
// If hardware offload is running and programming flows based on conntrack entries, try not
// to interfere with it, so do not offload TCP packets with any one of the SYN/FIN/RST flags
- if (tcph->syn || tcph->fin || tcph->rst) TC_PUNT(TCP_CONTROL_PACKET);
+ if (tcph->syn || tcph->fin || tcph->rst) TC_PUNT(TCPV4_CONTROL_PACKET);
} else { // UDP
// Make sure we can get at the udp header
if (data + l2_header_size + sizeof(*ip) + sizeof(*udph) > data_end)
@@ -576,7 +576,7 @@
if (is_ethernet && (eth->h_proto != htons(ETH_P_IP))) return TC_ACT_PIPE;
// IP version must be 4
- if (ip->version != 4) TC_PUNT(INVALID_IP_VERSION);
+ if (ip->version != 4) TC_PUNT(INVALID_IPV4_VERSION);
// We cannot handle IP options, just standard 20 byte == 5 dword minimal IPv4 header
if (ip->ihl != 5) TC_PUNT(HAS_IP_OPTIONS);
diff --git a/service-t/jni/com_android_server_net_NetworkStatsFactory.cpp b/service-t/jni/com_android_server_net_NetworkStatsFactory.cpp
index 8b6526f..a3299a7 100644
--- a/service-t/jni/com_android_server_net_NetworkStatsFactory.cpp
+++ b/service-t/jni/com_android_server_net_NetworkStatsFactory.cpp
@@ -93,118 +93,6 @@
return env->NewLongArray(size);
}
-static int legacyReadNetworkStatsDetail(std::vector<stats_line>* lines,
- const std::vector<std::string>& limitIfaces,
- int limitTag, int limitUid, const char* path) {
- FILE* fp = fopen(path, "re");
- if (fp == NULL) {
- return -1;
- }
-
- int lastIdx = 1;
- int idx;
- char buffer[384];
- while (fgets(buffer, sizeof(buffer), fp) != NULL) {
- stats_line s;
- int64_t rawTag;
- char* pos = buffer;
- char* endPos;
- // First field is the index.
- idx = (int)strtol(pos, &endPos, 10);
- //ALOGI("Index #%d: %s", idx, buffer);
- if (pos == endPos) {
- // Skip lines that don't start with in index. In particular,
- // this will skip the initial header line.
- continue;
- }
- if (idx != lastIdx + 1) {
- ALOGE("inconsistent idx=%d after lastIdx=%d: %s", idx, lastIdx, buffer);
- fclose(fp);
- return -1;
- }
- lastIdx = idx;
- pos = endPos;
- // Skip whitespace.
- while (*pos == ' ') {
- pos++;
- }
- // Next field is iface.
- int ifaceIdx = 0;
- while (*pos != ' ' && *pos != 0 && ifaceIdx < (int)(sizeof(s.iface)-1)) {
- s.iface[ifaceIdx] = *pos;
- ifaceIdx++;
- pos++;
- }
- if (*pos != ' ') {
- ALOGE("bad iface: %s", buffer);
- fclose(fp);
- return -1;
- }
- s.iface[ifaceIdx] = 0;
- if (limitIfaces.size() > 0) {
- // Is this an iface the caller is interested in?
- int i = 0;
- while (i < (int)limitIfaces.size()) {
- if (limitIfaces[i] == s.iface) {
- break;
- }
- i++;
- }
- if (i >= (int)limitIfaces.size()) {
- // Nothing matched; skip this line.
- //ALOGI("skipping due to iface: %s", buffer);
- continue;
- }
- }
-
- // Ignore whitespace
- while (*pos == ' ') pos++;
-
- // Find end of tag field
- endPos = pos;
- while (*endPos != ' ') endPos++;
-
- // Three digit field is always 0x0, otherwise parse
- if (endPos - pos == 3) {
- rawTag = 0;
- } else {
- if (sscanf(pos, "%" PRIx64, &rawTag) != 1) {
- ALOGE("bad tag: %s", pos);
- fclose(fp);
- return -1;
- }
- }
- s.tag = rawTag >> 32;
- if (limitTag != -1 && s.tag != static_cast<uint32_t>(limitTag)) {
- //ALOGI("skipping due to tag: %s", buffer);
- continue;
- }
- pos = endPos;
-
- // Ignore whitespace
- while (*pos == ' ') pos++;
-
- // Parse remaining fields.
- if (sscanf(pos, "%u %u %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64,
- &s.uid, &s.set, &s.rxBytes, &s.rxPackets,
- &s.txBytes, &s.txPackets) == 6) {
- if (limitUid != -1 && static_cast<uint32_t>(limitUid) != s.uid) {
- //ALOGI("skipping due to uid: %s", buffer);
- continue;
- }
- lines->push_back(s);
- } else {
- //ALOGI("skipping due to bad remaining fields: %s", pos);
- }
- }
-
- if (fclose(fp) != 0) {
- ALOGE("Failed to close netstats file");
- return -1;
- }
- return 0;
-}
-
static int statsLinesToNetworkStats(JNIEnv* env, jclass clazz, jobject stats,
std::vector<stats_line>& lines) {
int size = lines.size();
@@ -282,9 +170,8 @@
return 0;
}
-static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstring path,
- jint limitUid, jobjectArray limitIfacesObj, jint limitTag,
- jboolean useBpfStats) {
+static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jint limitUid,
+ jobjectArray limitIfacesObj, jint limitTag) {
std::vector<std::string> limitIfaces;
if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) {
@@ -299,20 +186,8 @@
}
std::vector<stats_line> lines;
-
- if (useBpfStats) {
- if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0)
- return -1;
- } else {
- ScopedUtfChars path8(env, path);
- if (path8.c_str() == NULL) {
- ALOGE("the qtaguid legacy path is invalid: %s", path8.c_str());
- return -1;
- }
- if (legacyReadNetworkStatsDetail(&lines, limitIfaces, limitTag,
- limitUid, path8.c_str()) < 0)
- return -1;
- }
+ if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0)
+ return -1;
return statsLinesToNetworkStats(env, clazz, stats, lines);
}
@@ -328,7 +203,7 @@
static const JNINativeMethod gMethods[] = {
{ "nativeReadNetworkStatsDetail",
- "(Landroid/net/NetworkStats;Ljava/lang/String;I[Ljava/lang/String;IZ)I",
+ "(Landroid/net/NetworkStats;I[Ljava/lang/String;I)I",
(void*) readNetworkStatsDetail },
{ "nativeReadNetworkStatsDev", "(Landroid/net/NetworkStats;)I",
(void*) readNetworkStatsDev },
diff --git a/service-t/src/com/android/server/net/NetworkStatsFactory.java b/service-t/src/com/android/server/net/NetworkStatsFactory.java
index 4a6741c..c9d1718 100644
--- a/service-t/src/com/android/server/net/NetworkStatsFactory.java
+++ b/service-t/src/com/android/server/net/NetworkStatsFactory.java
@@ -91,8 +91,7 @@
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 0);
// TODO: remove both path and useBpfStats arguments.
// The path is never used if useBpfStats is true.
- final int ret = nativeReadNetworkStatsDetail(stats, null /* path */,
- limitUid, limitIfaces, limitTag, true /* useBpfStats */);
+ final int ret = nativeReadNetworkStatsDetail(stats, limitUid, limitIfaces, limitTag);
if (ret != 0) {
throw new IOException("Failed to parse network stats");
}
@@ -334,8 +333,8 @@
* are expected to monotonically increase since device boot.
*/
@VisibleForTesting
- public static native int nativeReadNetworkStatsDetail(NetworkStats stats, String path,
- int limitUid, String[] limitIfaces, int limitTag, boolean useBpfStats);
+ public static native int nativeReadNetworkStatsDetail(NetworkStats stats, int limitUid,
+ String[] limitIfaces, int limitTag);
@VisibleForTesting
public static native int nativeReadNetworkStatsDev(NetworkStats stats);
diff --git a/service/Android.bp b/service/Android.bp
index 1e70d68..b68d389 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -143,8 +143,6 @@
"src/**/*.java",
":framework-connectivity-shared-srcs",
":services-connectivity-shared-srcs",
- // TODO: move to net-utils-device-common
- ":connectivity-module-utils-srcs",
],
libs: [
"framework-annotations-lib",
diff --git a/service/native/TrafficController.cpp b/service/native/TrafficController.cpp
index 303112f..a26d1e6 100644
--- a/service/native/TrafficController.cpp
+++ b/service/native/TrafficController.cpp
@@ -572,17 +572,6 @@
}
}
-std::string getProgramStatus(const char *path) {
- int ret = access(path, R_OK);
- if (ret == 0) {
- return StringPrintf("OK");
- }
- if (ret != 0 && errno == ENOENT) {
- return StringPrintf("program is missing at: %s", path);
- }
- return StringPrintf("check Program %s error: %s", path, strerror(errno));
-}
-
std::string getMapStatus(const base::unique_fd& map_fd, const char* path) {
if (map_fd.get() < 0) {
return StringPrintf("map fd lost");
@@ -614,6 +603,10 @@
dw.blankline();
dw.println("mCookieTagMap status: %s",
getMapStatus(mCookieTagMap.getMap(), COOKIE_TAG_MAP_PATH).c_str());
+ dw.println("mUidCounterSetMap status: %s",
+ getMapStatus(mUidCounterSetMap.getMap(), UID_COUNTERSET_MAP_PATH).c_str());
+ dw.println("mAppUidStatsMap status: %s",
+ getMapStatus(mAppUidStatsMap.getMap(), APP_UID_STATS_MAP_PATH).c_str());
dw.println("mStatsMapA status: %s",
getMapStatus(mStatsMapA.getMap(), STATS_MAP_A_PATH).c_str());
dw.println("mStatsMapB status: %s",
@@ -627,19 +620,6 @@
dw.println("mUidOwnerMap status: %s",
getMapStatus(mUidOwnerMap.getMap(), UID_OWNER_MAP_PATH).c_str());
- dw.blankline();
- dw.println("Cgroup ingress program status: %s",
- getProgramStatus(BPF_INGRESS_PROG_PATH).c_str());
- dw.println("Cgroup egress program status: %s", getProgramStatus(BPF_EGRESS_PROG_PATH).c_str());
- dw.println("xt_bpf ingress program status: %s",
- getProgramStatus(XT_BPF_INGRESS_PROG_PATH).c_str());
- dw.println("xt_bpf egress program status: %s",
- getProgramStatus(XT_BPF_EGRESS_PROG_PATH).c_str());
- dw.println("xt_bpf bandwidth allowlist program status: %s",
- getProgramStatus(XT_BPF_ALLOWLIST_PROG_PATH).c_str());
- dw.println("xt_bpf bandwidth denylist program status: %s",
- getProgramStatus(XT_BPF_DENYLIST_PROG_PATH).c_str());
-
if (!verbose) {
return;
}
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 0ca0d83..1caca01 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -89,7 +89,6 @@
import static android.net.NetworkScore.POLICY_TRANSPORT_PRIMARY;
import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST;
import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_ONLY;
-import static android.net.shared.NetworkMonitorUtils.isPrivateDnsValidationRequired;
import static android.os.Process.INVALID_UID;
import static android.os.Process.VPN_UID;
import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
@@ -98,6 +97,7 @@
import static android.system.OsConstants.IPPROTO_UDP;
import static com.android.net.module.util.DeviceConfigUtils.TETHERING_MODULE_NAME;
+import static com.android.net.module.util.NetworkMonitorUtils.isPrivateDnsValidationRequired;
import static com.android.net.module.util.PermissionUtils.enforceAnyPermissionOf;
import static com.android.net.module.util.PermissionUtils.enforceNetworkStackPermission;
import static com.android.net.module.util.PermissionUtils.enforceNetworkStackPermissionOr;
@@ -1220,16 +1220,7 @@
public void incrementCountOrThrow(final int uid) {
synchronized (mUidToNetworkRequestCount) {
final int newRequestCount = mUidToNetworkRequestCount.get(uid, 0) + 1;
- if (newRequestCount >= mMaxCountPerUid
- // HACK : the system server is allowed to go over the request count limit
- // when it is creating requests on behalf of another app (but not itself,
- // so it can still detect its own request leaks). This only happens in the
- // per-app API flows in which case the old requests for that particular
- // UID will be removed soon.
- // TODO : with the removal of the legacy transact() method, exempting the
- // system server UID should no longer be necessary. Make sure this is the
- // case and remove this test.
- && (Process.myUid() == uid || Process.myUid() != Binder.getCallingUid())) {
+ if (newRequestCount >= mMaxCountPerUid) {
throw new ServiceSpecificException(
ConnectivityManager.Errors.TOO_MANY_REQUESTS,
"Uid " + uid + " exceeded its allotted requests limit");
@@ -10856,6 +10847,7 @@
removeDefaultNetworkRequestsForPreference(PREFERENCE_ORDER_PROFILE);
addPerAppDefaultNetworkRequests(
createNrisFromProfileNetworkPreferences(mProfileNetworkPreferences));
+
// Finally, rematch.
rematchAllNetworksAndRequests();
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 06f7300..f8e70c4 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -300,7 +300,6 @@
import android.net.networkstack.NetworkStackClientBase;
import android.net.resolv.aidl.Nat64PrefixEventParcel;
import android.net.resolv.aidl.PrivateDnsValidationEventParcel;
-import android.net.shared.NetworkMonitorUtils;
import android.net.shared.PrivateDnsConfig;
import android.net.util.MultinetworkPolicyTracker;
import android.net.wifi.WifiInfo;
@@ -356,6 +355,7 @@
import com.android.net.module.util.ArrayTrackRecord;
import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.LocationPermissionChecker;
+import com.android.net.module.util.NetworkMonitorUtils;
import com.android.networkstack.apishim.NetworkAgentConfigShimImpl;
import com.android.networkstack.apishim.api29.ConstantsShim;
import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo;
@@ -2989,8 +2989,7 @@
@Test
public void testRequiresValidation() {
- assertTrue(NetworkMonitorUtils.isValidationRequired(
- NetworkAgentConfigShimImpl.newInstance(null),
+ assertTrue(NetworkMonitorUtils.isValidationRequired(false /* isVpnValidationRequired */,
mCm.getDefaultRequest().networkCapabilities));
}
@@ -7980,7 +7979,8 @@
// VPN networks do not satisfy the default request and are automatically validated
// by NetworkMonitor
assertFalse(NetworkMonitorUtils.isValidationRequired(
- NetworkAgentConfigShimImpl.newInstance(mMockVpn.getNetworkAgentConfig()),
+ NetworkAgentConfigShimImpl.newInstance(mMockVpn.getNetworkAgentConfig())
+ .isVpnValidationRequired(),
mMockVpn.getAgent().getNetworkCapabilities()));
mMockVpn.getAgent().setNetworkValid(false /* isStrictMode */);
@@ -8131,7 +8131,8 @@
assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
assertFalse(NetworkMonitorUtils.isValidationRequired(
- NetworkAgentConfigShimImpl.newInstance(mMockVpn.getNetworkAgentConfig()),
+ NetworkAgentConfigShimImpl.newInstance(mMockVpn.getNetworkAgentConfig())
+ .isVpnValidationRequired(),
mMockVpn.getAgent().getNetworkCapabilities()));
assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
mMockVpn.getAgent().getNetworkCapabilities()));