summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChiachang Wang <chiachangwang@google.com>2019-12-19 00:55:42 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2019-12-19 00:55:42 +0000
commitd75a722ebd83d9f5ee0e7194a04343980424a2bc (patch)
tree9545749b2450755895b30e5a3eb6cccb37d6cc43 /src
parentd035d367a91cb8ad94d1af4d9851c4f573f5ed8b (diff)
parentcded6ce35fc3f86ad1e9a6c699492ac1afcd45e5 (diff)
Merge "Evaluate tcp only on target network"
Diffstat (limited to 'src')
-rw-r--r--src/com/android/networkstack/netlink/TcpSocketTracker.java53
-rw-r--r--src/com/android/server/connectivity/NetworkMonitor.java7
2 files changed, 53 insertions, 7 deletions
diff --git a/src/com/android/networkstack/netlink/TcpSocketTracker.java b/src/com/android/networkstack/netlink/TcpSocketTracker.java
index 8f24aec..8929cdb 100644
--- a/src/com/android/networkstack/netlink/TcpSocketTracker.java
+++ b/src/com/android/networkstack/netlink/TcpSocketTracker.java
@@ -39,6 +39,9 @@ import static android.system.OsConstants.SOL_SOCKET;
import static android.system.OsConstants.SO_SNDTIMEO;
import android.content.Context;
+import android.net.INetd;
+import android.net.MarkMaskParcel;
+import android.net.Network;
import android.net.netlink.NetlinkConstants;
import android.net.netlink.NetlinkSocket;
import android.net.netlink.StructInetDiagMsg;
@@ -46,6 +49,8 @@ import android.net.netlink.StructNlMsgHdr;
import android.net.util.NetworkStackUtils;
import android.net.util.SocketUtils;
import android.os.AsyncTask;
+import android.os.IBinder;
+import android.os.RemoteException;
import android.os.SystemClock;
import android.provider.DeviceConfig;
import android.system.ErrnoException;
@@ -59,6 +64,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.networkstack.apishim.NetworkShimImpl;
+import com.android.networkstack.apishim.UnsupportedApiLevelException;
import java.io.FileDescriptor;
import java.io.InterruptedIOException;
@@ -84,6 +91,8 @@ public class TcpSocketTracker {
private static final long IO_TIMEOUT = 3_000L;
/** Cookie offset of an InetMagMessage header. */
private static final int IDIAG_COOKIE_OFFSET = 44;
+ private static final int UNKNOWN_MARK = 0xffffffff;
+ private static final int NULL_MASK = 0;
/**
* Gather the socket info.
*
@@ -106,6 +115,12 @@ public class TcpSocketTracker {
*/
private final SparseArray<byte[]> mSockDiagMsg = new SparseArray<>();
private final Dependencies mDependencies;
+ private final INetd mNetd;
+ private final Network mNetwork;
+ // The fwmark value of {@code mNetwork}.
+ private final int mNetworkMark;
+ // The network id mask of fwmark.
+ private final int mNetworkMask;
private int mMinPacketsThreshold = DEFAULT_DATA_STALL_MIN_PACKETS_THRESHOLD;
private int mTcpPacketsFailRateThreshold = DEFAULT_TCP_PACKETS_FAIL_PERCENTAGE;
@VisibleForTesting
@@ -124,8 +139,17 @@ public class TcpSocketTracker {
}
};
- public TcpSocketTracker(@NonNull final Dependencies dps) {
+ public TcpSocketTracker(@NonNull final Dependencies dps, @NonNull final Network network) {
mDependencies = dps;
+ mNetwork = network;
+ mNetd = mDependencies.getNetd();
+
+ // If the parcel is null, nothing should be matched which is achieved by the combination of
+ // {@code NULL_MASK} and {@code UNKNOWN_MARK}.
+ final MarkMaskParcel parcel = getNetworkMarkMask();
+ mNetworkMark = (parcel != null) ? parcel.mark : UNKNOWN_MARK;
+ mNetworkMask = (parcel != null) ? parcel.mask : NULL_MASK;
+
// Request tcp info from NetworkStack directly needs extra SELinux permission added after Q
// release.
if (!mDependencies.isTcpInfoParsingSupported()) return;
@@ -145,12 +169,24 @@ public class TcpSocketTracker {
mDependencies.addDeviceConfigChangedListener(mConfigListener);
}
+ @Nullable
+ private MarkMaskParcel getNetworkMarkMask() {
+ try {
+ final int netId = NetworkShimImpl.newInstance(mNetwork).getNetId();
+ return mNetd.getFwmarkForNetwork(netId);
+ } catch (UnsupportedApiLevelException e) {
+ log("Get netId is not available in this API level.");
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error getting fwmark for network, ", e);
+ }
+ return null;
+ }
+
/**
* Request to send a SockDiag Netlink request. Receive and parse the returned message. This
* function is not thread-safe and should only be called from only one thread.
*
* @Return if this polling request executes successfully or not.
- * TODO: Need to filter socket info based on the target network.
*/
public boolean pollSocketsInfo() {
if (!mDependencies.isTcpInfoParsingSupported()) return false;
@@ -294,6 +330,10 @@ public class TcpSocketTracker {
private TcpStat calculateLatestPacketsStat(@NonNull final SocketInfo current,
@Nullable final SocketInfo previous) {
final TcpStat stat = new TcpStat();
+ // Ignore non-target network sockets.
+ if ((current.fwmark & mNetworkMask) != mNetworkMark) {
+ return null;
+ }
if (current.tcpInfo == null) {
log("Current tcpInfo is null.");
@@ -428,7 +468,6 @@ public class TcpSocketTracker {
// One of {@code AF_INET6, AF_INET}.
public final int ipFamily;
// "fwmark" value of the socket queried from native.
- // TODO: Used to do bit-wise '&' operation to get netId information.
public final int fwmark;
// Socket information updated elapsed real time.
public final long updateTime;
@@ -554,6 +593,14 @@ public class TcpSocketTracker {
return mContext;
}
+ /**
+ * Get an INetd connector.
+ */
+ public INetd getNetd() {
+ return INetd.Stub.asInterface(
+ (IBinder) mContext.getSystemService(Context.NETD_SERVICE));
+ }
+
/** Add device config change listener */
public void addDeviceConfigChangedListener(
@NonNull final DeviceConfig.OnPropertiesChangedListener listener) {
diff --git a/src/com/android/server/connectivity/NetworkMonitor.java b/src/com/android/server/connectivity/NetworkMonitor.java
index 9b6915c..f950b47 100644
--- a/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/src/com/android/server/connectivity/NetworkMonitor.java
@@ -405,7 +405,7 @@ public class NetworkMonitor extends StateMachine {
SharedLog validationLog) {
this(context, cb, network, new IpConnectivityLog(), validationLog,
Dependencies.DEFAULT, new DataStallStatsUtils(),
- getTcpSocketTrackerOrNull(context));
+ getTcpSocketTrackerOrNull(context, network));
}
@VisibleForTesting
@@ -2240,7 +2240,6 @@ public class NetworkMonitor extends StateMachine {
// Check TCP signal. Suspect it may be a data stall if :
// 1. TCP connection fail rate(lost+retrans) is higher than threshold.
// 2. Accumulate enough packets count.
- // TODO: Need to filter per target network.
final TcpSocketTracker tst = getTcpSocketTracker();
if (dataStallEvaluateTypeEnabled(DATA_STALL_EVALUATION_TYPE_TCP) && tst != null) {
if (tst.getLatestReceivedCount() > 0) {
@@ -2406,14 +2405,14 @@ public class NetworkMonitor extends StateMachine {
}
@Nullable
- private static TcpSocketTracker getTcpSocketTrackerOrNull(Context context) {
+ private static TcpSocketTracker getTcpSocketTrackerOrNull(Context context, Network network) {
return ((Dependencies.DEFAULT.getDeviceConfigPropertyInt(
NAMESPACE_CONNECTIVITY,
CONFIG_DATA_STALL_EVALUATION_TYPE,
DEFAULT_DATA_STALL_EVALUATION_TYPES)
& DATA_STALL_EVALUATION_TYPE_TCP) != 0)
? new TcpSocketTracker(new TcpSocketTracker.Dependencies(context,
- ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q)))
+ ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q)), network)
: null;
}
}