Add version control for packet address translation design
This commit adds the version control for keepalive packet address translation design to prevent device crash if the network stack is not updated to a newer version. This commit also adds a DeviceConfig to control the design in newer module version. Bug: 291870956 Test: atest FrameworksNetTests CtsNetTestCases Change-Id: Id4efbf51dae9154d2bc3a1ee405e2139d5c91e36
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user