Loading packages/Tethering/src/android/net/ip/IpServer.java +6 −7 Original line number Diff line number Diff line Loading @@ -738,7 +738,7 @@ public class IpServer extends StateMachine { // // TODO: Evaluate using a data structure than is more directly suited to // communicating only the relevant information. private void updateUpstreamIPv6LinkProperties(LinkProperties v6only) { private void updateUpstreamIPv6LinkProperties(LinkProperties v6only, int ttlAdjustment) { if (mRaDaemon == null) return; // Avoid unnecessary work on spurious updates. Loading @@ -761,7 +761,7 @@ public class IpServer extends StateMachine { params.mtu = mUsingBpfOffload ? v6only.getMtu() - 16 : v6only.getMtu(); params.hasDefaultRoute = v6only.hasIpv6DefaultRoute(); if (params.hasDefaultRoute) params.hopLimit = getHopLimit(upstreamIface); if (params.hasDefaultRoute) params.hopLimit = getHopLimit(upstreamIface, ttlAdjustment); for (LinkAddress linkAddr : v6only.getLinkAddresses()) { if (linkAddr.getPrefixLength() != RFC7421_PREFIX_LENGTH) continue; Loading Loading @@ -1052,12 +1052,11 @@ public class IpServer extends StateMachine { } } private byte getHopLimit(String upstreamIface) { private byte getHopLimit(String upstreamIface, int adjustTTL) { try { int upstreamHopLimit = Integer.parseUnsignedInt( mNetd.getProcSysNet(INetd.IPV6, INetd.CONF, upstreamIface, "hop_limit")); // Add one hop to account for this forwarding device upstreamHopLimit++; upstreamHopLimit = upstreamHopLimit + adjustTTL; // Cap the hop limit to 255. return (byte) Integer.min(upstreamHopLimit, 255); } catch (Exception e) { Loading Loading @@ -1145,7 +1144,7 @@ public class IpServer extends StateMachine { transitionTo(mUnavailableState); break; case CMD_IPV6_TETHER_UPDATE: updateUpstreamIPv6LinkProperties((LinkProperties) message.obj); updateUpstreamIPv6LinkProperties((LinkProperties) message.obj, message.arg1); break; default: return NOT_HANDLED; Loading Loading @@ -1209,7 +1208,7 @@ public class IpServer extends StateMachine { if (DBG) Log.d(TAG, "Untethered (ifdown)" + mIfaceName); break; case CMD_IPV6_TETHER_UPDATE: updateUpstreamIPv6LinkProperties((LinkProperties) message.obj); updateUpstreamIPv6LinkProperties((LinkProperties) message.obj, message.arg1); sendLinkProperties(); break; case CMD_IP_FORWARDING_ENABLE_ERROR: Loading packages/Tethering/src/com/android/networkstack/tethering/IPv6TetheringCoordinator.java +18 −1 Original line number Diff line number Diff line Loading @@ -161,11 +161,28 @@ public class IPv6TetheringCoordinator { private void updateIPv6TetheringInterfaces() { for (IpServer ipServer : mNotifyList) { final LinkProperties lp = getInterfaceIPv6LinkProperties(ipServer); ipServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, lp); ipServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, getTtlAdjustment(), 0, lp); break; } } private int getTtlAdjustment() { if (mUpstreamNetworkState == null || mUpstreamNetworkState.networkCapabilities == null) { return 0; } // If upstream is cellular, set the TTL in Router Advertisements to "network-set TTL" - 1 // for carrier requirement. if (mUpstreamNetworkState.networkCapabilities.hasTransport( NetworkCapabilities.TRANSPORT_CELLULAR)) { return -1; } // For other non-cellular upstream, set TTL as "network-set TTL" + 1 to preventing arbitrary // distinction between tethered and untethered traffic. return 1; } private LinkProperties getInterfaceIPv6LinkProperties(IpServer ipServer) { final Downstream ds = findDownstream(ipServer); if (ds == null) return null; Loading packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java +54 −8 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.net.ip; import static android.net.INetd.IF_STATE_UP; import static android.net.RouteInfo.RTN_UNICAST; import static android.net.TetheringManager.TETHERING_BLUETOOTH; import static android.net.TetheringManager.TETHERING_NCM; import static android.net.TetheringManager.TETHERING_USB; Loading Loading @@ -74,6 +75,7 @@ import android.net.dhcp.IDhcpServer; import android.net.dhcp.IDhcpServerCallbacks; import android.net.ip.IpNeighborMonitor.NeighborEvent; import android.net.ip.IpNeighborMonitor.NeighborEventConsumer; import android.net.ip.RouterAdvertisementDaemon.RaParams; import android.net.util.InterfaceParams; import android.net.util.InterfaceSet; import android.net.util.SharedLog; Loading Loading @@ -196,7 +198,7 @@ public class IpServerTest { if (upstreamIface != null) { LinkProperties lp = new LinkProperties(); lp.setInterfaceName(upstreamIface); dispatchTetherConnectionChanged(upstreamIface, lp); dispatchTetherConnectionChanged(upstreamIface, lp, 0); } reset(mNetd, mCallback); } Loading Loading @@ -694,7 +696,7 @@ public class IpServerTest { InOrder inOrder = inOrder(mNetd); LinkProperties lp = new LinkProperties(); lp.setInterfaceName(UPSTREAM_IFACE2); dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp); dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp, -1); inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX2, neighA, macA)); inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighA, macA)); inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX2, neighB, macB)); Loading @@ -702,7 +704,7 @@ public class IpServerTest { reset(mNetd); // When the upstream is lost, rules are removed. dispatchTetherConnectionChanged(null, null); dispatchTetherConnectionChanged(null, null, 0); verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX2, neighA, macA)); verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX2, neighB, macB)); reset(mNetd); Loading @@ -715,19 +717,19 @@ public class IpServerTest { // Rules can be added again once upstream IPv6 connectivity is available. lp.setInterfaceName(UPSTREAM_IFACE); dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp); dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1); recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB); verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighB, macB)); verify(mNetd, never()).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighA, macA)); // If upstream IPv6 connectivity is lost, rules are removed. reset(mNetd); dispatchTetherConnectionChanged(UPSTREAM_IFACE, null); dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0); verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighB, macB)); // When the interface goes down, rules are removed. lp.setInterfaceName(UPSTREAM_IFACE); dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp); dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1); recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA); recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB); verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighA, macA)); Loading Loading @@ -788,6 +790,49 @@ public class IpServerTest { verify(mIpNeighborMonitor, never()).start(); } private LinkProperties buildIpv6OnlyLinkProperties(final String iface) { final LinkProperties linkProp = new LinkProperties(); linkProp.setInterfaceName(iface); linkProp.addLinkAddress(new LinkAddress("2001:db8::1/64")); linkProp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, iface, RTN_UNICAST)); final InetAddress dns = InetAddresses.parseNumericAddress("2001:4860:4860::8888"); linkProp.addDnsServer(dns); return linkProp; } @Test public void testAdjustTtlValue() throws Exception { final ArgumentCaptor<RaParams> raParamsCaptor = ArgumentCaptor.forClass(RaParams.class); initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture()); final RaParams noV6Params = raParamsCaptor.getValue(); assertEquals(65, noV6Params.hopLimit); reset(mRaDaemon); when(mNetd.getProcSysNet( INetd.IPV6, INetd.CONF, UPSTREAM_IFACE, "hop_limit")).thenReturn("64"); final LinkProperties lp = buildIpv6OnlyLinkProperties(UPSTREAM_IFACE); dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 1); verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture()); final RaParams nonCellularParams = raParamsCaptor.getValue(); assertEquals(65, nonCellularParams.hopLimit); reset(mRaDaemon); dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0); verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture()); final RaParams noUpstream = raParamsCaptor.getValue(); assertEquals(65, nonCellularParams.hopLimit); reset(mRaDaemon); dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1); verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture()); final RaParams cellularParams = raParamsCaptor.getValue(); assertEquals(63, cellularParams.hopLimit); reset(mRaDaemon); } private void assertDhcpServingParams(final DhcpServingParamsParcel params, final IpPrefix prefix) { // Last address byte is random Loading Loading @@ -838,9 +883,10 @@ public class IpServerTest { * @param upstreamIface String name of upstream interface (or null) * @param v6lp IPv6 LinkProperties of the upstream interface, or null for an IPv4-only upstream. */ private void dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp) { private void dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp, int ttlAdjustment) { dispatchTetherConnectionChanged(upstreamIface); mIpServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, v6lp); mIpServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, ttlAdjustment, 0, v6lp); mLooper.dispatchAll(); } Loading packages/Tethering/tests/unit/src/com/android/networkstack/tethering/IPv6TetheringCoordinatorTest.java +2 −2 Original line number Diff line number Diff line Loading @@ -128,7 +128,7 @@ public class IPv6TetheringCoordinatorTest { final UpstreamNetworkState mobileUpstream = createDualStackUpstream(TRANSPORT_CELLULAR); final ArgumentCaptor<LinkProperties> lp = ArgumentCaptor.forClass(LinkProperties.class); mIPv6TetheringCoordinator.updateUpstreamNetworkState(mobileUpstream); verify(firstServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(0), eq(0), verify(firstServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(-1), eq(0), lp.capture()); final LinkProperties v6OnlyLink = lp.getValue(); assertOnlyOneV6AddressAndNoV4(v6OnlyLink); Loading @@ -140,7 +140,7 @@ public class IPv6TetheringCoordinatorTest { mNotifyList.remove(firstServer); mIPv6TetheringCoordinator.removeActiveDownstream(firstServer); verify(firstServer).sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, null); verify(secondServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(0), eq(0), verify(secondServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(-1), eq(0), lp.capture()); final LinkProperties localOnlyLink = lp.getValue(); assertNotNull(localOnlyLink); Loading Loading
packages/Tethering/src/android/net/ip/IpServer.java +6 −7 Original line number Diff line number Diff line Loading @@ -738,7 +738,7 @@ public class IpServer extends StateMachine { // // TODO: Evaluate using a data structure than is more directly suited to // communicating only the relevant information. private void updateUpstreamIPv6LinkProperties(LinkProperties v6only) { private void updateUpstreamIPv6LinkProperties(LinkProperties v6only, int ttlAdjustment) { if (mRaDaemon == null) return; // Avoid unnecessary work on spurious updates. Loading @@ -761,7 +761,7 @@ public class IpServer extends StateMachine { params.mtu = mUsingBpfOffload ? v6only.getMtu() - 16 : v6only.getMtu(); params.hasDefaultRoute = v6only.hasIpv6DefaultRoute(); if (params.hasDefaultRoute) params.hopLimit = getHopLimit(upstreamIface); if (params.hasDefaultRoute) params.hopLimit = getHopLimit(upstreamIface, ttlAdjustment); for (LinkAddress linkAddr : v6only.getLinkAddresses()) { if (linkAddr.getPrefixLength() != RFC7421_PREFIX_LENGTH) continue; Loading Loading @@ -1052,12 +1052,11 @@ public class IpServer extends StateMachine { } } private byte getHopLimit(String upstreamIface) { private byte getHopLimit(String upstreamIface, int adjustTTL) { try { int upstreamHopLimit = Integer.parseUnsignedInt( mNetd.getProcSysNet(INetd.IPV6, INetd.CONF, upstreamIface, "hop_limit")); // Add one hop to account for this forwarding device upstreamHopLimit++; upstreamHopLimit = upstreamHopLimit + adjustTTL; // Cap the hop limit to 255. return (byte) Integer.min(upstreamHopLimit, 255); } catch (Exception e) { Loading Loading @@ -1145,7 +1144,7 @@ public class IpServer extends StateMachine { transitionTo(mUnavailableState); break; case CMD_IPV6_TETHER_UPDATE: updateUpstreamIPv6LinkProperties((LinkProperties) message.obj); updateUpstreamIPv6LinkProperties((LinkProperties) message.obj, message.arg1); break; default: return NOT_HANDLED; Loading Loading @@ -1209,7 +1208,7 @@ public class IpServer extends StateMachine { if (DBG) Log.d(TAG, "Untethered (ifdown)" + mIfaceName); break; case CMD_IPV6_TETHER_UPDATE: updateUpstreamIPv6LinkProperties((LinkProperties) message.obj); updateUpstreamIPv6LinkProperties((LinkProperties) message.obj, message.arg1); sendLinkProperties(); break; case CMD_IP_FORWARDING_ENABLE_ERROR: Loading
packages/Tethering/src/com/android/networkstack/tethering/IPv6TetheringCoordinator.java +18 −1 Original line number Diff line number Diff line Loading @@ -161,11 +161,28 @@ public class IPv6TetheringCoordinator { private void updateIPv6TetheringInterfaces() { for (IpServer ipServer : mNotifyList) { final LinkProperties lp = getInterfaceIPv6LinkProperties(ipServer); ipServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, lp); ipServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, getTtlAdjustment(), 0, lp); break; } } private int getTtlAdjustment() { if (mUpstreamNetworkState == null || mUpstreamNetworkState.networkCapabilities == null) { return 0; } // If upstream is cellular, set the TTL in Router Advertisements to "network-set TTL" - 1 // for carrier requirement. if (mUpstreamNetworkState.networkCapabilities.hasTransport( NetworkCapabilities.TRANSPORT_CELLULAR)) { return -1; } // For other non-cellular upstream, set TTL as "network-set TTL" + 1 to preventing arbitrary // distinction between tethered and untethered traffic. return 1; } private LinkProperties getInterfaceIPv6LinkProperties(IpServer ipServer) { final Downstream ds = findDownstream(ipServer); if (ds == null) return null; Loading
packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java +54 −8 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.net.ip; import static android.net.INetd.IF_STATE_UP; import static android.net.RouteInfo.RTN_UNICAST; import static android.net.TetheringManager.TETHERING_BLUETOOTH; import static android.net.TetheringManager.TETHERING_NCM; import static android.net.TetheringManager.TETHERING_USB; Loading Loading @@ -74,6 +75,7 @@ import android.net.dhcp.IDhcpServer; import android.net.dhcp.IDhcpServerCallbacks; import android.net.ip.IpNeighborMonitor.NeighborEvent; import android.net.ip.IpNeighborMonitor.NeighborEventConsumer; import android.net.ip.RouterAdvertisementDaemon.RaParams; import android.net.util.InterfaceParams; import android.net.util.InterfaceSet; import android.net.util.SharedLog; Loading Loading @@ -196,7 +198,7 @@ public class IpServerTest { if (upstreamIface != null) { LinkProperties lp = new LinkProperties(); lp.setInterfaceName(upstreamIface); dispatchTetherConnectionChanged(upstreamIface, lp); dispatchTetherConnectionChanged(upstreamIface, lp, 0); } reset(mNetd, mCallback); } Loading Loading @@ -694,7 +696,7 @@ public class IpServerTest { InOrder inOrder = inOrder(mNetd); LinkProperties lp = new LinkProperties(); lp.setInterfaceName(UPSTREAM_IFACE2); dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp); dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp, -1); inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX2, neighA, macA)); inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighA, macA)); inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX2, neighB, macB)); Loading @@ -702,7 +704,7 @@ public class IpServerTest { reset(mNetd); // When the upstream is lost, rules are removed. dispatchTetherConnectionChanged(null, null); dispatchTetherConnectionChanged(null, null, 0); verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX2, neighA, macA)); verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX2, neighB, macB)); reset(mNetd); Loading @@ -715,19 +717,19 @@ public class IpServerTest { // Rules can be added again once upstream IPv6 connectivity is available. lp.setInterfaceName(UPSTREAM_IFACE); dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp); dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1); recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB); verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighB, macB)); verify(mNetd, never()).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighA, macA)); // If upstream IPv6 connectivity is lost, rules are removed. reset(mNetd); dispatchTetherConnectionChanged(UPSTREAM_IFACE, null); dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0); verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighB, macB)); // When the interface goes down, rules are removed. lp.setInterfaceName(UPSTREAM_IFACE); dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp); dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1); recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA); recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB); verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighA, macA)); Loading Loading @@ -788,6 +790,49 @@ public class IpServerTest { verify(mIpNeighborMonitor, never()).start(); } private LinkProperties buildIpv6OnlyLinkProperties(final String iface) { final LinkProperties linkProp = new LinkProperties(); linkProp.setInterfaceName(iface); linkProp.addLinkAddress(new LinkAddress("2001:db8::1/64")); linkProp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, iface, RTN_UNICAST)); final InetAddress dns = InetAddresses.parseNumericAddress("2001:4860:4860::8888"); linkProp.addDnsServer(dns); return linkProp; } @Test public void testAdjustTtlValue() throws Exception { final ArgumentCaptor<RaParams> raParamsCaptor = ArgumentCaptor.forClass(RaParams.class); initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE); verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture()); final RaParams noV6Params = raParamsCaptor.getValue(); assertEquals(65, noV6Params.hopLimit); reset(mRaDaemon); when(mNetd.getProcSysNet( INetd.IPV6, INetd.CONF, UPSTREAM_IFACE, "hop_limit")).thenReturn("64"); final LinkProperties lp = buildIpv6OnlyLinkProperties(UPSTREAM_IFACE); dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 1); verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture()); final RaParams nonCellularParams = raParamsCaptor.getValue(); assertEquals(65, nonCellularParams.hopLimit); reset(mRaDaemon); dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0); verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture()); final RaParams noUpstream = raParamsCaptor.getValue(); assertEquals(65, nonCellularParams.hopLimit); reset(mRaDaemon); dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1); verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture()); final RaParams cellularParams = raParamsCaptor.getValue(); assertEquals(63, cellularParams.hopLimit); reset(mRaDaemon); } private void assertDhcpServingParams(final DhcpServingParamsParcel params, final IpPrefix prefix) { // Last address byte is random Loading Loading @@ -838,9 +883,10 @@ public class IpServerTest { * @param upstreamIface String name of upstream interface (or null) * @param v6lp IPv6 LinkProperties of the upstream interface, or null for an IPv4-only upstream. */ private void dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp) { private void dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp, int ttlAdjustment) { dispatchTetherConnectionChanged(upstreamIface); mIpServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, v6lp); mIpServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, ttlAdjustment, 0, v6lp); mLooper.dispatchAll(); } Loading
packages/Tethering/tests/unit/src/com/android/networkstack/tethering/IPv6TetheringCoordinatorTest.java +2 −2 Original line number Diff line number Diff line Loading @@ -128,7 +128,7 @@ public class IPv6TetheringCoordinatorTest { final UpstreamNetworkState mobileUpstream = createDualStackUpstream(TRANSPORT_CELLULAR); final ArgumentCaptor<LinkProperties> lp = ArgumentCaptor.forClass(LinkProperties.class); mIPv6TetheringCoordinator.updateUpstreamNetworkState(mobileUpstream); verify(firstServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(0), eq(0), verify(firstServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(-1), eq(0), lp.capture()); final LinkProperties v6OnlyLink = lp.getValue(); assertOnlyOneV6AddressAndNoV4(v6OnlyLink); Loading @@ -140,7 +140,7 @@ public class IPv6TetheringCoordinatorTest { mNotifyList.remove(firstServer); mIPv6TetheringCoordinator.removeActiveDownstream(firstServer); verify(firstServer).sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, null); verify(secondServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(0), eq(0), verify(secondServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(-1), eq(0), lp.capture()); final LinkProperties localOnlyLink = lp.getValue(); assertNotNull(localOnlyLink); Loading