Migrate NetdUtils from networkAddRoute to networkAddRouteParcel.
This will allow us to deprecate networkAddRoute. Bug:412629841 Test: atest TetheringTests Flag: EXEMPT Using device config kill-switch Change-Id: I20e988f760b8ad22b51effdc1f0e204763c6e240
This commit is contained in:
parent
169a584691
commit
98e5827ccc
6 changed files with 184 additions and 79 deletions
|
|
@ -39,6 +39,7 @@ import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
|
|||
import static android.net.util.NetworkConstants.asByte;
|
||||
import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
|
||||
|
||||
import static com.android.net.module.util.ConnectivityCommonFlags.USE_ROUTE_PARCEL_IPCS;
|
||||
import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
|
||||
import static com.android.net.module.util.NetworkStackConstants.RFC7421_PREFIX_LENGTH;
|
||||
import static com.android.networkstack.tethering.TetheringConfiguration.USE_SYNC_SM;
|
||||
|
|
@ -232,6 +233,13 @@ public class IpServer extends StateMachineShim {
|
|||
return Flags.tetheringAndP2pGoLocalAgent();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DeviceConfigUtils#isTetheringFeatureNotChickenedOut
|
||||
*/
|
||||
public boolean isFeatureNotChickenedOut(Context context, String name) {
|
||||
return DeviceConfigUtils.isTetheringFeatureNotChickenedOut(context, name);
|
||||
}
|
||||
|
||||
/** Create a NetworkAgent instance to be used by IpServer. */
|
||||
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
|
||||
@SuppressLint("NewApi")
|
||||
|
|
@ -296,6 +304,7 @@ public class IpServer extends StateMachineShim {
|
|||
private final boolean mUsingLegacyDhcp;
|
||||
private final int mP2pLeasesSubnetPrefixLength;
|
||||
private final boolean mIsWifiP2pDedicatedIpEnabled;
|
||||
private final boolean mUseRouteParcel;
|
||||
|
||||
private final Dependencies mDeps;
|
||||
|
||||
|
|
@ -400,6 +409,11 @@ public class IpServer extends StateMachineShim {
|
|||
TETHERING_AND_P2P_GO_LOCAL_AGENT)
|
||||
: mDeps.isTetheringAndP2pGoLocalAgentBetaFlagEnabled());
|
||||
|
||||
// For post 25Q2 releases always use *RouteParcel methods. For 25Q2 or lower, decide based
|
||||
// on kill-switch
|
||||
mUseRouteParcel = SdkUtil.isAtLeast25Q4()
|
||||
|| mDeps.isFeatureNotChickenedOut(mContext, USE_ROUTE_PARCEL_IPCS);
|
||||
|
||||
mInitialState = new InitialState();
|
||||
mLocalHotspotState = new LocalHotspotState();
|
||||
mTetheredState = new TetheredState();
|
||||
|
|
@ -919,7 +933,8 @@ public class IpServer extends StateMachineShim {
|
|||
}
|
||||
|
||||
private void removeRoutesFromNetwork(int netId, @NonNull final List<RouteInfo> toBeRemoved) {
|
||||
final int removalFailures = NetdUtils.removeRoutesFromNetwork(mNetd, netId, toBeRemoved);
|
||||
final int removalFailures = NetdUtils.removeRoutesFromNetwork(mNetd, netId, toBeRemoved,
|
||||
mUseRouteParcel);
|
||||
if (removalFailures > 0) {
|
||||
mLog.e("Failed to remove " + removalFailures
|
||||
+ " IPv6 routes from network " + netId + ".");
|
||||
|
|
@ -950,15 +965,14 @@ public class IpServer extends StateMachineShim {
|
|||
}
|
||||
}
|
||||
|
||||
private void addRoutesToNetwork(int netId,
|
||||
@NonNull final List<RouteInfo> toBeAdded) {
|
||||
private void addRoutesToNetwork(int netId, @NonNull final List<RouteInfo> toBeAdded) {
|
||||
// It's safe to call addInterfaceToNetwork() even if
|
||||
// the interface is already in the network.
|
||||
addInterfaceToNetwork(netId, mIfaceName);
|
||||
try {
|
||||
// Add routes from local network. Note that adding routes that
|
||||
// already exist does not cause an error (EEXIST is silently ignored).
|
||||
NetdUtils.addRoutesToNetwork(mNetd, netId, mIfaceName, toBeAdded);
|
||||
NetdUtils.addRoutesToNetwork(mNetd, netId, mIfaceName, toBeAdded, mUseRouteParcel);
|
||||
} catch (IllegalStateException e) {
|
||||
mLog.e("Failed to add IPv4/v6 routes to local table: " + e);
|
||||
return;
|
||||
|
|
@ -972,6 +986,7 @@ public class IpServer extends StateMachineShim {
|
|||
final List<RouteInfo> routesToBeRemoved =
|
||||
getLocalRoutesFor(mIfaceName, deprecatedPrefixes);
|
||||
if (mTetheringAgent == null) {
|
||||
// Routes for local network are not considered local routes.
|
||||
removeRoutesFromNetwork(LOCAL_NET_ID, routesToBeRemoved);
|
||||
}
|
||||
for (RouteInfo route : routesToBeRemoved) mLinkProperties.removeRoute(route);
|
||||
|
|
@ -1219,10 +1234,11 @@ public class IpServer extends StateMachineShim {
|
|||
20 /* maxAttempts */, 50 /* pollingIntervalMs */);
|
||||
// Activate a route to dest and IPv6 link local.
|
||||
NetdUtils.modifyRoute(mNetd, NetdUtils.ModifyOperation.ADD, LOCAL_NET_ID,
|
||||
new RouteInfo(asIpPrefix(mIpv4Address), null, mIfaceName, RTN_UNICAST));
|
||||
new RouteInfo(asIpPrefix(mIpv4Address), null, mIfaceName,
|
||||
RTN_UNICAST), mUseRouteParcel);
|
||||
NetdUtils.modifyRoute(mNetd, NetdUtils.ModifyOperation.ADD, LOCAL_NET_ID,
|
||||
new RouteInfo(new IpPrefix("fe80::/64"), null, mIfaceName,
|
||||
RTN_UNICAST));
|
||||
RTN_UNICAST), mUseRouteParcel);
|
||||
}
|
||||
} catch (RemoteException | ServiceSpecificException | IllegalStateException e) {
|
||||
mLog.e("Error Tethering", e);
|
||||
|
|
@ -1352,6 +1368,7 @@ public class IpServer extends StateMachineShim {
|
|||
final List<RouteInfo> routesToBeRemoved =
|
||||
List.of(getDirectConnectedRoute(deprecatedLinkAddress));
|
||||
if (mTetheringAgent == null) {
|
||||
// Routes for local network are not considered local routes.
|
||||
removeRoutesFromNetwork(LOCAL_NET_ID, routesToBeRemoved);
|
||||
}
|
||||
for (RouteInfo route : routesToBeRemoved) mLinkProperties.removeRoute(route);
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import static android.net.ip.IpServer.getTetherableIpv6Prefixes;
|
|||
|
||||
import static com.android.modules.utils.build.SdkLevel.isAtLeastT;
|
||||
import static com.android.modules.utils.build.SdkLevel.isAtLeastV;
|
||||
import static com.android.net.module.util.ConnectivityCommonFlags.USE_ROUTE_PARCEL_IPCS;
|
||||
import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
|
||||
import static com.android.networkstack.tethering.TetheringFeatureFlags.TETHERING_AND_P2P_GO_LOCAL_AGENT;
|
||||
|
||||
|
|
@ -234,6 +235,9 @@ public class IpServerTest {
|
|||
eq(TETHERING_AND_P2P_GO_LOCAL_AGENT));
|
||||
doReturn(agentFeatureEnabled).when(mDependencies)
|
||||
.isTetheringAndP2pGoLocalAgentBetaFlagEnabled();
|
||||
doAnswer(
|
||||
invocation -> mFeatureFlags.getOrDefault((String) invocation.getArgument(1), true)
|
||||
).when(mDependencies).isFeatureNotChickenedOut(any(), anyString());
|
||||
if (isAtLeastV()) {
|
||||
when(mDependencies.makeNetworkAgent(any(), any(), anyString(), anyInt(), any()))
|
||||
.thenReturn(mNetworkAgent);
|
||||
|
|
@ -385,6 +389,7 @@ public class IpServerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FeatureFlag(name = USE_ROUTE_PARCEL_IPCS)
|
||||
public void canBeTetheredAsBluetooth() throws Exception {
|
||||
initStateMachine(TETHERING_BLUETOOTH);
|
||||
|
||||
|
|
@ -404,13 +409,11 @@ public class IpServerTest {
|
|||
inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
|
||||
if (isTetheringNetworkAgentFeatureEnabled()) {
|
||||
inOrder.verify(mNetd, never()).networkAddInterface(anyInt(), anyString());
|
||||
inOrder.verify(mNetd, never())
|
||||
.networkAddRoute(anyInt(), anyString(), anyString(), anyString());
|
||||
verifyNeverNetworkAddRoute(inOrder);
|
||||
} else {
|
||||
inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
|
||||
// One for ipv4 route, one for ipv6 link local route.
|
||||
inOrder.verify(mNetd, times(2))
|
||||
.networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME), any(), any());
|
||||
verifyNetworkAddRoute(inOrder, true, 2);
|
||||
}
|
||||
inOrder.verify(mCallback).updateInterfaceState(
|
||||
mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
|
||||
|
|
@ -451,6 +454,7 @@ public class IpServerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FeatureFlag(name = USE_ROUTE_PARCEL_IPCS)
|
||||
public void canBeTetheredAsUsb() throws Exception {
|
||||
initStateMachine(TETHERING_USB);
|
||||
|
||||
|
|
@ -465,12 +469,10 @@ public class IpServerTest {
|
|||
inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
|
||||
if (isTetheringNetworkAgentFeatureEnabled()) {
|
||||
inOrder.verify(mNetd, never()).networkAddInterface(anyInt(), anyString());
|
||||
inOrder.verify(mNetd, never())
|
||||
.networkAddRoute(anyInt(), anyString(), anyString(), anyString());
|
||||
verifyNeverNetworkAddRoute(inOrder);
|
||||
} else {
|
||||
inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
|
||||
inOrder.verify(mNetd, times(2))
|
||||
.networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME), any(), any());
|
||||
verifyNetworkAddRoute(inOrder, true, 2);
|
||||
}
|
||||
inOrder.verify(mCallback).updateInterfaceState(
|
||||
mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
|
||||
|
|
@ -481,6 +483,7 @@ public class IpServerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FeatureFlag(name = USE_ROUTE_PARCEL_IPCS)
|
||||
public void canBeTetheredAsWifiP2p_NotUsingDedicatedIp() throws Exception {
|
||||
initStateMachine(TETHERING_WIFI_P2P);
|
||||
|
||||
|
|
@ -494,8 +497,7 @@ public class IpServerTest {
|
|||
IFACE_NAME.equals(cfg.ifName) && assertNotContainsFlag(cfg.flags, IF_STATE_UP)));
|
||||
inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
|
||||
inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
|
||||
inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
|
||||
any(), any());
|
||||
verifyNetworkAddRoute(inOrder, true, 2);
|
||||
inOrder.verify(mCallback).updateInterfaceState(
|
||||
mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR);
|
||||
inOrder.verify(mCallback).updateLinkProperties(
|
||||
|
|
@ -505,6 +507,7 @@ public class IpServerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FeatureFlag(name = USE_ROUTE_PARCEL_IPCS)
|
||||
public void canBeTetheredAsWifiP2p_UsingDedicatedIp() throws Exception {
|
||||
initStateMachine(TETHERING_WIFI_P2P, false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD,
|
||||
true /* shouldEnableWifiP2pDedicatedIp */);
|
||||
|
|
@ -521,8 +524,7 @@ public class IpServerTest {
|
|||
IFACE_NAME.equals(cfg.ifName) && assertNotContainsFlag(cfg.flags, IF_STATE_UP)));
|
||||
inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
|
||||
inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
|
||||
inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
|
||||
any(), any());
|
||||
verifyNetworkAddRoute(inOrder, true, 2);
|
||||
inOrder.verify(mCallback).updateInterfaceState(
|
||||
mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR);
|
||||
inOrder.verify(mCallback).updateLinkProperties(
|
||||
|
|
@ -789,6 +791,7 @@ public class IpServerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FeatureFlag(name = USE_ROUTE_PARCEL_IPCS)
|
||||
public void testOnNewPrefixRequest() throws Exception {
|
||||
initStateMachine(TETHERING_NCM);
|
||||
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0,
|
||||
|
|
@ -810,8 +813,7 @@ public class IpServerTest {
|
|||
inOrder.verify(mRoutingCoordinatorManager, never()).requestDownstreamAddress(any());
|
||||
inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
|
||||
// One for ipv4 route, one for ipv6 link local route.
|
||||
inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
|
||||
any(), any());
|
||||
verifyNetworkAddRoute(inOrder, true, 2);
|
||||
inOrder.verify(mCallback).updateInterfaceState(
|
||||
mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR);
|
||||
inOrder.verify(mCallback).updateLinkProperties(eq(mIpServer), lpCaptor.capture());
|
||||
|
|
@ -1120,24 +1122,67 @@ public class IpServerTest {
|
|||
return true;
|
||||
}
|
||||
|
||||
@FeatureFlag(name = Flags.FLAG_TETHERING_AND_P2P_GO_LOCAL_AGENT)
|
||||
private void verifyNeverNetworkAddRoute(InOrder inOrder) throws Exception {
|
||||
inOrder.verify(mNetd, never()).networkAddRoute(anyInt(), anyString(), anyString(),
|
||||
anyString());
|
||||
}
|
||||
|
||||
private void verifyNetworkAddRoute(InOrder inOrder, boolean useParcelMethods, int times)
|
||||
throws Exception {
|
||||
if (useParcelMethods) {
|
||||
inOrder.verify(mNetd, times(times)).networkAddRouteParcel(eq(INetd.LOCAL_NET_ID),
|
||||
argThat(routeInfo -> routeInfo != null && IFACE_NAME.equals(routeInfo.ifName)));
|
||||
inOrder.verify(mNetd, never()).networkAddRoute(anyInt(), anyString(), anyString(),
|
||||
anyString());
|
||||
} else {
|
||||
inOrder.verify(mNetd, times(times)).networkAddRoute(eq(INetd.LOCAL_NET_ID),
|
||||
eq(IFACE_NAME), any(), any());
|
||||
inOrder.verify(mNetd, never()).networkAddRouteParcel(anyInt(), any());
|
||||
}
|
||||
}
|
||||
|
||||
@IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
||||
@FeatureFlag(name = Flags.FLAG_TETHERING_AND_P2P_GO_LOCAL_AGENT)
|
||||
@FeatureFlag(name = USE_ROUTE_PARCEL_IPCS)
|
||||
@Test
|
||||
public void testTetheringNetworkAgent_tetheringAgentEnabled() throws Exception {
|
||||
doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_GLOBAL, true);
|
||||
doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_LOCAL, true);
|
||||
doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_GLOBAL, true, true);
|
||||
doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_LOCAL, true, true);
|
||||
}
|
||||
|
||||
@FeatureFlag(name = Flags.FLAG_TETHERING_AND_P2P_GO_LOCAL_AGENT, enabled = false)
|
||||
@IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
||||
|
||||
@FeatureFlag(name = USE_ROUTE_PARCEL_IPCS)
|
||||
@Test
|
||||
public void testTetheringNetworkAgent_tetheringAgentDisabled() throws Exception {
|
||||
doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_GLOBAL, false);
|
||||
doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_LOCAL, false);
|
||||
doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_GLOBAL, false, true);
|
||||
doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_LOCAL, false, true);
|
||||
}
|
||||
|
||||
private void doTestTetheringNetworkAgent(int scope, boolean expectAgentEnabled)
|
||||
// todo(b/441359615) : remove the test while cleaning up flag USE_ROUTE_PARCEL_IPCS.
|
||||
@IgnoreAfter(Build.VERSION_CODES.BAKLAVA)
|
||||
@IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
||||
@FeatureFlag(name = USE_ROUTE_PARCEL_IPCS, enabled = false)
|
||||
@Test
|
||||
public void testTetheringNetworkAgent_UseRouteParcelDisabled_RouteMethodsCalled()
|
||||
throws Exception {
|
||||
doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_GLOBAL, false, false);
|
||||
doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_LOCAL, false, false);
|
||||
}
|
||||
|
||||
@IgnoreUpTo(Build.VERSION_CODES.BAKLAVA)
|
||||
@FeatureFlag(name = USE_ROUTE_PARCEL_IPCS, enabled = false)
|
||||
@Test
|
||||
public void testTetheringNetworkAgent_postBaklava_RouteParcelMethodsCalled()
|
||||
throws Exception {
|
||||
// On Android versions post-Baklava, the implementation exclusively uses route parcel
|
||||
// IPCs. As a result, the USE_ROUTE_PARCEL_IPCS feature flag is no longer checked and
|
||||
// has no effect.
|
||||
doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_GLOBAL, false, true);
|
||||
doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_LOCAL, false, true);
|
||||
}
|
||||
|
||||
private void doTestTetheringNetworkAgent(int scope, boolean expectAgentEnabled,
|
||||
boolean useRouteParcelIpcs) throws Exception {
|
||||
initStateMachine(TETHERING_USB);
|
||||
|
||||
final InOrder inOrder = inOrder(mNetworkAgent, mNetd);
|
||||
|
|
@ -1148,12 +1193,12 @@ public class IpServerTest {
|
|||
inOrder.verify(mNetd, times(1)).tetherInterfaceAdd(anyString());
|
||||
if (expectAgentEnabled) {
|
||||
inOrder.verify(mNetd, never()).networkAddInterface(anyInt(), anyString());
|
||||
inOrder.verify(mNetd, never()).networkAddRoute(anyInt(), anyString(), any(), any());
|
||||
verifyNeverNetworkAddRoute(inOrder);
|
||||
inOrder.verify(mNetworkAgent, times(1)).sendLinkProperties(any());
|
||||
inOrder.verify(mNetworkAgent, times(1)).markConnected();
|
||||
} else {
|
||||
inOrder.verify(mNetd, times(1)).networkAddInterface(anyInt(), anyString());
|
||||
inOrder.verify(mNetd, times(2)).networkAddRoute(anyInt(), anyString(), any(), any());
|
||||
verifyNetworkAddRoute(inOrder, useRouteParcelIpcs, 2);
|
||||
inOrder.verify(mNetworkAgent, never()).sendLinkProperties(any());
|
||||
inOrder.verify(mNetworkAgent, never()).markConnected();
|
||||
}
|
||||
|
|
@ -1226,7 +1271,7 @@ public class IpServerTest {
|
|||
|
||||
inOrder.verify(mNetworkAgent).register();
|
||||
inOrder.verify(mNetd, never()).networkCreate(any());
|
||||
inOrder.verify(mNetd, never()).networkAddRoute(anyInt(), anyString(), any(), any());
|
||||
verifyNeverNetworkAddRoute(inOrder);
|
||||
|
||||
// Ipv6 link local route won't show up in the LinkProperties, so just
|
||||
// verify ipv4 route.
|
||||
|
|
@ -1249,7 +1294,7 @@ public class IpServerTest {
|
|||
lp.setInterfaceName(UPSTREAM_IFACE);
|
||||
lp.setLinkAddresses(UPSTREAM_ADDRESSES);
|
||||
dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
|
||||
inOrder.verify(mNetd, never()).networkAddRoute(anyInt(), anyString(), any(), any());
|
||||
verifyNeverNetworkAddRoute(inOrder);
|
||||
inOrder.verify(mNetworkAgent).sendLinkProperties(lpCaptor.capture());
|
||||
|
||||
// Expect one Ipv4 route, plus one Ipv6 route.
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
|||
import static com.android.modules.utils.build.SdkLevel.isAtLeastS;
|
||||
import static com.android.modules.utils.build.SdkLevel.isAtLeastT;
|
||||
import static com.android.modules.utils.build.SdkLevel.isAtLeastV;
|
||||
import static com.android.net.module.util.ConnectivityCommonFlags.USE_ROUTE_PARCEL_IPCS;
|
||||
import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTH;
|
||||
import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
|
||||
import static com.android.net.module.util.NetworkStackConstants.RFC7421_PREFIX_LENGTH;
|
||||
|
|
@ -211,6 +212,7 @@ import com.android.net.module.util.InterfaceParams;
|
|||
import com.android.net.module.util.PrivateAddressCoordinator;
|
||||
import com.android.net.module.util.RoutingCoordinatorManager;
|
||||
import com.android.net.module.util.RoutingCoordinatorService;
|
||||
import com.android.net.module.util.SdkUtil;
|
||||
import com.android.net.module.util.SharedLog;
|
||||
import com.android.net.module.util.ip.IpNeighborMonitor;
|
||||
import com.android.networkstack.apishim.common.BluetoothPanShim;
|
||||
|
|
@ -494,6 +496,11 @@ public class TetheringTest {
|
|||
public boolean isTetheringAndP2pGoLocalAgentBetaFlagEnabled() {
|
||||
return mFeatureFlags.getOrDefault(Flags.FLAG_TETHERING_AND_P2P_GO_LOCAL_AGENT, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFeatureNotChickenedOut(Context context, String name) {
|
||||
return mFeatureFlags.getOrDefault(name, true);
|
||||
}
|
||||
}
|
||||
|
||||
public class MockTetheringDependencies extends TetheringDependencies {
|
||||
|
|
@ -994,11 +1001,10 @@ public class TetheringTest {
|
|||
verify(mNetd).tetherInterfaceAdd(ifname);
|
||||
if (expectAgentEnabled) {
|
||||
verify(mNetd, never()).networkAddInterface(anyInt(), anyString());
|
||||
verify(mNetd, never()).networkAddRoute(anyInt(), anyString(), anyString(), anyString());
|
||||
verifyNeverNetworkAddRoute();
|
||||
} else {
|
||||
verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, ifname);
|
||||
verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(ifname),
|
||||
anyString(), anyString());
|
||||
verifyNetworkAddRoute(ifname, 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2250,11 +2256,10 @@ public class TetheringTest {
|
|||
verify(mNetd, times(1)).tetherInterfaceAdd(TEST_WLAN_IFNAME);
|
||||
if (isTetheringNetworkAgentFeatureEnabled()) {
|
||||
verify(mNetd, never()).networkAddInterface(anyInt(), anyString());
|
||||
verify(mNetd, never()).networkAddRoute(anyInt(), anyString(), anyString(), anyString());
|
||||
verifyNeverNetworkAddRoute();
|
||||
} else {
|
||||
verify(mNetd, times(1)).networkAddInterface(INetd.LOCAL_NET_ID, TEST_WLAN_IFNAME);
|
||||
verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(TEST_WLAN_IFNAME),
|
||||
anyString(), anyString());
|
||||
verifyNetworkAddRoute(TEST_WLAN_IFNAME, 2);
|
||||
}
|
||||
verify(mWifiManager).updateInterfaceIpState(
|
||||
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
|
||||
|
|
@ -4183,19 +4188,17 @@ public class TetheringTest {
|
|||
verify(mNetd).tetherInterfaceAdd(TEST_BT_IFNAME);
|
||||
if (isTetheringNetworkAgentFeatureEnabled()) {
|
||||
verify(mNetd, never()).networkAddInterface(anyInt(), anyString());
|
||||
verify(mNetd, never()).networkAddRoute(anyInt(), anyString(), anyString(), anyString());
|
||||
verifyNeverNetworkAddRoute();
|
||||
} else {
|
||||
verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, TEST_BT_IFNAME);
|
||||
verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(TEST_BT_IFNAME),
|
||||
anyString(), anyString());
|
||||
verifyNetworkAddRoute(TEST_BT_IFNAME, 2);
|
||||
}
|
||||
verify(mNetd).ipfwdEnableForwarding(TETHERING_NAME);
|
||||
verify(mNetd).tetherStartWithConfiguration(any());
|
||||
if (isTetheringNetworkAgentFeatureEnabled()) {
|
||||
verify(mNetd, never()).networkAddRoute(anyInt(), anyString(), anyString(), anyString());
|
||||
verifyNeverNetworkAddRoute();
|
||||
} else {
|
||||
verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(TEST_BT_IFNAME),
|
||||
anyString(), anyString());
|
||||
verifyNetworkAddRoute(TEST_BT_IFNAME, 2);
|
||||
}
|
||||
verifyNoMoreInteractions(mNetd);
|
||||
reset(mNetd);
|
||||
|
|
@ -4208,6 +4211,29 @@ public class TetheringTest {
|
|||
return false;
|
||||
}
|
||||
|
||||
private void verifyNeverNetworkAddRoute() throws Exception {
|
||||
verify(mNetd, never()).networkAddRoute(anyInt(), anyString(), anyString(), anyString());
|
||||
verify(mNetd, never()).networkAddRouteParcel(anyInt(), any());
|
||||
}
|
||||
|
||||
private boolean useRouteParcelIpcs() {
|
||||
return SdkUtil.isAtLeast25Q4()
|
||||
|| mFeatureFlags.getOrDefault(USE_ROUTE_PARCEL_IPCS, true);
|
||||
}
|
||||
|
||||
private void verifyNetworkAddRoute(String ifName, int times)
|
||||
throws Exception {
|
||||
if (useRouteParcelIpcs()) {
|
||||
verify(mNetd, times(times))
|
||||
.networkAddRouteParcel(eq(INetd.LOCAL_NET_ID),
|
||||
argThat((parcel) -> ifName.equals(parcel.ifName)));
|
||||
} else {
|
||||
verify(mNetd, times(times))
|
||||
.networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(ifName),
|
||||
anyString(), anyString());
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyNetdCommandForBtTearDown() throws Exception {
|
||||
verify(mNetd).tetherApplyDnsInterfaces();
|
||||
verify(mNetd).tetherInterfaceRemove(TEST_BT_IFNAME);
|
||||
|
|
|
|||
|
|
@ -176,27 +176,27 @@ public class NetdUtils {
|
|||
|
||||
/** Add |routes| to the given network. */
|
||||
public static void addRoutesToNetwork(final INetd netd, int netId, final String iface,
|
||||
final List<RouteInfo> routes) {
|
||||
final List<RouteInfo> routes, final boolean useRouteParcel) {
|
||||
|
||||
for (RouteInfo route : routes) {
|
||||
if (!route.isDefaultRoute()) {
|
||||
modifyRoute(netd, ModifyOperation.ADD, netId, route);
|
||||
modifyRoute(netd, ModifyOperation.ADD, netId, route, useRouteParcel);
|
||||
}
|
||||
}
|
||||
|
||||
// IPv6 link local should be activated always.
|
||||
modifyRoute(netd, ModifyOperation.ADD, netId,
|
||||
new RouteInfo(new IpPrefix("fe80::/64"), null, iface, RTN_UNICAST));
|
||||
new RouteInfo(new IpPrefix("fe80::/64"), null, iface, RTN_UNICAST), useRouteParcel);
|
||||
}
|
||||
|
||||
/** Remove routes from the given network. */
|
||||
public static int removeRoutesFromNetwork(final INetd netd, int netId,
|
||||
final List<RouteInfo> routes) {
|
||||
final List<RouteInfo> routes, final boolean useRouteParcel) {
|
||||
int failures = 0;
|
||||
|
||||
for (RouteInfo route : routes) {
|
||||
try {
|
||||
modifyRoute(netd, ModifyOperation.REMOVE, netId, route);
|
||||
modifyRoute(netd, ModifyOperation.REMOVE, netId, route, useRouteParcel);
|
||||
} catch (IllegalStateException e) {
|
||||
failures++;
|
||||
}
|
||||
|
|
@ -231,18 +231,26 @@ public class NetdUtils {
|
|||
|
||||
/** Add or remove |route|. */
|
||||
public static void modifyRoute(final INetd netd, final ModifyOperation op, final int netId,
|
||||
final RouteInfo route) {
|
||||
final String ifName = route.getInterface();
|
||||
final String dst = route.getDestination().toString();
|
||||
final String nextHop = findNextHop(route);
|
||||
|
||||
final RouteInfo route, final boolean useRouteParcel) {
|
||||
try {
|
||||
switch(op) {
|
||||
case ADD:
|
||||
netd.networkAddRoute(netId, ifName, dst, nextHop);
|
||||
if (useRouteParcel) {
|
||||
RouteInfoParcel routeParcel = NetdUtils.toRouteInfoParcel(route);
|
||||
netd.networkAddRouteParcel(netId, routeParcel);
|
||||
} else {
|
||||
netd.networkAddRoute(netId, route.getInterface(),
|
||||
route.getDestination().toString(), findNextHop(route));
|
||||
}
|
||||
break;
|
||||
case REMOVE:
|
||||
netd.networkRemoveRoute(netId, ifName, dst, nextHop);
|
||||
if (useRouteParcel) {
|
||||
RouteInfoParcel routeParcel = NetdUtils.toRouteInfoParcel(route);
|
||||
netd.networkRemoveRouteParcel(netId, routeParcel);
|
||||
} else {
|
||||
netd.networkRemoveRoute(netId, route.getInterface(),
|
||||
route.getDestination().toString(), findNextHop(route));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unsupported modify operation:" + op);
|
||||
|
|
@ -256,31 +264,10 @@ public class NetdUtils {
|
|||
* Convert a RouteInfo into a RouteInfoParcel.
|
||||
*/
|
||||
public static RouteInfoParcel toRouteInfoParcel(RouteInfo route) {
|
||||
final String nextHop;
|
||||
|
||||
switch (route.getType()) {
|
||||
case RouteInfo.RTN_UNICAST:
|
||||
if (route.hasGateway()) {
|
||||
nextHop = route.getGateway().getHostAddress();
|
||||
} else {
|
||||
nextHop = INetd.NEXTHOP_NONE;
|
||||
}
|
||||
break;
|
||||
case RouteInfo.RTN_UNREACHABLE:
|
||||
nextHop = INetd.NEXTHOP_UNREACHABLE;
|
||||
break;
|
||||
case RouteInfo.RTN_THROW:
|
||||
nextHop = INetd.NEXTHOP_THROW;
|
||||
break;
|
||||
default:
|
||||
nextHop = INetd.NEXTHOP_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
final RouteInfoParcel rip = new RouteInfoParcel();
|
||||
rip.ifName = route.getInterface();
|
||||
rip.destination = route.getDestination().toString();
|
||||
rip.nextHop = nextHop;
|
||||
rip.nextHop = findNextHop(route);
|
||||
rip.mtu = route.getMtu();
|
||||
|
||||
return rip;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (C) 2025 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.net.module.util;
|
||||
|
||||
/**
|
||||
* Collection of flag constants shared across modules.
|
||||
* @hide
|
||||
*/
|
||||
public class ConnectivityCommonFlags {
|
||||
|
||||
/**
|
||||
* A feature flag to use the network{Add,Remove}RouteParcel netd IPCs instead of the legacy
|
||||
* network{Add,Remote}Route IPCs. This flag is used by both the connectivity and wifi modules.
|
||||
*/
|
||||
public static final String USE_ROUTE_PARCEL_IPCS = "use_route_parcel_ipcs";
|
||||
}
|
||||
|
|
@ -189,6 +189,7 @@ import static com.android.testutils.MiscAsserts.assertLength;
|
|||
import static com.android.testutils.MiscAsserts.assertRunsInAtMost;
|
||||
import static com.android.testutils.MiscAsserts.assertSameElements;
|
||||
import static com.android.testutils.MiscAsserts.assertThrows;
|
||||
import static com.android.testutils.TestPermissionUtil.runAsShell;
|
||||
import static com.android.testutils.TestableNetworkCallback.Event.AVAILABLE;
|
||||
import static com.android.testutils.TestableNetworkCallback.Event.BLOCKED_STATUS;
|
||||
import static com.android.testutils.TestableNetworkCallback.Event.BLOCKED_STATUS_INT;
|
||||
|
|
@ -199,7 +200,6 @@ import static com.android.testutils.TestableNetworkCallback.Event.NETWORK_CAPS_U
|
|||
import static com.android.testutils.TestableNetworkCallback.Event.RESUMED;
|
||||
import static com.android.testutils.TestableNetworkCallback.Event.SUSPENDED;
|
||||
import static com.android.testutils.TestableNetworkCallback.Event.UNAVAILABLE;
|
||||
import static com.android.testutils.TestPermissionUtil.runAsShell;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
|
|
|||
Loading…
Reference in a new issue