diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java index 224aad79e1..e54a7e0ddb 100644 --- a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java +++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java @@ -25,8 +25,6 @@ import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkStats.UID_TETHERING; -import static android.net.TetheringManager.TETHERING_WIFI; -import static android.net.ip.IpServer.STATE_TETHERED; import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED; import static android.system.OsConstants.ETH_P_IP; import static android.system.OsConstants.ETH_P_IPV6; @@ -79,9 +77,7 @@ import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.argThat; import static org.mockito.Mockito.clearInvocations; -import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; @@ -100,11 +96,9 @@ import android.net.MacAddress; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkStats; -import android.net.RoutingCoordinatorManager; import android.net.TetherOffloadRuleParcel; import android.net.TetherStatsParcel; import android.net.ip.IpServer; -import android.net.ip.RouterAdvertisementDaemon; import android.os.Build; import android.os.Handler; import android.os.test.TestLooper; @@ -119,12 +113,10 @@ import androidx.test.runner.AndroidJUnit4; import com.android.dx.mockito.inline.extended.ExtendedMockito; import com.android.internal.util.IndentingPrintWriter; -import com.android.modules.utils.build.SdkLevel; import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.IBpfMap; import com.android.net.module.util.InterfaceParams; import com.android.net.module.util.NetworkStackConstants; -import com.android.net.module.util.SdkUtil.LateSdk; import com.android.net.module.util.SharedLog; import com.android.net.module.util.Struct.S32; import com.android.net.module.util.bpf.Tether4Key; @@ -143,8 +135,6 @@ import com.android.networkstack.tethering.BpfCoordinator.BpfConntrackEventConsum import com.android.networkstack.tethering.BpfCoordinator.ClientInfo; import com.android.networkstack.tethering.BpfCoordinator.Ipv6DownstreamRule; import com.android.networkstack.tethering.BpfCoordinator.Ipv6UpstreamRule; -import com.android.networkstack.tethering.metrics.TetheringMetrics; -import com.android.networkstack.tethering.util.InterfaceSet; import com.android.testutils.DevSdkIgnoreRule; import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter; import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; @@ -209,11 +199,6 @@ public class BpfCoordinatorTest { private static final MacAddress MAC_B = MacAddress.fromString("11:22:33:00:00:0b"); private static final MacAddress MAC_NULL = MacAddress.fromString("00:00:00:00:00:00"); - private static final LinkAddress UPSTREAM_ADDRESS = new LinkAddress("2001:db8:0:1234::168/64"); - private static final LinkAddress UPSTREAM_ADDRESS2 = new LinkAddress("2001:db8:0:abcd::168/64"); - private static final Set UPSTREAM_ADDRESSES = Set.of(UPSTREAM_ADDRESS); - private static final Set UPSTREAM_ADDRESSES2 = - Set.of(UPSTREAM_ADDRESS, UPSTREAM_ADDRESS2); private static final IpPrefix UPSTREAM_PREFIX = new IpPrefix("2001:db8:0:1234::/64"); private static final IpPrefix UPSTREAM_PREFIX2 = new IpPrefix("2001:db8:0:abcd::/64"); private static final Set UPSTREAM_PREFIXES = Set.of(UPSTREAM_PREFIX); @@ -449,13 +434,6 @@ public class BpfCoordinatorTest { @Mock private TetheringConfiguration mTetherConfig; @Mock private ConntrackMonitor mConntrackMonitor; @Mock private IpNeighborMonitor mIpNeighborMonitor; - @Mock private RouterAdvertisementDaemon mRaDaemon; - @Mock private IpServer.Dependencies mIpServerDeps; - @Mock private IpServer.Callback mIpServerCallback; - @Mock private PrivateAddressCoordinator mAddressCoordinator; - private final LateSdk mRoutingCoordinatorManager = - new LateSdk<>(SdkLevel.isAtLeastS() ? mock(RoutingCoordinatorManager.class) : null); - @Mock private TetheringMetrics mTetheringMetrics; // Late init since methods must be called by the thread that created this object. private TestableNetworkStatsProviderCbBinder mTetherStatsProviderCb; @@ -575,24 +553,6 @@ public class BpfCoordinatorTest { when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(true /* default value */); when(mIpServer.getInterfaceParams()).thenReturn(DOWNSTREAM_IFACE_PARAMS); when(mIpServer2.getInterfaceParams()).thenReturn(DOWNSTREAM_IFACE_PARAMS2); - - // Simulate the behavior of RoutingCoordinator - if (null != mRoutingCoordinatorManager.value) { - doAnswer(it -> { - final String fromIface = (String) it.getArguments()[0]; - final String toIface = (String) it.getArguments()[1]; - mNetd.tetherAddForward(fromIface, toIface); - mNetd.ipfwdAddInterfaceForward(fromIface, toIface); - return null; - }).when(mRoutingCoordinatorManager.value).addInterfaceForward(any(), any()); - doAnswer(it -> { - final String fromIface = (String) it.getArguments()[0]; - final String toIface = (String) it.getArguments()[1]; - mNetd.ipfwdRemoveInterfaceForward(fromIface, toIface); - mNetd.tetherRemoveForward(fromIface, toIface); - return null; - }).when(mRoutingCoordinatorManager.value).removeInterfaceForward(any(), any()); - } } private void waitForIdle() { @@ -605,48 +565,6 @@ public class BpfCoordinatorTest { when(mNetd.tetherOffloadGetStats()).thenReturn(new TetherStatsParcel[0]); } - @NonNull - private IpServer makeAndStartIpServer(String interfaceName, BpfCoordinator bpfCoordinator) - throws Exception { - final LinkAddress testAddress = new LinkAddress("192.168.42.5/24"); - when(mIpServerDeps.getRouterAdvertisementDaemon(any())).thenReturn(mRaDaemon); - when(mIpServerDeps.getInterfaceParams(DOWNSTREAM_IFACE)).thenReturn( - DOWNSTREAM_IFACE_PARAMS); - when(mIpServerDeps.getInterfaceParams(UPSTREAM_IFACE)).thenReturn(UPSTREAM_IFACE_PARAMS); - when(mIpServerDeps.getInterfaceParams(UPSTREAM_IFACE2)).thenReturn(UPSTREAM_IFACE_PARAMS2); - when(mIpServerDeps.getInterfaceParams(IPSEC_IFACE)).thenReturn(IPSEC_IFACE_PARAMS); - when(mAddressCoordinator.requestDownstreamAddress(any(), anyInt(), - anyBoolean())).thenReturn(testAddress); - when(mRaDaemon.start()).thenReturn(true); - final IpServer ipServer = new IpServer( - interfaceName, mHandler, TETHERING_WIFI, new SharedLog("test"), mNetd, - bpfCoordinator, mRoutingCoordinatorManager, mIpServerCallback, mTetherConfig, - mAddressCoordinator, mTetheringMetrics, mIpServerDeps); - ipServer.start(); - ipServer.sendMessage(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED); - mTestLooper.dispatchAll(); - - LinkProperties lp = new LinkProperties(); - lp.setInterfaceName(UPSTREAM_IFACE); - lp.setLinkAddresses(UPSTREAM_ADDRESSES); - dispatchTetherConnectionChanged(ipServer, UPSTREAM_IFACE, lp, 0); - - return ipServer; - } - - private void dispatchTetherConnectionChanged(IpServer ipServer, String upstreamIface, - LinkProperties v6lp, int ttlAdjustment) { - dispatchTetherConnectionChanged(ipServer, upstreamIface); - ipServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, ttlAdjustment, 0, v6lp); - mTestLooper.dispatchAll(); - } - - private void dispatchTetherConnectionChanged(IpServer ipServer, String upstreamIface) { - final InterfaceSet ifs = (upstreamIface != null) ? new InterfaceSet(upstreamIface) : null; - ipServer.sendMessage(IpServer.CMD_TETHER_CONNECTION_CHANGED, ifs); - mTestLooper.dispatchAll(); - } - private void dispatchIpv6UpstreamChanged(BpfCoordinator bpfCoordinator, IpServer ipServer, int upstreamIfindex, String upstreamIface, Set upstreamPrefixes) { bpfCoordinator.maybeAddUpstreamToLookupTable(upstreamIfindex, upstreamIface); @@ -658,13 +576,11 @@ public class BpfCoordinatorTest { private void recvNewNeigh(int ifindex, InetAddress addr, short nudState, MacAddress mac) { mNeighborEventConsumer.accept(new NeighborEvent(0, RTM_NEWNEIGH, ifindex, addr, nudState, mac)); - mTestLooper.dispatchAll(); } private void recvDelNeigh(int ifindex, InetAddress addr, short nudState, MacAddress mac) { mNeighborEventConsumer.accept(new NeighborEvent(0, RTM_DELNEIGH, ifindex, addr, nudState, mac)); - mTestLooper.dispatchAll(); } @NonNull @@ -2856,9 +2772,10 @@ public class BpfCoordinatorTest { public void addRemoveIpv6ForwardingRules() throws Exception { final int myIfindex = DOWNSTREAM_IFINDEX; final int notMyIfindex = myIfindex - 1; - final BpfCoordinator coordinator = makeBpfCoordinator(false /* addDefaultIpServer */); - final IpServer ipServer = makeAndStartIpServer(DOWNSTREAM_IFACE, coordinator); + final BpfCoordinator coordinator = makeBpfCoordinator(); + dispatchIpv6UpstreamChanged( + coordinator, mIpServer, UPSTREAM_IFINDEX, UPSTREAM_IFACE, UPSTREAM_PREFIXES); resetNetdAndBpfMaps(); verifyNoMoreInteractions(mNetd, mBpfDownstream6Map, mBpfUpstream6Map); @@ -2907,10 +2824,8 @@ public class BpfCoordinatorTest { resetNetdAndBpfMaps(); InOrder inOrder = inOrder(mNetd, mBpfDownstream6Map, mBpfUpstream6Map); - LinkProperties lp = new LinkProperties(); - lp.setInterfaceName(UPSTREAM_IFACE2); - lp.setLinkAddresses(UPSTREAM_ADDRESSES); - dispatchTetherConnectionChanged(ipServer, UPSTREAM_IFACE2, lp, -1); + dispatchIpv6UpstreamChanged( + coordinator, mIpServer, UPSTREAM_IFINDEX2, UPSTREAM_IFACE2, UPSTREAM_PREFIXES); final Ipv6DownstreamRule ruleA2 = buildTestDownstreamRule( UPSTREAM_IFINDEX2, NEIGH_A, MAC_A); final Ipv6DownstreamRule ruleB2 = buildTestDownstreamRule( @@ -2924,11 +2839,9 @@ public class BpfCoordinatorTest { verifyNoUpstreamIpv6ForwardingChange(inOrder); resetNetdAndBpfMaps(); - // Upstream link addresses change result in updating the rules. - LinkProperties lp2 = new LinkProperties(); - lp2.setInterfaceName(UPSTREAM_IFACE2); - lp2.setLinkAddresses(UPSTREAM_ADDRESSES2); - dispatchTetherConnectionChanged(ipServer, UPSTREAM_IFACE2, lp2, -1); + // Upstream prefixes change result in updating the rules. + dispatchIpv6UpstreamChanged( + coordinator, mIpServer, UPSTREAM_IFINDEX2, UPSTREAM_IFACE2, UPSTREAM_PREFIXES2); verifyRemoveDownstreamRule(inOrder, ruleA2); verifyRemoveDownstreamRule(inOrder, ruleB2); verifyStopUpstreamIpv6Forwarding(inOrder, UPSTREAM_PREFIXES); @@ -2938,7 +2851,7 @@ public class BpfCoordinatorTest { resetNetdAndBpfMaps(); // When the upstream is lost, rules are removed. - dispatchTetherConnectionChanged(ipServer, null, null, 0); + dispatchIpv6UpstreamChanged(coordinator, mIpServer, NO_UPSTREAM, null, NO_PREFIXES); verifyStopUpstreamIpv6Forwarding(inOrder, UPSTREAM_PREFIXES2); verifyRemoveDownstreamRule(ruleA2); verifyRemoveDownstreamRule(ruleB2); @@ -2949,7 +2862,7 @@ public class BpfCoordinatorTest { resetNetdAndBpfMaps(); // If the upstream is IPv4-only, no IPv6 rules are added to BPF map. - dispatchTetherConnectionChanged(ipServer, UPSTREAM_IFACE); + dispatchIpv6UpstreamChanged(coordinator, mIpServer, NO_UPSTREAM, null, NO_PREFIXES); resetNetdAndBpfMaps(); recvNewNeigh(myIfindex, NEIGH_A, NUD_REACHABLE, MAC_A); verifyNoUpstreamIpv6ForwardingChange(null); @@ -2959,8 +2872,8 @@ public class BpfCoordinatorTest { // Rules can be added again once upstream IPv6 connectivity is available. The existing rules // with an upstream of NO_UPSTREAM are reapplied. - lp.setInterfaceName(UPSTREAM_IFACE); - dispatchTetherConnectionChanged(ipServer, UPSTREAM_IFACE, lp, -1); + dispatchIpv6UpstreamChanged( + coordinator, mIpServer, UPSTREAM_IFINDEX, UPSTREAM_IFACE, UPSTREAM_PREFIXES); verifyStartUpstreamIpv6Forwarding(null, UPSTREAM_IFINDEX, UPSTREAM_PREFIXES); verifyAddDownstreamRule(ruleA); recvNewNeigh(myIfindex, NEIGH_B, NUD_REACHABLE, MAC_B); @@ -2968,23 +2881,27 @@ public class BpfCoordinatorTest { // If upstream IPv6 connectivity is lost, rules are removed. resetNetdAndBpfMaps(); - dispatchTetherConnectionChanged(ipServer, UPSTREAM_IFACE, null, 0); + dispatchIpv6UpstreamChanged(coordinator, mIpServer, NO_UPSTREAM, null, NO_PREFIXES); verifyRemoveDownstreamRule(ruleA); verifyRemoveDownstreamRule(ruleB); verifyStopUpstreamIpv6Forwarding(null, UPSTREAM_PREFIXES); // When upstream IPv6 connectivity comes back, upstream rules are added and downstream rules // are reapplied. - lp.setInterfaceName(UPSTREAM_IFACE); - dispatchTetherConnectionChanged(ipServer, UPSTREAM_IFACE, lp, -1); + dispatchIpv6UpstreamChanged( + coordinator, mIpServer, UPSTREAM_IFINDEX, UPSTREAM_IFACE, UPSTREAM_PREFIXES); verifyStartUpstreamIpv6Forwarding(null, UPSTREAM_IFINDEX, UPSTREAM_PREFIXES); verifyAddDownstreamRule(ruleA); verifyAddDownstreamRule(ruleB); resetNetdAndBpfMaps(); // When the downstream interface goes down, rules are removed. - ipServer.stop(); - mTestLooper.dispatchAll(); + // Simulate receiving CMD_INTERFACE_DOWN in the BaseServingState of IpServer. + reset(mIpNeighborMonitor); + dispatchIpv6UpstreamChanged(coordinator, mIpServer, NO_UPSTREAM, null, NO_PREFIXES); + coordinator.tetherOffloadClientClear(mIpServer); + coordinator.removeIpServer(mIpServer); + verifyStopUpstreamIpv6Forwarding(null, UPSTREAM_PREFIXES); verifyRemoveDownstreamRule(ruleA); verifyRemoveDownstreamRule(ruleB); @@ -3005,8 +2922,9 @@ public class BpfCoordinatorTest { // [1] Enable BPF offload. // A neighbor that is added or deleted causes the rule to be added or removed. - final BpfCoordinator coordinator = makeBpfCoordinator(false /* addDefaultIpServer */); - final IpServer ipServer = makeAndStartIpServer(DOWNSTREAM_IFACE, coordinator); + final BpfCoordinator coordinator = makeBpfCoordinator(); + dispatchIpv6UpstreamChanged( + coordinator, mIpServer, UPSTREAM_IFINDEX, UPSTREAM_IFACE, UPSTREAM_PREFIXES); resetNetdAndBpfMaps(); recvNewNeigh(myIfindex, NEIGH_A, NUD_REACHABLE, MAC_A); @@ -3021,18 +2939,15 @@ public class BpfCoordinatorTest { resetNetdAndBpfMaps(); // Upstream IPv6 connectivity change causes upstream rules change. - LinkProperties lp2 = new LinkProperties(); - lp2.setInterfaceName(UPSTREAM_IFACE2); - lp2.setLinkAddresses(UPSTREAM_ADDRESSES2); - dispatchTetherConnectionChanged(ipServer, UPSTREAM_IFACE2, lp2, 0); + dispatchIpv6UpstreamChanged( + coordinator, mIpServer, UPSTREAM_IFINDEX2, UPSTREAM_IFACE2, UPSTREAM_PREFIXES2); verifyStartUpstreamIpv6Forwarding(null, UPSTREAM_IFINDEX2, UPSTREAM_PREFIXES2); resetNetdAndBpfMaps(); // [2] Disable BPF offload. // A neighbor that is added or deleted doesn’t cause the rule to be added or removed. when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(false); - final BpfCoordinator coordinator2 = makeBpfCoordinator(false /* addDefaultIpServer */); - final IpServer ipServer2 = makeAndStartIpServer(DOWNSTREAM_IFACE, coordinator2); + final BpfCoordinator coordinator2 = makeBpfCoordinator(); verifyNoUpstreamIpv6ForwardingChange(null); resetNetdAndBpfMaps(); @@ -3045,7 +2960,8 @@ public class BpfCoordinatorTest { resetNetdAndBpfMaps(); // Upstream IPv6 connectivity change doesn't cause the rule to be added or removed. - dispatchTetherConnectionChanged(ipServer2, UPSTREAM_IFACE2, lp2, 0); + dispatchIpv6UpstreamChanged( + coordinator, mIpServer2, UPSTREAM_IFINDEX2, UPSTREAM_IFACE2, NO_PREFIXES); verifyNoUpstreamIpv6ForwardingChange(null); verifyNeverRemoveDownstreamRule(); resetNetdAndBpfMaps(); @@ -3054,8 +2970,7 @@ public class BpfCoordinatorTest { @Test public void doesNotStartIpNeighborMonitorIfBpfOffloadDisabled() throws Exception { when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(false); - final BpfCoordinator coordinator = makeBpfCoordinator(false /* addDefaultIpServer */); - final IpServer ipServer = makeAndStartIpServer(DOWNSTREAM_IFACE, coordinator); + final BpfCoordinator coordinator = makeBpfCoordinator(); // IP neighbor monitor doesn't start if BPF offload is disabled. verify(mIpNeighborMonitor, never()).start(); @@ -3063,16 +2978,11 @@ public class BpfCoordinatorTest { @Test public void testSkipVirtualNetworkInBpf() throws Exception { - final BpfCoordinator coordinator = makeBpfCoordinator(false /* addDefaultIpServer */); - final IpServer ipServer = makeAndStartIpServer(DOWNSTREAM_IFACE, coordinator); - final LinkProperties v6Only = new LinkProperties(); - v6Only.setInterfaceName(IPSEC_IFACE); - v6Only.setLinkAddresses(UPSTREAM_ADDRESSES); + final BpfCoordinator coordinator = makeBpfCoordinator(); resetNetdAndBpfMaps(); - dispatchTetherConnectionChanged(ipServer, IPSEC_IFACE, v6Only, 0); - verify(mNetd).tetherAddForward(DOWNSTREAM_IFACE, IPSEC_IFACE); - verify(mNetd).ipfwdAddInterfaceForward(DOWNSTREAM_IFACE, IPSEC_IFACE); + dispatchIpv6UpstreamChanged( + coordinator, mIpServer, IPSEC_IFINDEX, IPSEC_IFACE, UPSTREAM_PREFIXES); verifyNeverAddUpstreamRule(); recvNewNeigh(DOWNSTREAM_IFINDEX, NEIGH_A, NUD_REACHABLE, MAC_A); @@ -3081,8 +2991,7 @@ public class BpfCoordinatorTest { @Test public void addRemoveTetherClient() throws Exception { - final BpfCoordinator coordinator = makeBpfCoordinator(false /* addDefaultIpServer */); - final IpServer ipServer = makeAndStartIpServer(DOWNSTREAM_IFACE, coordinator); + final BpfCoordinator coordinator = makeBpfCoordinator(); final int myIfindex = DOWNSTREAM_IFINDEX; final int notMyIfindex = myIfindex - 1; @@ -3091,33 +3000,36 @@ public class BpfCoordinatorTest { final InetAddress neighLL = InetAddresses.parseNumericAddress("169.254.0.1"); final InetAddress neighMC = InetAddresses.parseNumericAddress("224.0.0.1"); + dispatchIpv6UpstreamChanged( + coordinator, mIpServer, UPSTREAM_IFINDEX, UPSTREAM_IFACE, UPSTREAM_PREFIXES); + // Events on other interfaces are ignored. recvNewNeigh(notMyIfindex, neighA, NUD_REACHABLE, MAC_A); - assertNull(mTetherClients.get(ipServer)); + assertNull(mTetherClients.get(mIpServer)); // Events on this interface are received and sent to BpfCoordinator. recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, MAC_A); - assertClientInfoExists(ipServer, + assertClientInfoExists(mIpServer, new ClientInfo(myIfindex, DOWNSTREAM_MAC, (Inet4Address) neighA, MAC_A)); recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, MAC_B); - assertClientInfoExists(ipServer, + assertClientInfoExists(mIpServer, new ClientInfo(myIfindex, DOWNSTREAM_MAC, (Inet4Address) neighB, MAC_B)); // Link-local and multicast neighbors are ignored. recvNewNeigh(myIfindex, neighLL, NUD_REACHABLE, MAC_A); - assertClientInfoDoesNotExist(ipServer, (Inet4Address) neighLL); + assertClientInfoDoesNotExist(mIpServer, (Inet4Address) neighLL); recvNewNeigh(myIfindex, neighMC, NUD_REACHABLE, MAC_A); - assertClientInfoDoesNotExist(ipServer, (Inet4Address) neighMC); + assertClientInfoDoesNotExist(mIpServer, (Inet4Address) neighMC); // A neighbor that is no longer valid causes the client to be removed. // NUD_FAILED events do not have a MAC address. recvNewNeigh(myIfindex, neighA, NUD_FAILED, null); - assertClientInfoDoesNotExist(ipServer, (Inet4Address) neighA); + assertClientInfoDoesNotExist(mIpServer, (Inet4Address) neighA); // A neighbor that is deleted causes the client to be removed. recvDelNeigh(myIfindex, neighB, NUD_STALE, MAC_B); // When last client information is deleted, IpServer will be removed from mTetherClients - assertNull(mTetherClients.get(ipServer)); + assertNull(mTetherClients.get(mIpServer)); } }