Switch SkDestroyListener based on the flag.
Switch existing C SkDestroyListener and new Java SkDestroyListener based on the experiment flag. Bug: 217624062 Test: atest SkDestroyListenerTest Change-Id: I7031ba7c155edb43e0e7b77449587058d6ba38fb
This commit is contained in:
@@ -162,11 +162,13 @@ import com.android.net.module.util.IBpfMap;
|
||||
import com.android.net.module.util.LocationPermissionChecker;
|
||||
import com.android.net.module.util.NetworkStatsUtils;
|
||||
import com.android.net.module.util.PermissionUtils;
|
||||
import com.android.net.module.util.SharedLog;
|
||||
import com.android.net.module.util.Struct;
|
||||
import com.android.net.module.util.Struct.U32;
|
||||
import com.android.net.module.util.Struct.U8;
|
||||
import com.android.net.module.util.bpf.CookieTagMapKey;
|
||||
import com.android.net.module.util.bpf.CookieTagMapValue;
|
||||
import com.android.server.BpfNetMaps;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
@@ -454,6 +456,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
@NonNull
|
||||
private final BpfInterfaceMapUpdater mInterfaceMapUpdater;
|
||||
|
||||
@Nullable
|
||||
private final SkDestroyListener mSkDestroyListener;
|
||||
|
||||
private static @NonNull Clock getDefaultClock() {
|
||||
return new BestClock(ZoneOffset.UTC, SystemClock.currentNetworkTimeClock(),
|
||||
Clock.systemUTC());
|
||||
@@ -587,6 +592,18 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
mStatsMapA = mDeps.getStatsMapA();
|
||||
mStatsMapB = mDeps.getStatsMapB();
|
||||
mAppUidStatsMap = mDeps.getAppUidStatsMap();
|
||||
|
||||
// TODO: Remove bpfNetMaps creation and always start SkDestroyListener
|
||||
// Following code is for the experiment to verify the SkDestroyListener refactoring. Based
|
||||
// on the experiment flag, BpfNetMaps starts C SkDestroyListener (existing code) or
|
||||
// NetworkStatsService starts Java SkDestroyListener (new code).
|
||||
final BpfNetMaps bpfNetMaps = mDeps.makeBpfNetMaps(mContext);
|
||||
if (bpfNetMaps.isSkDestroyListenerRunning()) {
|
||||
mSkDestroyListener = null;
|
||||
} else {
|
||||
mSkDestroyListener = mDeps.makeSkDestroyListener(mCookieTagMap, mHandler);
|
||||
mHandler.post(mSkDestroyListener::start);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -782,6 +799,17 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
public boolean isDebuggable() {
|
||||
return Build.isDebuggable();
|
||||
}
|
||||
|
||||
/** Create a new BpfNetMaps. */
|
||||
public BpfNetMaps makeBpfNetMaps(Context ctx) {
|
||||
return new BpfNetMaps(ctx);
|
||||
}
|
||||
|
||||
/** Create a new SkDestroyListener. */
|
||||
public SkDestroyListener makeSkDestroyListener(
|
||||
IBpfMap<CookieTagMapKey, CookieTagMapValue> cookieTagMap, Handler handler) {
|
||||
return new SkDestroyListener(cookieTagMap, handler, new SharedLog(TAG));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
75
service-t/src/com/android/server/net/SkDestroyListener.java
Normal file
75
service-t/src/com/android/server/net/SkDestroyListener.java
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.net;
|
||||
|
||||
import static android.system.OsConstants.NETLINK_INET_DIAG;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.system.ErrnoException;
|
||||
|
||||
import com.android.net.module.util.IBpfMap;
|
||||
import com.android.net.module.util.SharedLog;
|
||||
import com.android.net.module.util.bpf.CookieTagMapKey;
|
||||
import com.android.net.module.util.bpf.CookieTagMapValue;
|
||||
import com.android.net.module.util.ip.NetlinkMonitor;
|
||||
import com.android.net.module.util.netlink.InetDiagMessage;
|
||||
import com.android.net.module.util.netlink.NetlinkMessage;
|
||||
import com.android.net.module.util.netlink.StructInetDiagSockId;
|
||||
|
||||
/**
|
||||
* Monitor socket destroy and delete entry from cookie tag bpf map.
|
||||
*/
|
||||
public class SkDestroyListener extends NetlinkMonitor {
|
||||
private static final int SKNLGRP_INET_TCP_DESTROY = 1;
|
||||
private static final int SKNLGRP_INET_UDP_DESTROY = 2;
|
||||
private static final int SKNLGRP_INET6_TCP_DESTROY = 3;
|
||||
private static final int SKNLGRP_INET6_UDP_DESTROY = 4;
|
||||
|
||||
// TODO: if too many sockets are closed too quickly, this can overflow the socket buffer, and
|
||||
// some entries in mCookieTagMap will not be freed. In order to fix this it would be needed to
|
||||
// periodically dump all sockets and remove the tag entries for sockets that have been closed.
|
||||
// For now, set a large-enough buffer that hundreds of sockets can be closed without getting
|
||||
// ENOBUFS and leaking mCookieTagMap entries.
|
||||
private static final int SOCK_RCV_BUF_SIZE = 512 * 1024;
|
||||
|
||||
private final IBpfMap<CookieTagMapKey, CookieTagMapValue> mCookieTagMap;
|
||||
|
||||
SkDestroyListener(final IBpfMap<CookieTagMapKey, CookieTagMapValue> cookieTagMap,
|
||||
final Handler handler, final SharedLog log) {
|
||||
super(handler, log, "SkDestroyListener", NETLINK_INET_DIAG,
|
||||
1 << (SKNLGRP_INET_TCP_DESTROY - 1)
|
||||
| 1 << (SKNLGRP_INET_UDP_DESTROY - 1)
|
||||
| 1 << (SKNLGRP_INET6_TCP_DESTROY - 1)
|
||||
| 1 << (SKNLGRP_INET6_UDP_DESTROY - 1),
|
||||
SOCK_RCV_BUF_SIZE);
|
||||
mCookieTagMap = cookieTagMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNetlinkMessage(final NetlinkMessage nlMsg, final long whenMs) {
|
||||
if (!(nlMsg instanceof InetDiagMessage)) {
|
||||
mLog.e("Received non InetDiagMessage");
|
||||
return;
|
||||
}
|
||||
final StructInetDiagSockId sockId = ((InetDiagMessage) nlMsg).inetDiagMsg.id;
|
||||
try {
|
||||
mCookieTagMap.deleteEntry(new CookieTagMapKey(sockId.cookie));
|
||||
} catch (ErrnoException e) {
|
||||
mLog.e("Failed to delete CookieTagMap entry for " + sockId.cookie + ": " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,10 +225,14 @@ public class BpfNetMaps {
|
||||
Log.d(TAG, "BpfNetMaps is initialized with sEnableJavaBpfMap=" + sEnableJavaBpfMap);
|
||||
|
||||
initBpfMaps();
|
||||
native_init(true /* startSkDestroyListener */);
|
||||
native_init(!sEnableJavaBpfMap /* startSkDestroyListener */);
|
||||
sInitialized = true;
|
||||
}
|
||||
|
||||
public boolean isSkDestroyListenerRunning() {
|
||||
return !sEnableJavaBpfMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dependencies of BpfNetMaps, for injection in tests.
|
||||
*/
|
||||
|
||||
@@ -143,6 +143,7 @@ import com.android.net.module.util.Struct.U32;
|
||||
import com.android.net.module.util.Struct.U8;
|
||||
import com.android.net.module.util.bpf.CookieTagMapKey;
|
||||
import com.android.net.module.util.bpf.CookieTagMapValue;
|
||||
import com.android.server.BpfNetMaps;
|
||||
import com.android.server.net.NetworkStatsService.AlertObserver;
|
||||
import com.android.server.net.NetworkStatsService.NetworkStatsSettings;
|
||||
import com.android.server.net.NetworkStatsService.NetworkStatsSettings.Config;
|
||||
@@ -248,6 +249,10 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
|
||||
@Mock
|
||||
private LocationPermissionChecker mLocationPermissionChecker;
|
||||
private TestBpfMap<U32, U8> mUidCounterSetMap = spy(new TestBpfMap<>(U32.class, U8.class));
|
||||
@Mock
|
||||
private BpfNetMaps mBpfNetMaps;
|
||||
@Mock
|
||||
private SkDestroyListener mSkDestroyListener;
|
||||
|
||||
private TestBpfMap<CookieTagMapKey, CookieTagMapValue> mCookieTagMap = new TestBpfMap<>(
|
||||
CookieTagMapKey.class, CookieTagMapValue.class);
|
||||
@@ -500,6 +505,17 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
|
||||
public boolean isDebuggable() {
|
||||
return mIsDebuggable == Boolean.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BpfNetMaps makeBpfNetMaps(Context ctx) {
|
||||
return mBpfNetMaps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkDestroyListener makeSkDestroyListener(
|
||||
IBpfMap<CookieTagMapKey, CookieTagMapValue> cookieTagMap, Handler handler) {
|
||||
return mSkDestroyListener;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user