Loading services/core/java/com/android/server/connectivity/tethering/OffloadController.java +34 −19 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; Loading @@ -73,6 +74,8 @@ public class OffloadController { private static final String ANYIP = "0.0.0.0"; private static final ForwardedStats EMPTY_STATS = new ForwardedStats(); private static enum UpdateType { IF_NEEDED, FORCE }; private final Handler mHandler; private final OffloadHardwareInterface mHwInterface; private final ContentResolver mContentResolver; Loading Loading @@ -185,8 +188,8 @@ public class OffloadController { updateStatsForAllUpstreams(); forceTetherStatsPoll(); // [2] (Re)Push all state. // TODO: computeAndPushLocalPrefixes() // TODO: push all downstream state. computeAndPushLocalPrefixes(UpdateType.FORCE); pushAllDownstreamState(); pushUpstreamParameters(null); } Loading Loading @@ -319,7 +322,7 @@ public class OffloadController { } private boolean maybeUpdateDataLimit(String iface) { // setDataLimit may only be called while offload is occuring on this upstream. // setDataLimit may only be called while offload is occurring on this upstream. if (!started() || !TextUtils.equals(iface, currentUpstreamInterface())) { return true; } Loading Loading @@ -368,15 +371,15 @@ public class OffloadController { // upstream parameters fails (probably just wait for a subsequent // onOffloadEvent() callback to tell us offload is available again and // then reapply all state). computeAndPushLocalPrefixes(); computeAndPushLocalPrefixes(UpdateType.IF_NEEDED); pushUpstreamParameters(prevUpstream); } public void setLocalPrefixes(Set<IpPrefix> localPrefixes) { if (!started()) return; mExemptPrefixes = localPrefixes; computeAndPushLocalPrefixes(); if (!started()) return; computeAndPushLocalPrefixes(UpdateType.IF_NEEDED); } public void notifyDownstreamLinkProperties(LinkProperties lp) { Loading @@ -385,25 +388,36 @@ public class OffloadController { if (Objects.equals(oldLp, lp)) return; if (!started()) return; pushDownstreamState(oldLp, lp); } final List<RouteInfo> oldRoutes = (oldLp != null) ? oldLp.getRoutes() : new ArrayList<>(); final List<RouteInfo> newRoutes = lp.getRoutes(); private void pushDownstreamState(LinkProperties oldLp, LinkProperties newLp) { final String ifname = newLp.getInterfaceName(); final List<RouteInfo> oldRoutes = (oldLp != null) ? oldLp.getRoutes() : Collections.EMPTY_LIST; final List<RouteInfo> newRoutes = newLp.getRoutes(); // For each old route, if not in new routes: remove. for (RouteInfo oldRoute : oldRoutes) { if (shouldIgnoreDownstreamRoute(oldRoute)) continue; if (!newRoutes.contains(oldRoute)) { mHwInterface.removeDownstreamPrefix(ifname, oldRoute.getDestination().toString()); for (RouteInfo ri : oldRoutes) { if (shouldIgnoreDownstreamRoute(ri)) continue; if (!newRoutes.contains(ri)) { mHwInterface.removeDownstreamPrefix(ifname, ri.getDestination().toString()); } } // For each new route, if not in old routes: add. for (RouteInfo newRoute : newRoutes) { if (shouldIgnoreDownstreamRoute(newRoute)) continue; if (!oldRoutes.contains(newRoute)) { mHwInterface.addDownstreamPrefix(ifname, newRoute.getDestination().toString()); for (RouteInfo ri : newRoutes) { if (shouldIgnoreDownstreamRoute(ri)) continue; if (!oldRoutes.contains(ri)) { mHwInterface.addDownstreamPrefix(ifname, ri.getDestination().toString()); } } } private void pushAllDownstreamState() { for (LinkProperties lp : mDownstreams.values()) { pushDownstreamState(null, lp); } } public void removeDownstreamInterface(String ifname) { Loading Loading @@ -484,10 +498,11 @@ public class OffloadController { return success; } private boolean computeAndPushLocalPrefixes() { private boolean computeAndPushLocalPrefixes(UpdateType how) { final boolean force = (how == UpdateType.FORCE); final Set<String> localPrefixStrs = computeLocalPrefixStrings( mExemptPrefixes, mUpstreamLinkProperties); if (mLastLocalPrefixStrs.equals(localPrefixStrs)) return true; if (!force && mLastLocalPrefixStrs.equals(localPrefixStrs)) return true; mLastLocalPrefixStrs = localPrefixStrs; return mHwInterface.setLocalPrefixes(new ArrayList<>(localPrefixStrs)); Loading tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java +41 −1 Original line number Diff line number Diff line Loading @@ -671,6 +671,35 @@ public class OffloadControllerTest { offload.setUpstreamLinkProperties(upstreamLp); } // Pretend that some local prefixes and downstreams have been added // (and removed, for good measure). final Set<IpPrefix> minimumLocalPrefixes = new HashSet<>(); for (String s : new String[]{ "127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64"}) { minimumLocalPrefixes.add(new IpPrefix(s)); } offload.setLocalPrefixes(minimumLocalPrefixes); final LinkProperties usbLinkProperties = new LinkProperties(); usbLinkProperties.setInterfaceName(RNDIS0); usbLinkProperties.addLinkAddress(new LinkAddress("192.168.42.1/24")); usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(USB_PREFIX))); offload.notifyDownstreamLinkProperties(usbLinkProperties); final LinkProperties wifiLinkProperties = new LinkProperties(); wifiLinkProperties.setInterfaceName(WLAN0); wifiLinkProperties.addLinkAddress(new LinkAddress("192.168.43.1/24")); wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix(WIFI_PREFIX))); wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix(IPV6_LINKLOCAL))); // Use a benchmark prefix (RFC 5180 + erratum), since the documentation // prefix is included in the excluded prefix list. wifiLinkProperties.addLinkAddress(new LinkAddress("2001:2::1/64")); wifiLinkProperties.addLinkAddress(new LinkAddress("2001:2::2/64")); wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix("2001:2::/64"))); offload.notifyDownstreamLinkProperties(wifiLinkProperties); offload.removeDownstreamInterface(RNDIS0); // Clear invocation history, especially the getForwardedStats() calls // that happen with setUpstreamParameters(). clearInvocations(mHardware); Loading @@ -685,6 +714,17 @@ public class OffloadControllerTest { verifyNoMoreInteractions(mNMService); // TODO: verify local prefixes and downstreams are also pushed to the HAL. verify(mHardware, times(1)).setLocalPrefixes(mStringArrayCaptor.capture()); ArrayList<String> localPrefixes = mStringArrayCaptor.getValue(); assertEquals(4, localPrefixes.size()); assertArrayListContains(localPrefixes, // TODO: The logic to find and exclude downstream IP prefixes // is currently in Tethering's OffloadWrapper but must be moved // into OffloadController proper. After this, also check for: // "192.168.43.1/32", "2001:2::1/128", "2001:2::2/128" "127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64"); verify(mHardware, times(1)).addDownstreamPrefix(WLAN0, "192.168.43.0/24"); verify(mHardware, times(1)).addDownstreamPrefix(WLAN0, "2001:2::/64"); verify(mHardware, times(1)).setUpstreamParameters(eq(RMNET0), any(), any(), any()); verify(mHardware, times(1)).setDataLimit(eq(RMNET0), anyLong()); verifyNoMoreInteractions(mHardware); Loading @@ -692,7 +732,7 @@ public class OffloadControllerTest { private static void assertArrayListContains(ArrayList<String> list, String... elems) { for (String element : elems) { assertTrue(list.contains(element)); assertTrue(element + " not in list", list.contains(element)); } } } Loading
services/core/java/com/android/server/connectivity/tethering/OffloadController.java +34 −19 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; Loading @@ -73,6 +74,8 @@ public class OffloadController { private static final String ANYIP = "0.0.0.0"; private static final ForwardedStats EMPTY_STATS = new ForwardedStats(); private static enum UpdateType { IF_NEEDED, FORCE }; private final Handler mHandler; private final OffloadHardwareInterface mHwInterface; private final ContentResolver mContentResolver; Loading Loading @@ -185,8 +188,8 @@ public class OffloadController { updateStatsForAllUpstreams(); forceTetherStatsPoll(); // [2] (Re)Push all state. // TODO: computeAndPushLocalPrefixes() // TODO: push all downstream state. computeAndPushLocalPrefixes(UpdateType.FORCE); pushAllDownstreamState(); pushUpstreamParameters(null); } Loading Loading @@ -319,7 +322,7 @@ public class OffloadController { } private boolean maybeUpdateDataLimit(String iface) { // setDataLimit may only be called while offload is occuring on this upstream. // setDataLimit may only be called while offload is occurring on this upstream. if (!started() || !TextUtils.equals(iface, currentUpstreamInterface())) { return true; } Loading Loading @@ -368,15 +371,15 @@ public class OffloadController { // upstream parameters fails (probably just wait for a subsequent // onOffloadEvent() callback to tell us offload is available again and // then reapply all state). computeAndPushLocalPrefixes(); computeAndPushLocalPrefixes(UpdateType.IF_NEEDED); pushUpstreamParameters(prevUpstream); } public void setLocalPrefixes(Set<IpPrefix> localPrefixes) { if (!started()) return; mExemptPrefixes = localPrefixes; computeAndPushLocalPrefixes(); if (!started()) return; computeAndPushLocalPrefixes(UpdateType.IF_NEEDED); } public void notifyDownstreamLinkProperties(LinkProperties lp) { Loading @@ -385,25 +388,36 @@ public class OffloadController { if (Objects.equals(oldLp, lp)) return; if (!started()) return; pushDownstreamState(oldLp, lp); } final List<RouteInfo> oldRoutes = (oldLp != null) ? oldLp.getRoutes() : new ArrayList<>(); final List<RouteInfo> newRoutes = lp.getRoutes(); private void pushDownstreamState(LinkProperties oldLp, LinkProperties newLp) { final String ifname = newLp.getInterfaceName(); final List<RouteInfo> oldRoutes = (oldLp != null) ? oldLp.getRoutes() : Collections.EMPTY_LIST; final List<RouteInfo> newRoutes = newLp.getRoutes(); // For each old route, if not in new routes: remove. for (RouteInfo oldRoute : oldRoutes) { if (shouldIgnoreDownstreamRoute(oldRoute)) continue; if (!newRoutes.contains(oldRoute)) { mHwInterface.removeDownstreamPrefix(ifname, oldRoute.getDestination().toString()); for (RouteInfo ri : oldRoutes) { if (shouldIgnoreDownstreamRoute(ri)) continue; if (!newRoutes.contains(ri)) { mHwInterface.removeDownstreamPrefix(ifname, ri.getDestination().toString()); } } // For each new route, if not in old routes: add. for (RouteInfo newRoute : newRoutes) { if (shouldIgnoreDownstreamRoute(newRoute)) continue; if (!oldRoutes.contains(newRoute)) { mHwInterface.addDownstreamPrefix(ifname, newRoute.getDestination().toString()); for (RouteInfo ri : newRoutes) { if (shouldIgnoreDownstreamRoute(ri)) continue; if (!oldRoutes.contains(ri)) { mHwInterface.addDownstreamPrefix(ifname, ri.getDestination().toString()); } } } private void pushAllDownstreamState() { for (LinkProperties lp : mDownstreams.values()) { pushDownstreamState(null, lp); } } public void removeDownstreamInterface(String ifname) { Loading Loading @@ -484,10 +498,11 @@ public class OffloadController { return success; } private boolean computeAndPushLocalPrefixes() { private boolean computeAndPushLocalPrefixes(UpdateType how) { final boolean force = (how == UpdateType.FORCE); final Set<String> localPrefixStrs = computeLocalPrefixStrings( mExemptPrefixes, mUpstreamLinkProperties); if (mLastLocalPrefixStrs.equals(localPrefixStrs)) return true; if (!force && mLastLocalPrefixStrs.equals(localPrefixStrs)) return true; mLastLocalPrefixStrs = localPrefixStrs; return mHwInterface.setLocalPrefixes(new ArrayList<>(localPrefixStrs)); Loading
tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java +41 −1 Original line number Diff line number Diff line Loading @@ -671,6 +671,35 @@ public class OffloadControllerTest { offload.setUpstreamLinkProperties(upstreamLp); } // Pretend that some local prefixes and downstreams have been added // (and removed, for good measure). final Set<IpPrefix> minimumLocalPrefixes = new HashSet<>(); for (String s : new String[]{ "127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64"}) { minimumLocalPrefixes.add(new IpPrefix(s)); } offload.setLocalPrefixes(minimumLocalPrefixes); final LinkProperties usbLinkProperties = new LinkProperties(); usbLinkProperties.setInterfaceName(RNDIS0); usbLinkProperties.addLinkAddress(new LinkAddress("192.168.42.1/24")); usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(USB_PREFIX))); offload.notifyDownstreamLinkProperties(usbLinkProperties); final LinkProperties wifiLinkProperties = new LinkProperties(); wifiLinkProperties.setInterfaceName(WLAN0); wifiLinkProperties.addLinkAddress(new LinkAddress("192.168.43.1/24")); wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix(WIFI_PREFIX))); wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix(IPV6_LINKLOCAL))); // Use a benchmark prefix (RFC 5180 + erratum), since the documentation // prefix is included in the excluded prefix list. wifiLinkProperties.addLinkAddress(new LinkAddress("2001:2::1/64")); wifiLinkProperties.addLinkAddress(new LinkAddress("2001:2::2/64")); wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix("2001:2::/64"))); offload.notifyDownstreamLinkProperties(wifiLinkProperties); offload.removeDownstreamInterface(RNDIS0); // Clear invocation history, especially the getForwardedStats() calls // that happen with setUpstreamParameters(). clearInvocations(mHardware); Loading @@ -685,6 +714,17 @@ public class OffloadControllerTest { verifyNoMoreInteractions(mNMService); // TODO: verify local prefixes and downstreams are also pushed to the HAL. verify(mHardware, times(1)).setLocalPrefixes(mStringArrayCaptor.capture()); ArrayList<String> localPrefixes = mStringArrayCaptor.getValue(); assertEquals(4, localPrefixes.size()); assertArrayListContains(localPrefixes, // TODO: The logic to find and exclude downstream IP prefixes // is currently in Tethering's OffloadWrapper but must be moved // into OffloadController proper. After this, also check for: // "192.168.43.1/32", "2001:2::1/128", "2001:2::2/128" "127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64"); verify(mHardware, times(1)).addDownstreamPrefix(WLAN0, "192.168.43.0/24"); verify(mHardware, times(1)).addDownstreamPrefix(WLAN0, "2001:2::/64"); verify(mHardware, times(1)).setUpstreamParameters(eq(RMNET0), any(), any(), any()); verify(mHardware, times(1)).setDataLimit(eq(RMNET0), anyLong()); verifyNoMoreInteractions(mHardware); Loading @@ -692,7 +732,7 @@ public class OffloadControllerTest { private static void assertArrayListContains(ArrayList<String> list, String... elems) { for (String element : elems) { assertTrue(list.contains(element)); assertTrue(element + " not in list", list.contains(element)); } } }