Merge "Add version control for packet address translation design" into main

This commit is contained in:
Chiachang Wang
2023-08-03 06:58:28 +00:00
committed by Gerrit Code Review
3 changed files with 65 additions and 6 deletions

View File

@@ -34,6 +34,8 @@ import static android.net.SocketKeepalive.NO_KEEPALIVE;
import static android.net.SocketKeepalive.SUCCESS;
import static android.net.SocketKeepalive.SUCCESS_PAUSED;
import static com.android.net.module.util.FeatureVersions.FEATURE_CLAT_ADDRESS_TRANSLATE;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -59,6 +61,7 @@ import android.util.Pair;
import com.android.connectivity.resources.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import com.android.net.module.util.DeviceConfigUtils;
import com.android.net.module.util.HexDump;
import com.android.net.module.util.IpUtils;
@@ -86,6 +89,9 @@ public class KeepaliveTracker {
public static final String PERMISSION = android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD;
private static final String CONFIG_DISABLE_CLAT_ADDRESS_TRANSLATE =
"disable_clat_address_translate";
/** Keeps track of keepalive requests. */
private final HashMap <NetworkAgentInfo, HashMap<Integer, KeepaliveInfo>> mKeepalives =
new HashMap<> ();
@@ -113,7 +119,7 @@ public class KeepaliveTracker {
}
@VisibleForTesting
KeepaliveTracker(Context context, Handler handler, TcpKeepaliveController tcpController,
public KeepaliveTracker(Context context, Handler handler, TcpKeepaliveController tcpController,
Dependencies deps) {
mTcpController = tcpController;
mContext = context;
@@ -553,6 +559,8 @@ public class KeepaliveTracker {
private KeepaliveInfo handleUpdateKeepaliveForClat(KeepaliveInfo ki)
throws InvalidSocketException, InvalidPacketException {
if (!mDependencies.isAddressTranslationEnabled(mContext)) return ki;
// Translation applies to only NAT-T keepalive
if (ki.mType != KeepaliveInfo.TYPE_NATT) return ki;
// Only try to translate address if the packet source address is the clat's source address.
@@ -973,5 +981,20 @@ public class KeepaliveTracker {
public ConnectivityResources createConnectivityResources(@NonNull Context context) {
return new ConnectivityResources(context);
}
/**
* Return if keepalive address translation with clat feature is supported or not.
*
* This is controlled by both isFeatureSupported() and isFeatureEnabled(). The
* isFeatureSupported() checks whether device contains the minimal required module
* version for FEATURE_CLAT_ADDRESS_TRANSLATE. The isTetheringFeatureForceDisabled()
* checks the DeviceConfig flag that can be updated via DeviceConfig push to control
* the overall feature.
*/
public boolean isAddressTranslationEnabled(@NonNull Context context) {
return DeviceConfigUtils.isFeatureSupported(context, FEATURE_CLAT_ADDRESS_TRANSLATE)
&& !DeviceConfigUtils.isTetheringFeatureForceDisabled(
CONFIG_DISABLE_CLAT_ADDRESS_TRANSLATE);
}
}
}

View File

@@ -402,6 +402,7 @@ import com.android.server.connectivity.CarrierPrivilegeAuthenticator;
import com.android.server.connectivity.ClatCoordinator;
import com.android.server.connectivity.ConnectivityFlags;
import com.android.server.connectivity.ConnectivityResources;
import com.android.server.connectivity.KeepaliveTracker;
import com.android.server.connectivity.MultinetworkPolicyTracker;
import com.android.server.connectivity.MultinetworkPolicyTrackerTestDependencies;
import com.android.server.connectivity.Nat464Xlat;
@@ -410,6 +411,7 @@ import com.android.server.connectivity.NetworkNotificationManager;
import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
import com.android.server.connectivity.ProxyTracker;
import com.android.server.connectivity.QosCallbackTracker;
import com.android.server.connectivity.TcpKeepaliveController;
import com.android.server.connectivity.UidRangeUtils;
import com.android.server.connectivity.Vpn;
import com.android.server.connectivity.VpnProfileStore;
@@ -627,6 +629,7 @@ public class ConnectivityServiceTest {
@Mock ActivityManager mActivityManager;
@Mock DestroySocketsWrapper mDestroySocketsWrapper;
@Mock SubscriptionManager mSubscriptionManager;
@Mock KeepaliveTracker.Dependencies mMockKeepaliveTrackerDependencies;
// BatteryStatsManager is final and cannot be mocked with regular mockito, so just mock the
// underlying binder calls.
@@ -1898,6 +1901,12 @@ public class ConnectivityServiceTest {
doReturn(mResources).when(mockResContext).getResources();
ConnectivityResources.setResourcesContextForTest(mockResContext);
mDeps = new ConnectivityServiceDependencies(mockResContext);
doReturn(true).when(mMockKeepaliveTrackerDependencies)
.isAddressTranslationEnabled(mServiceContext);
doReturn(new ConnectivityResources(mockResContext)).when(mMockKeepaliveTrackerDependencies)
.createConnectivityResources(mServiceContext);
doReturn(new int[] {1, 3, 0, 0}).when(mMockKeepaliveTrackerDependencies)
.getSupportedKeepalives(mServiceContext);
mAutoOnOffKeepaliveDependencies =
new AutomaticOnOffKeepaliveTrackerDependencies(mServiceContext);
mService = new ConnectivityService(mServiceContext,
@@ -2297,6 +2306,12 @@ public class ConnectivityServiceTest {
// Assuming enabled here to focus on ConnectivityService tests.
return true;
}
public KeepaliveTracker newKeepaliveTracker(@NonNull Context context,
@NonNull Handler connectivityserviceHander) {
return new KeepaliveTracker(context, connectivityserviceHander,
new TcpKeepaliveController(connectivityserviceHander),
mMockKeepaliveTrackerDependencies);
}
}
private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {

View File

@@ -78,7 +78,6 @@ import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.connectivity.resources.R;
import com.android.server.connectivity.AutomaticOnOffKeepaliveTracker.AutomaticOnOffKeepalive;
import com.android.server.connectivity.KeepaliveTracker.KeepaliveInfo;
import com.android.testutils.DevSdkIgnoreRule;
@@ -96,6 +95,7 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.io.FileDescriptor;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
@@ -128,7 +128,7 @@ public class AutomaticOnOffKeepaliveTrackerTest {
@Mock AlarmManager mAlarmManager;
@Mock NetworkAgentInfo mNai;
@Mock SubscriptionManager mSubscriptionManager;
@Mock KeepaliveTracker.Dependencies mKeepaliveTrackerDeps;
KeepaliveStatsTracker mKeepaliveStatsTracker;
TestKeepaliveTracker mKeepaliveTracker;
AOOTestHandler mTestHandler;
@@ -267,7 +267,7 @@ public class AutomaticOnOffKeepaliveTrackerTest {
TestKeepaliveTracker(@NonNull final Context context, @NonNull final Handler handler,
@NonNull final TcpKeepaliveController tcpController) {
super(context, handler, tcpController, new Dependencies());
super(context, handler, tcpController, mKeepaliveTrackerDeps);
}
public void setReturnedKeepaliveInfo(@NonNull final KeepaliveInfo ki) {
@@ -336,8 +336,6 @@ public class AutomaticOnOffKeepaliveTrackerTest {
anyInt() /* pid */, anyInt() /* uid */);
ConnectivityResources.setResourcesContextForTest(mCtx);
final Resources mockResources = mock(Resources.class);
doReturn(new String[] { "0,3", "3,3" }).when(mockResources)
.getStringArray(R.array.config_networkSupportedKeepaliveCount);
doReturn(mockResources).when(mCtx).getResources();
doReturn(mNetd).when(mDependencies).getNetd();
doReturn(mAlarmManager).when(mDependencies).getAlarmManager(any());
@@ -345,6 +343,10 @@ public class AutomaticOnOffKeepaliveTrackerTest {
.getFwmarkForNetwork(TEST_NETID);
doNothing().when(mDependencies).sendRequest(any(), any());
doReturn(true).when(mKeepaliveTrackerDeps).isAddressTranslationEnabled(mCtx);
doReturn(new ConnectivityResources(mCtx)).when(mKeepaliveTrackerDeps)
.createConnectivityResources(mCtx);
doReturn(new int[] {3, 0, 0, 3}).when(mKeepaliveTrackerDeps).getSupportedKeepalives(mCtx);
mHandlerThread = new HandlerThread("KeepaliveTrackerTest");
mHandlerThread.start();
@@ -658,6 +660,25 @@ public class AutomaticOnOffKeepaliveTrackerTest {
assertEquals(srcAddr, tpd.getSrcAddress());
}
@Test
public void testStartNattKeepalive_addressTranslationOnClatNotSupported() throws Exception {
// Disable address translation feature and verify the behavior
doReturn(false).when(mKeepaliveTrackerDeps).isAddressTranslationEnabled(mCtx);
setupTestNaiForClat(InetAddresses.parseNumericAddress("2001:db8::1"),
InetAddresses.parseNumericAddress("2001:db8::2"));
doStartNattKeepalive();
final ArgumentCaptor<NattKeepalivePacketData> kpdCaptor =
ArgumentCaptor.forClass(NattKeepalivePacketData.class);
verify(mNai).onStartNattSocketKeepalive(
eq(TEST_SLOT), eq(TEST_KEEPALIVE_INTERVAL_SEC), kpdCaptor.capture());
// Verify that address translation is not triggered so the addresses are still v4.
final NattKeepalivePacketData kpd = kpdCaptor.getValue();
assertTrue(kpd.getSrcAddress() instanceof Inet4Address);
assertTrue(kpd.getDstAddress() instanceof Inet4Address);
}
@Test
public void testStartNattKeepalive_addressTranslationOnClat() throws Exception {
final InetAddress v6AddrSrc = InetAddresses.parseNumericAddress("2001:db8::1");