Loading services/core/java/com/android/server/connectivity/Tethering.java +92 −36 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import android.net.ConnectivityManager; import android.net.INetworkPolicyManager; import android.net.INetworkStatsService; import android.net.IpPrefix; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; Loading Loading @@ -1196,6 +1197,7 @@ public class Tethering extends BaseNetworkObserver { // to tear itself down. private final ArrayList<TetherInterfaceStateMachine> mNotifyList; private final IPv6TetheringCoordinator mIPv6TetheringCoordinator; private final OffloadWrapper mOffload; private static final int UPSTREAM_SETTLE_TIME_MS = 10000; Loading @@ -1220,33 +1222,11 @@ public class Tethering extends BaseNetworkObserver { mNotifyList = new ArrayList<>(); mIPv6TetheringCoordinator = new IPv6TetheringCoordinator(mNotifyList, mLog); mOffload = new OffloadWrapper(); setInitialState(mInitialState); } private void startOffloadController() { mOffloadController.start(); sendOffloadExemptPrefixes(); } private void sendOffloadExemptPrefixes() { sendOffloadExemptPrefixes(mUpstreamNetworkMonitor.getLocalPrefixes()); } private void sendOffloadExemptPrefixes(Set<IpPrefix> localPrefixes) { // Add in well-known minimum set. PrefixUtils.addNonForwardablePrefixes(localPrefixes); // Add tragically hardcoded prefixes. localPrefixes.add(PrefixUtils.DEFAULT_WIFI_P2P_PREFIX); // Add prefixes for all downstreams, regardless of IP serving mode. for (TetherInterfaceStateMachine tism : mNotifyList) { localPrefixes.addAll(PrefixUtils.localPrefixesFrom(tism.linkProperties())); } mOffloadController.setLocalPrefixes(localPrefixes); } class InitialState extends State { @Override public boolean processMessage(Message message) { Loading Loading @@ -1404,7 +1384,7 @@ public class Tethering extends BaseNetworkObserver { protected void handleNewUpstreamNetworkState(NetworkState ns) { mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns); mOffloadController.setUpstreamLinkProperties((ns != null) ? ns.linkProperties : null); mOffload.updateUpstreamNetworkState(ns); } private void handleInterfaceServingStateActive(int mode, TetherInterfaceStateMachine who) { Loading @@ -1414,9 +1394,12 @@ public class Tethering extends BaseNetworkObserver { } if (mode == IControlsTethering.STATE_TETHERED) { // No need to notify OffloadController just yet as there are no // "offload-able" prefixes to pass along. This will handled // when the TISM informs Tethering of its LinkProperties. mForwardedDownstreams.add(who); } else { mOffloadController.removeDownstreamInterface(who.interfaceName()); mOffload.excludeDownstreamInterface(who.interfaceName()); mForwardedDownstreams.remove(who); } Loading @@ -1441,7 +1424,7 @@ public class Tethering extends BaseNetworkObserver { private void handleInterfaceServingStateInactive(TetherInterfaceStateMachine who) { mNotifyList.remove(who); mIPv6TetheringCoordinator.removeActiveDownstream(who); mOffloadController.removeDownstreamInterface(who.interfaceName()); mOffload.excludeDownstreamInterface(who.interfaceName()); mForwardedDownstreams.remove(who); // If this is a Wi-Fi interface, tell WifiManager of any errors. Loading @@ -1455,7 +1438,7 @@ public class Tethering extends BaseNetworkObserver { private void handleUpstreamNetworkMonitorCallback(int arg1, Object o) { if (arg1 == UpstreamNetworkMonitor.NOTIFY_LOCAL_PREFIXES) { sendOffloadExemptPrefixes((Set<IpPrefix>) o); mOffload.sendOffloadExemptPrefixes((Set<IpPrefix>) o); return; } Loading Loading @@ -1525,7 +1508,7 @@ public class Tethering extends BaseNetworkObserver { // TODO: De-duplicate with updateUpstreamWanted() below. if (upstreamWanted()) { mUpstreamWanted = true; startOffloadController(); mOffload.start(); chooseUpstreamType(true); mTryCell = false; } Loading @@ -1533,7 +1516,7 @@ public class Tethering extends BaseNetworkObserver { @Override public void exit() { mOffloadController.stop(); mOffload.stop(); mUpstreamNetworkMonitor.stop(); mSimChange.stopListening(); notifyDownstreamsOfNewUpstreamIface(null); Loading @@ -1545,9 +1528,9 @@ public class Tethering extends BaseNetworkObserver { mUpstreamWanted = upstreamWanted(); if (mUpstreamWanted != previousUpstreamWanted) { if (mUpstreamWanted) { startOffloadController(); mOffload.start(); } else { mOffloadController.stop(); mOffload.stop(); } } return previousUpstreamWanted; Loading Loading @@ -1602,12 +1585,9 @@ public class Tethering extends BaseNetworkObserver { case EVENT_IFACE_UPDATE_LINKPROPERTIES: { final LinkProperties newLp = (LinkProperties) message.obj; if (message.arg1 == IControlsTethering.STATE_TETHERED) { mOffloadController.notifyDownstreamLinkProperties(newLp); mOffload.updateDownstreamLinkProperties(newLp); } else { mOffloadController.removeDownstreamInterface(newLp.getInterfaceName()); // Another interface might be in local-only hotspot mode; // resend all local prefixes to the OffloadController. sendOffloadExemptPrefixes(); mOffload.excludeDownstreamInterface(newLp.getInterfaceName()); } break; } Loading Loading @@ -1722,6 +1702,82 @@ public class Tethering extends BaseNetworkObserver { } catch (Exception e) {} } } // A wrapper class to handle multiple situations where several calls to // the OffloadController need to happen together. // // TODO: This suggests that the interface between OffloadController and // Tethering is in need of improvement. Refactor these calls into the // OffloadController implementation. class OffloadWrapper { public void start() { mOffloadController.start(); sendOffloadExemptPrefixes(); } public void stop() { mOffloadController.stop(); } public void updateUpstreamNetworkState(NetworkState ns) { mOffloadController.setUpstreamLinkProperties( (ns != null) ? ns.linkProperties : null); } public void updateDownstreamLinkProperties(LinkProperties newLp) { // Update the list of offload-exempt prefixes before adding // new prefixes on downstream interfaces to the offload HAL. sendOffloadExemptPrefixes(); mOffloadController.notifyDownstreamLinkProperties(newLp); } public void excludeDownstreamInterface(String ifname) { // This and other interfaces may be in local-only hotspot mode; // resend all local prefixes to the OffloadController. sendOffloadExemptPrefixes(); mOffloadController.removeDownstreamInterface(ifname); } public void sendOffloadExemptPrefixes() { sendOffloadExemptPrefixes(mUpstreamNetworkMonitor.getLocalPrefixes()); } public void sendOffloadExemptPrefixes(final Set<IpPrefix> localPrefixes) { // Add in well-known minimum set. PrefixUtils.addNonForwardablePrefixes(localPrefixes); // Add tragically hardcoded prefixes. localPrefixes.add(PrefixUtils.DEFAULT_WIFI_P2P_PREFIX); // Maybe add prefixes or addresses for downstreams, depending on // the IP serving mode of each. for (TetherInterfaceStateMachine tism : mNotifyList) { final LinkProperties lp = tism.linkProperties(); switch (tism.servingMode()) { case IControlsTethering.STATE_UNAVAILABLE: case IControlsTethering.STATE_AVAILABLE: // No usable LinkProperties in these states. continue; case IControlsTethering.STATE_TETHERED: // Only add IPv4 /32 and IPv6 /128 prefixes. The // directly-connected prefixes will be sent as // downstream "offload-able" prefixes. for (LinkAddress addr : lp.getAllLinkAddresses()) { final InetAddress ip = addr.getAddress(); if (ip.isLinkLocalAddress()) continue; localPrefixes.add(PrefixUtils.ipAddressAsPrefix(ip)); } break; case IControlsTethering.STATE_LOCAL_ONLY: // Add prefixes covering all local IPs. localPrefixes.addAll(PrefixUtils.localPrefixesFrom(lp)); break; } } mOffloadController.setLocalPrefixes(localPrefixes); } } } @Override Loading services/core/java/com/android/server/connectivity/tethering/OffloadController.java +46 −10 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ import java.net.InetAddress; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; Loading @@ -69,6 +70,7 @@ public class OffloadController { private final INetworkManagementService mNms; private final ITetheringStatsProvider mStatsProvider; private final SharedLog mLog; private final HashMap<String, LinkProperties> mDownstreams; private boolean mConfigInitialized; private boolean mControlInitialized; private LinkProperties mUpstreamLinkProperties; Loading Loading @@ -100,6 +102,7 @@ public class OffloadController { mNms = nms; mStatsProvider = new OffloadTetheringStatsProvider(); mLog = log.forSubComponent(TAG); mDownstreams = new HashMap<>(); mExemptPrefixes = new HashSet<>(); mLastLocalPrefixStrs = new HashSet<>(); Loading Loading @@ -257,6 +260,11 @@ public class OffloadController { } } private String currentUpstreamInterface() { return (mUpstreamLinkProperties != null) ? mUpstreamLinkProperties.getInterfaceName() : null; } private void maybeUpdateStats(String iface) { if (TextUtils.isEmpty(iface)) { return; Loading @@ -281,9 +289,7 @@ public class OffloadController { private boolean maybeUpdateDataLimit(String iface) { // setDataLimit may only be called while offload is occuring on this upstream. if (!started() || mUpstreamLinkProperties == null || !TextUtils.equals(iface, mUpstreamLinkProperties.getInterfaceName())) { if (!started() || !TextUtils.equals(iface, currentUpstreamInterface())) { return true; } Loading @@ -296,9 +302,7 @@ public class OffloadController { } private void updateStatsForCurrentUpstream() { if (mUpstreamLinkProperties != null) { maybeUpdateStats(mUpstreamLinkProperties.getInterfaceName()); } maybeUpdateStats(currentUpstreamInterface()); } public void setUpstreamLinkProperties(LinkProperties lp) { Loading @@ -325,17 +329,42 @@ public class OffloadController { } public void notifyDownstreamLinkProperties(LinkProperties lp) { final String ifname = lp.getInterfaceName(); final LinkProperties oldLp = mDownstreams.put(ifname, new LinkProperties(lp)); if (Objects.equals(oldLp, lp)) return; if (!started()) return; // TODO: Cache LinkProperties on a per-ifname basis and compute the // deltas, calling addDownstream()/removeDownstream() accordingly. final List<RouteInfo> oldRoutes = (oldLp != null) ? oldLp.getRoutes() : new ArrayList<>(); final List<RouteInfo> newRoutes = lp.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 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()); } } } public void removeDownstreamInterface(String ifname) { final LinkProperties lp = mDownstreams.remove(ifname); if (lp == null) return; if (!started()) return; // TODO: Check cache for LinkProperties of ifname and, if present, // call removeDownstream() accordingly. for (RouteInfo route : lp.getRoutes()) { if (shouldIgnoreDownstreamRoute(route)) continue; mHwInterface.removeDownstreamPrefix(ifname, route.getDestination().toString()); } } private boolean isOffloadDisabled() { Loading Loading @@ -442,6 +471,13 @@ public class OffloadController { return localPrefixStrs; } private static boolean shouldIgnoreDownstreamRoute(RouteInfo route) { // Ignore any link-local routes. if (!route.getDestinationLinkAddress().isGlobalPreferred()) return true; return false; } public void dump(IndentingPrintWriter pw) { if (isOffloadDisabled()) { pw.println("Offload disabled"); Loading services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java +38 −0 Original line number Diff line number Diff line Loading @@ -236,6 +236,44 @@ public class OffloadHardwareInterface { return results.success; } public boolean addDownstreamPrefix(String ifname, String prefix) { final String logmsg = String.format("addDownstreamPrefix(%s, %s)", ifname, prefix); final CbResults results = new CbResults(); try { mOffloadControl.addDownstream(ifname, prefix, (boolean success, String errMsg) -> { results.success = success; results.errMsg = errMsg; }); } catch (RemoteException e) { record(logmsg, e); return false; } record(logmsg, results); return results.success; } public boolean removeDownstreamPrefix(String ifname, String prefix) { final String logmsg = String.format("removeDownstreamPrefix(%s, %s)", ifname, prefix); final CbResults results = new CbResults(); try { mOffloadControl.removeDownstream(ifname, prefix, (boolean success, String errMsg) -> { results.success = success; results.errMsg = errMsg; }); } catch (RemoteException e) { record(logmsg, e); return false; } record(logmsg, results); return results.success; } private void record(String msg, Throwable t) { mLog.e(msg + YIELDS + "exception: " + t); } Loading services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java +5 −0 Original line number Diff line number Diff line Loading @@ -115,6 +115,7 @@ public class TetherInterfaceStateMachine extends StateMachine { private final LinkProperties mLinkProperties; private int mLastError; private int mServingMode; private String mMyUpstreamIfaceName; // may change over time private NetworkInterface mNetworkInterface; private byte[] mHwAddr; Loading Loading @@ -142,6 +143,7 @@ public class TetherInterfaceStateMachine extends StateMachine { mLinkProperties = new LinkProperties(); resetLinkProperties(); mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR; mServingMode = IControlsTethering.STATE_AVAILABLE; mInitialState = new InitialState(); mLocalHotspotState = new LocalHotspotState(); Loading @@ -161,6 +163,8 @@ public class TetherInterfaceStateMachine extends StateMachine { public int lastError() { return mLastError; } public int servingMode() { return mServingMode; } public LinkProperties linkProperties() { return new LinkProperties(mLinkProperties); } public void stop() { sendMessage(CMD_INTERFACE_DOWN); } Loading Loading @@ -448,6 +452,7 @@ public class TetherInterfaceStateMachine extends StateMachine { } private void sendInterfaceState(int newInterfaceState) { mServingMode = newInterfaceState; mTetherController.updateInterfaceState( TetherInterfaceStateMachine.this, newInterfaceState, mLastError); sendLinkProperties(); Loading services/net/java/android/net/util/NetworkConstants.java +2 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,7 @@ public final class NetworkConstants { public static final int IPV4_PROTOCOL_OFFSET = 9; public static final int IPV4_SRC_ADDR_OFFSET = 12; public static final int IPV4_DST_ADDR_OFFSET = 16; public static final int IPV4_ADDR_BITS = 32; public static final int IPV4_ADDR_LEN = 4; /** Loading @@ -99,6 +100,7 @@ public final class NetworkConstants { public static final int IPV6_PROTOCOL_OFFSET = 6; public static final int IPV6_SRC_ADDR_OFFSET = 8; public static final int IPV6_DST_ADDR_OFFSET = 24; public static final int IPV6_ADDR_BITS = 128; public static final int IPV6_ADDR_LEN = 16; public static final int IPV6_MIN_MTU = 1280; public static final int RFC7421_PREFIX_LENGTH = 64; Loading Loading
services/core/java/com/android/server/connectivity/Tethering.java +92 −36 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import android.net.ConnectivityManager; import android.net.INetworkPolicyManager; import android.net.INetworkStatsService; import android.net.IpPrefix; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; Loading Loading @@ -1196,6 +1197,7 @@ public class Tethering extends BaseNetworkObserver { // to tear itself down. private final ArrayList<TetherInterfaceStateMachine> mNotifyList; private final IPv6TetheringCoordinator mIPv6TetheringCoordinator; private final OffloadWrapper mOffload; private static final int UPSTREAM_SETTLE_TIME_MS = 10000; Loading @@ -1220,33 +1222,11 @@ public class Tethering extends BaseNetworkObserver { mNotifyList = new ArrayList<>(); mIPv6TetheringCoordinator = new IPv6TetheringCoordinator(mNotifyList, mLog); mOffload = new OffloadWrapper(); setInitialState(mInitialState); } private void startOffloadController() { mOffloadController.start(); sendOffloadExemptPrefixes(); } private void sendOffloadExemptPrefixes() { sendOffloadExemptPrefixes(mUpstreamNetworkMonitor.getLocalPrefixes()); } private void sendOffloadExemptPrefixes(Set<IpPrefix> localPrefixes) { // Add in well-known minimum set. PrefixUtils.addNonForwardablePrefixes(localPrefixes); // Add tragically hardcoded prefixes. localPrefixes.add(PrefixUtils.DEFAULT_WIFI_P2P_PREFIX); // Add prefixes for all downstreams, regardless of IP serving mode. for (TetherInterfaceStateMachine tism : mNotifyList) { localPrefixes.addAll(PrefixUtils.localPrefixesFrom(tism.linkProperties())); } mOffloadController.setLocalPrefixes(localPrefixes); } class InitialState extends State { @Override public boolean processMessage(Message message) { Loading Loading @@ -1404,7 +1384,7 @@ public class Tethering extends BaseNetworkObserver { protected void handleNewUpstreamNetworkState(NetworkState ns) { mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns); mOffloadController.setUpstreamLinkProperties((ns != null) ? ns.linkProperties : null); mOffload.updateUpstreamNetworkState(ns); } private void handleInterfaceServingStateActive(int mode, TetherInterfaceStateMachine who) { Loading @@ -1414,9 +1394,12 @@ public class Tethering extends BaseNetworkObserver { } if (mode == IControlsTethering.STATE_TETHERED) { // No need to notify OffloadController just yet as there are no // "offload-able" prefixes to pass along. This will handled // when the TISM informs Tethering of its LinkProperties. mForwardedDownstreams.add(who); } else { mOffloadController.removeDownstreamInterface(who.interfaceName()); mOffload.excludeDownstreamInterface(who.interfaceName()); mForwardedDownstreams.remove(who); } Loading @@ -1441,7 +1424,7 @@ public class Tethering extends BaseNetworkObserver { private void handleInterfaceServingStateInactive(TetherInterfaceStateMachine who) { mNotifyList.remove(who); mIPv6TetheringCoordinator.removeActiveDownstream(who); mOffloadController.removeDownstreamInterface(who.interfaceName()); mOffload.excludeDownstreamInterface(who.interfaceName()); mForwardedDownstreams.remove(who); // If this is a Wi-Fi interface, tell WifiManager of any errors. Loading @@ -1455,7 +1438,7 @@ public class Tethering extends BaseNetworkObserver { private void handleUpstreamNetworkMonitorCallback(int arg1, Object o) { if (arg1 == UpstreamNetworkMonitor.NOTIFY_LOCAL_PREFIXES) { sendOffloadExemptPrefixes((Set<IpPrefix>) o); mOffload.sendOffloadExemptPrefixes((Set<IpPrefix>) o); return; } Loading Loading @@ -1525,7 +1508,7 @@ public class Tethering extends BaseNetworkObserver { // TODO: De-duplicate with updateUpstreamWanted() below. if (upstreamWanted()) { mUpstreamWanted = true; startOffloadController(); mOffload.start(); chooseUpstreamType(true); mTryCell = false; } Loading @@ -1533,7 +1516,7 @@ public class Tethering extends BaseNetworkObserver { @Override public void exit() { mOffloadController.stop(); mOffload.stop(); mUpstreamNetworkMonitor.stop(); mSimChange.stopListening(); notifyDownstreamsOfNewUpstreamIface(null); Loading @@ -1545,9 +1528,9 @@ public class Tethering extends BaseNetworkObserver { mUpstreamWanted = upstreamWanted(); if (mUpstreamWanted != previousUpstreamWanted) { if (mUpstreamWanted) { startOffloadController(); mOffload.start(); } else { mOffloadController.stop(); mOffload.stop(); } } return previousUpstreamWanted; Loading Loading @@ -1602,12 +1585,9 @@ public class Tethering extends BaseNetworkObserver { case EVENT_IFACE_UPDATE_LINKPROPERTIES: { final LinkProperties newLp = (LinkProperties) message.obj; if (message.arg1 == IControlsTethering.STATE_TETHERED) { mOffloadController.notifyDownstreamLinkProperties(newLp); mOffload.updateDownstreamLinkProperties(newLp); } else { mOffloadController.removeDownstreamInterface(newLp.getInterfaceName()); // Another interface might be in local-only hotspot mode; // resend all local prefixes to the OffloadController. sendOffloadExemptPrefixes(); mOffload.excludeDownstreamInterface(newLp.getInterfaceName()); } break; } Loading Loading @@ -1722,6 +1702,82 @@ public class Tethering extends BaseNetworkObserver { } catch (Exception e) {} } } // A wrapper class to handle multiple situations where several calls to // the OffloadController need to happen together. // // TODO: This suggests that the interface between OffloadController and // Tethering is in need of improvement. Refactor these calls into the // OffloadController implementation. class OffloadWrapper { public void start() { mOffloadController.start(); sendOffloadExemptPrefixes(); } public void stop() { mOffloadController.stop(); } public void updateUpstreamNetworkState(NetworkState ns) { mOffloadController.setUpstreamLinkProperties( (ns != null) ? ns.linkProperties : null); } public void updateDownstreamLinkProperties(LinkProperties newLp) { // Update the list of offload-exempt prefixes before adding // new prefixes on downstream interfaces to the offload HAL. sendOffloadExemptPrefixes(); mOffloadController.notifyDownstreamLinkProperties(newLp); } public void excludeDownstreamInterface(String ifname) { // This and other interfaces may be in local-only hotspot mode; // resend all local prefixes to the OffloadController. sendOffloadExemptPrefixes(); mOffloadController.removeDownstreamInterface(ifname); } public void sendOffloadExemptPrefixes() { sendOffloadExemptPrefixes(mUpstreamNetworkMonitor.getLocalPrefixes()); } public void sendOffloadExemptPrefixes(final Set<IpPrefix> localPrefixes) { // Add in well-known minimum set. PrefixUtils.addNonForwardablePrefixes(localPrefixes); // Add tragically hardcoded prefixes. localPrefixes.add(PrefixUtils.DEFAULT_WIFI_P2P_PREFIX); // Maybe add prefixes or addresses for downstreams, depending on // the IP serving mode of each. for (TetherInterfaceStateMachine tism : mNotifyList) { final LinkProperties lp = tism.linkProperties(); switch (tism.servingMode()) { case IControlsTethering.STATE_UNAVAILABLE: case IControlsTethering.STATE_AVAILABLE: // No usable LinkProperties in these states. continue; case IControlsTethering.STATE_TETHERED: // Only add IPv4 /32 and IPv6 /128 prefixes. The // directly-connected prefixes will be sent as // downstream "offload-able" prefixes. for (LinkAddress addr : lp.getAllLinkAddresses()) { final InetAddress ip = addr.getAddress(); if (ip.isLinkLocalAddress()) continue; localPrefixes.add(PrefixUtils.ipAddressAsPrefix(ip)); } break; case IControlsTethering.STATE_LOCAL_ONLY: // Add prefixes covering all local IPs. localPrefixes.addAll(PrefixUtils.localPrefixesFrom(lp)); break; } } mOffloadController.setLocalPrefixes(localPrefixes); } } } @Override Loading
services/core/java/com/android/server/connectivity/tethering/OffloadController.java +46 −10 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ import java.net.InetAddress; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; Loading @@ -69,6 +70,7 @@ public class OffloadController { private final INetworkManagementService mNms; private final ITetheringStatsProvider mStatsProvider; private final SharedLog mLog; private final HashMap<String, LinkProperties> mDownstreams; private boolean mConfigInitialized; private boolean mControlInitialized; private LinkProperties mUpstreamLinkProperties; Loading Loading @@ -100,6 +102,7 @@ public class OffloadController { mNms = nms; mStatsProvider = new OffloadTetheringStatsProvider(); mLog = log.forSubComponent(TAG); mDownstreams = new HashMap<>(); mExemptPrefixes = new HashSet<>(); mLastLocalPrefixStrs = new HashSet<>(); Loading Loading @@ -257,6 +260,11 @@ public class OffloadController { } } private String currentUpstreamInterface() { return (mUpstreamLinkProperties != null) ? mUpstreamLinkProperties.getInterfaceName() : null; } private void maybeUpdateStats(String iface) { if (TextUtils.isEmpty(iface)) { return; Loading @@ -281,9 +289,7 @@ public class OffloadController { private boolean maybeUpdateDataLimit(String iface) { // setDataLimit may only be called while offload is occuring on this upstream. if (!started() || mUpstreamLinkProperties == null || !TextUtils.equals(iface, mUpstreamLinkProperties.getInterfaceName())) { if (!started() || !TextUtils.equals(iface, currentUpstreamInterface())) { return true; } Loading @@ -296,9 +302,7 @@ public class OffloadController { } private void updateStatsForCurrentUpstream() { if (mUpstreamLinkProperties != null) { maybeUpdateStats(mUpstreamLinkProperties.getInterfaceName()); } maybeUpdateStats(currentUpstreamInterface()); } public void setUpstreamLinkProperties(LinkProperties lp) { Loading @@ -325,17 +329,42 @@ public class OffloadController { } public void notifyDownstreamLinkProperties(LinkProperties lp) { final String ifname = lp.getInterfaceName(); final LinkProperties oldLp = mDownstreams.put(ifname, new LinkProperties(lp)); if (Objects.equals(oldLp, lp)) return; if (!started()) return; // TODO: Cache LinkProperties on a per-ifname basis and compute the // deltas, calling addDownstream()/removeDownstream() accordingly. final List<RouteInfo> oldRoutes = (oldLp != null) ? oldLp.getRoutes() : new ArrayList<>(); final List<RouteInfo> newRoutes = lp.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 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()); } } } public void removeDownstreamInterface(String ifname) { final LinkProperties lp = mDownstreams.remove(ifname); if (lp == null) return; if (!started()) return; // TODO: Check cache for LinkProperties of ifname and, if present, // call removeDownstream() accordingly. for (RouteInfo route : lp.getRoutes()) { if (shouldIgnoreDownstreamRoute(route)) continue; mHwInterface.removeDownstreamPrefix(ifname, route.getDestination().toString()); } } private boolean isOffloadDisabled() { Loading Loading @@ -442,6 +471,13 @@ public class OffloadController { return localPrefixStrs; } private static boolean shouldIgnoreDownstreamRoute(RouteInfo route) { // Ignore any link-local routes. if (!route.getDestinationLinkAddress().isGlobalPreferred()) return true; return false; } public void dump(IndentingPrintWriter pw) { if (isOffloadDisabled()) { pw.println("Offload disabled"); Loading
services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java +38 −0 Original line number Diff line number Diff line Loading @@ -236,6 +236,44 @@ public class OffloadHardwareInterface { return results.success; } public boolean addDownstreamPrefix(String ifname, String prefix) { final String logmsg = String.format("addDownstreamPrefix(%s, %s)", ifname, prefix); final CbResults results = new CbResults(); try { mOffloadControl.addDownstream(ifname, prefix, (boolean success, String errMsg) -> { results.success = success; results.errMsg = errMsg; }); } catch (RemoteException e) { record(logmsg, e); return false; } record(logmsg, results); return results.success; } public boolean removeDownstreamPrefix(String ifname, String prefix) { final String logmsg = String.format("removeDownstreamPrefix(%s, %s)", ifname, prefix); final CbResults results = new CbResults(); try { mOffloadControl.removeDownstream(ifname, prefix, (boolean success, String errMsg) -> { results.success = success; results.errMsg = errMsg; }); } catch (RemoteException e) { record(logmsg, e); return false; } record(logmsg, results); return results.success; } private void record(String msg, Throwable t) { mLog.e(msg + YIELDS + "exception: " + t); } Loading
services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java +5 −0 Original line number Diff line number Diff line Loading @@ -115,6 +115,7 @@ public class TetherInterfaceStateMachine extends StateMachine { private final LinkProperties mLinkProperties; private int mLastError; private int mServingMode; private String mMyUpstreamIfaceName; // may change over time private NetworkInterface mNetworkInterface; private byte[] mHwAddr; Loading Loading @@ -142,6 +143,7 @@ public class TetherInterfaceStateMachine extends StateMachine { mLinkProperties = new LinkProperties(); resetLinkProperties(); mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR; mServingMode = IControlsTethering.STATE_AVAILABLE; mInitialState = new InitialState(); mLocalHotspotState = new LocalHotspotState(); Loading @@ -161,6 +163,8 @@ public class TetherInterfaceStateMachine extends StateMachine { public int lastError() { return mLastError; } public int servingMode() { return mServingMode; } public LinkProperties linkProperties() { return new LinkProperties(mLinkProperties); } public void stop() { sendMessage(CMD_INTERFACE_DOWN); } Loading Loading @@ -448,6 +452,7 @@ public class TetherInterfaceStateMachine extends StateMachine { } private void sendInterfaceState(int newInterfaceState) { mServingMode = newInterfaceState; mTetherController.updateInterfaceState( TetherInterfaceStateMachine.this, newInterfaceState, mLastError); sendLinkProperties(); Loading
services/net/java/android/net/util/NetworkConstants.java +2 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,7 @@ public final class NetworkConstants { public static final int IPV4_PROTOCOL_OFFSET = 9; public static final int IPV4_SRC_ADDR_OFFSET = 12; public static final int IPV4_DST_ADDR_OFFSET = 16; public static final int IPV4_ADDR_BITS = 32; public static final int IPV4_ADDR_LEN = 4; /** Loading @@ -99,6 +100,7 @@ public final class NetworkConstants { public static final int IPV6_PROTOCOL_OFFSET = 6; public static final int IPV6_SRC_ADDR_OFFSET = 8; public static final int IPV6_DST_ADDR_OFFSET = 24; public static final int IPV6_ADDR_BITS = 128; public static final int IPV6_ADDR_LEN = 16; public static final int IPV6_MIN_MTU = 1280; public static final int RFC7421_PREFIX_LENGTH = 64; Loading