From 6e29bf0069caceb38806101c150acb477df99989 Mon Sep 17 00:00:00 2001 From: Erik Kline Date: Mon, 15 Aug 2016 16:16:18 +0900 Subject: [PATCH] Support tethering IPv6 toward the first requested downstream. We no longer tether toward wifi only, but rather implement 64share toward the current, oldest (first requested) active downstream. Additionally, explicitly ban IPv6 tethering toward Bluetooth until PAN support is figured out. Bug: 30298058 Change-Id: Ib705b69eae767ec50131d09d26168d9e041e4bc0 --- .../server/connectivity/Tethering.java | 12 +++-- .../tethering/IPv6TetheringCoordinator.java | 52 ++++++++++++++----- 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java index e0d8373fc445a..927f8f98284fc 100644 --- a/services/core/java/com/android/server/connectivity/Tethering.java +++ b/services/core/java/com/android/server/connectivity/Tethering.java @@ -1616,6 +1616,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering if (VDBG) Log.d(TAG, "Tether Mode requested by " + who); if (mNotifyList.indexOf(who) < 0) { mNotifyList.add(who); + mIPv6TetheringCoordinator.addActiveDownstream(who); } transitionTo(mTetherModeAliveState); break; @@ -1623,6 +1624,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering who = (TetherInterfaceStateMachine)message.obj; if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who); mNotifyList.remove(who); + mIPv6TetheringCoordinator.removeActiveDownstream(who); break; default: retValue = false; @@ -1661,17 +1663,19 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering maybeLogMessage(this, message.what); boolean retValue = true; switch (message.what) { - case CMD_TETHER_MODE_REQUESTED: + case CMD_TETHER_MODE_REQUESTED: { TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj; if (VDBG) Log.d(TAG, "Tether Mode requested by " + who); if (mNotifyList.indexOf(who) < 0) { mNotifyList.add(who); + mIPv6TetheringCoordinator.addActiveDownstream(who); } who.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED, mCurrentUpstreamIface); break; - case CMD_TETHER_MODE_UNREQUESTED: - who = (TetherInterfaceStateMachine)message.obj; + } + case CMD_TETHER_MODE_UNREQUESTED: { + TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj; if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who); if (mNotifyList.remove(who)) { if (DBG) Log.d(TAG, "TetherModeAlive removing notifyee " + who); @@ -1689,7 +1693,9 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering } else { Log.e(TAG, "TetherModeAliveState UNREQUESTED has unknown who: " + who); } + mIPv6TetheringCoordinator.removeActiveDownstream(who); break; + } case CMD_UPSTREAM_CHANGED: // need to try DUN immediately if Wifi goes down mTryCell = true; diff --git a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java index e94b584ac48aa..9173febd0ef3f 100644 --- a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java +++ b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java @@ -29,6 +29,7 @@ import android.util.Log; import java.net.Inet6Address; import java.net.InetAddress; import java.util.ArrayList; +import java.util.LinkedList; /** @@ -45,10 +46,28 @@ public class IPv6TetheringCoordinator { private static final boolean VDBG = false; private final ArrayList mNotifyList; + private final LinkedList mActiveDownstreams; private NetworkState mUpstreamNetworkState; public IPv6TetheringCoordinator(ArrayList notifyList) { mNotifyList = notifyList; + mActiveDownstreams = new LinkedList<>(); + } + + public void addActiveDownstream(TetherInterfaceStateMachine downstream) { + if (mActiveDownstreams.indexOf(downstream) == -1) { + // Adding a new downstream appends it to the list. Adding a + // downstream a second time without first removing it has no effect. + mActiveDownstreams.offer(downstream); + updateIPv6TetheringInterfaces(); + } + } + + public void removeActiveDownstream(TetherInterfaceStateMachine downstream) { + stopIPv6TetheringOn(downstream); + if (mActiveDownstreams.remove(downstream)) { + updateIPv6TetheringInterfaces(); + } } public void updateUpstreamNetworkState(NetworkState ns) { @@ -72,8 +91,7 @@ public class IPv6TetheringCoordinator { private void stopIPv6TetheringOnAllInterfaces() { for (TetherInterfaceStateMachine sm : mNotifyList) { - sm.sendMessage(TetherInterfaceStateMachine.CMD_IPV6_TETHER_UPDATE, - 0, 0, null); + stopIPv6TetheringOn(sm); } } @@ -98,28 +116,32 @@ public class IPv6TetheringCoordinator { private void updateIPv6TetheringInterfaces() { for (TetherInterfaceStateMachine sm : mNotifyList) { - final LinkProperties lp = getInterfaceIPv6LinkProperties(sm.interfaceType()); + final LinkProperties lp = getInterfaceIPv6LinkProperties(sm); sm.sendMessage(TetherInterfaceStateMachine.CMD_IPV6_TETHER_UPDATE, 0, 0, lp); break; } } - private LinkProperties getInterfaceIPv6LinkProperties(int interfaceType) { + private LinkProperties getInterfaceIPv6LinkProperties(TetherInterfaceStateMachine sm) { if (mUpstreamNetworkState == null) return null; + if (sm.interfaceType() == ConnectivityManager.TETHERING_BLUETOOTH) { + // TODO: Figure out IPv6 support on PAN interfaces. + return null; + } + // NOTE: Here, in future, we would have policies to decide how to divvy // up the available dedicated prefixes among downstream interfaces. // At this time we have no such mechanism--we only support tethering - // IPv6 toward Wi-Fi interfaces. + // IPv6 toward the oldest (first requested) active downstream. - switch (interfaceType) { - case ConnectivityManager.TETHERING_WIFI: - final LinkProperties lp = getIPv6OnlyLinkProperties( - mUpstreamNetworkState.linkProperties); - if (lp.hasIPv6DefaultRoute() && lp.hasGlobalIPv6Address()) { - return lp; - } - break; + final TetherInterfaceStateMachine currentActive = mActiveDownstreams.peek(); + if (currentActive != null && currentActive == sm) { + final LinkProperties lp = getIPv6OnlyLinkProperties( + mUpstreamNetworkState.linkProperties); + if (lp.hasIPv6DefaultRoute() && lp.hasGlobalIPv6Address()) { + return lp; + } } return null; @@ -250,4 +272,8 @@ public class IPv6TetheringCoordinator { ns.networkCapabilities, ns.linkProperties); } + + private static void stopIPv6TetheringOn(TetherInterfaceStateMachine sm) { + sm.sendMessage(TetherInterfaceStateMachine.CMD_IPV6_TETHER_UPDATE, 0, 0, null); + } }