Loading services/core/java/com/android/server/connectivity/Nat464Xlat.java +108 −83 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.server.connectivity; import java.net.Inet4Address; import android.net.InterfaceConfiguration; import android.net.ConnectivityManager; import android.net.LinkAddress; Loading @@ -33,6 +31,9 @@ import android.util.Slog; import com.android.server.net.BaseNetworkObserver; import com.android.internal.util.ArrayUtils; import java.net.Inet4Address; import java.util.Objects; /** * Class to manage a 464xlat CLAT daemon. * Loading Loading @@ -60,21 +61,18 @@ public class Nat464Xlat extends BaseNetworkObserver { // The network we're running on, and its type. private final NetworkAgentInfo mNetwork; // Internal state variables. // // The possible states are: // - Idle: start() not called. Everything is null. // - Starting: start() called. Interfaces are non-null. isStarted() returns true. // mIsRunning is false. // - Running: start() called, and interfaceLinkStateChanged() told us that mIface is up. // mIsRunning is true. // private enum State { IDLE, // start() not called. Base iface and stacked iface names are null. STARTING, // start() called. Base iface and stacked iface names are known. RUNNING; // start() called, and the stacked iface is known to be up. } // Once mIface is non-null and isStarted() is true, methods called by ConnectivityService on // its handler thread must not modify any internal state variables; they are only updated by the // interface observers, called on the notification threads. private String mBaseIface; private String mIface; private boolean mIsRunning; private volatile State mState = State.IDLE; public Nat464Xlat(INetworkManagementService nmService, Handler handler, NetworkAgentInfo nai) { mNMService = nmService; Loading @@ -99,20 +97,36 @@ public class Nat464Xlat extends BaseNetworkObserver { } /** * Determines whether clatd is started. Always true, except a) if start has not yet been called, * or b) if our interface was removed. * @return true if clatd has been started and has not yet stopped. * A true result corresponds to internal states STARTING and RUNNING. */ public boolean isStarted() { return mIface != null; return mState != State.IDLE; } /** * @return true if clatd has been started and the stacked interface is up. */ public boolean isRunning() { return mState == State.RUNNING; } /** * Sets internal state. */ private void enterStartingState(String baseIface) { mIface = CLAT_PREFIX + baseIface; mBaseIface = baseIface; mState = State.STARTING; } /** * Clears internal state. Must not be called by ConnectivityService. */ private void clear() { private void enterIdleState() { mIface = null; mBaseIface = null; mIsRunning = false; mState = State.IDLE; } /** Loading @@ -136,19 +150,19 @@ public class Nat464Xlat extends BaseNetworkObserver { return; } mBaseIface = mNetwork.linkProperties.getInterfaceName(); if (mBaseIface == null) { String baseIface = mNetwork.linkProperties.getInterfaceName(); if (baseIface == null) { Slog.e(TAG, "startClat: Can't start clat on null interface"); return; } mIface = CLAT_PREFIX + mBaseIface; // From now on, isStarted() will return true. // TODO: should we only do this if mNMService.startClatd() succeeds? enterStartingState(baseIface); Slog.i(TAG, "Starting clatd on " + mBaseIface); try { mNMService.startClatd(mBaseIface); } catch(RemoteException|IllegalStateException e) { Slog.e(TAG, "Error starting clatd: " + e); Slog.e(TAG, "Error starting clatd on " + mBaseIface, e); } } Loading @@ -156,18 +170,19 @@ public class Nat464Xlat extends BaseNetworkObserver { * Stops the clat daemon. Called by ConnectivityService on the handler thread. */ public void stop() { if (isStarted()) { Slog.i(TAG, "Stopping clatd"); if (!isStarted()) { Slog.e(TAG, "stopClat: already stopped or not started"); return; } Slog.i(TAG, "Stopping clatd on " + mBaseIface); try { mNMService.stopClatd(mBaseIface); } catch(RemoteException|IllegalStateException e) { Slog.e(TAG, "Error stopping clatd: " + e); Slog.e(TAG, "Error stopping clatd on " + mBaseIface, e); } // When clatd stops and its interface is deleted, interfaceRemoved() will notify // ConnectivityService and call clear(). } else { Slog.e(TAG, "clatd: already stopped"); } // ConnectivityService and call enterIdleState(). } private void updateConnectivityService(LinkProperties lp) { Loading @@ -183,16 +198,19 @@ public class Nat464Xlat extends BaseNetworkObserver { * has no idea that 464xlat is running on top of it. */ public void fixupLinkProperties(LinkProperties oldLp) { if (mNetwork.clatd != null && mIsRunning && mNetwork.linkProperties != null && !mNetwork.linkProperties.getAllInterfaceNames().contains(mIface)) { if (!isRunning()) { return; } LinkProperties lp = mNetwork.linkProperties; if (lp == null || lp.getAllInterfaceNames().contains(mIface)) { return; } Slog.d(TAG, "clatd running, updating NAI for " + mIface); for (LinkProperties stacked: oldLp.getStackedLinks()) { if (mIface.equals(stacked.getInterfaceName())) { mNetwork.linkProperties.addStackedLink(stacked); break; } if (Objects.equals(mIface, stacked.getInterfaceName())) { lp.addStackedLink(stacked); return; } } } Loading Loading @@ -238,33 +256,42 @@ public class Nat464Xlat extends BaseNetworkObserver { } } /** * Adds stacked link on base link and transitions to Running state * This is called by the InterfaceObserver on its own thread, so can race with stop(). */ @Override public void interfaceLinkStateChanged(String iface, boolean up) { // Called by the InterfaceObserver on its own thread, so can race with stop(). if (isStarted() && up && mIface.equals(iface)) { Slog.i(TAG, "interface " + iface + " is up, mIsRunning " + mIsRunning + "->true"); if (!mIsRunning) { if (!isStarted() || !up || !Objects.equals(mIface, iface)) { return; } if (isRunning()) { return; } LinkAddress clatAddress = getLinkAddress(iface); if (clatAddress == null) { return; } mIsRunning = true; mState = State.RUNNING; Slog.i(TAG, String.format("interface %s is up, adding stacked link %s on top of %s", mIface, mIface, mBaseIface)); maybeSetIpv6NdOffload(mBaseIface, false); LinkProperties lp = new LinkProperties(mNetwork.linkProperties); lp.addStackedLink(makeLinkProperties(clatAddress)); Slog.i(TAG, "Adding stacked link " + mIface + " on top of " + mBaseIface); updateConnectivityService(lp); } } } @Override public void interfaceRemoved(String iface) { if (isStarted() && mIface.equals(iface)) { Slog.i(TAG, "interface " + iface + " removed, mIsRunning " + mIsRunning + "->false"); if (!isStarted() || !Objects.equals(mIface, iface)) { return; } if (!isRunning()) { return; } if (mIsRunning) { Slog.i(TAG, "interface " + iface + " removed"); // The interface going away likely means clatd has crashed. Ask netd to stop it, // because otherwise when we try to start it again on the same base interface netd // will complain that it's already started. Loading @@ -281,14 +308,12 @@ public class Nat464Xlat extends BaseNetworkObserver { maybeSetIpv6NdOffload(mBaseIface, true); LinkProperties lp = new LinkProperties(mNetwork.linkProperties); lp.removeStackedLink(mIface); clear(); enterIdleState(); updateConnectivityService(lp); } } } @Override public String toString() { return "mBaseIface: " + mBaseIface + ", mIface: " + mIface + ", mIsRunning: " + mIsRunning; return "mBaseIface: " + mBaseIface + ", mIface: " + mIface + ", mState: " + mState; } } Loading
services/core/java/com/android/server/connectivity/Nat464Xlat.java +108 −83 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.server.connectivity; import java.net.Inet4Address; import android.net.InterfaceConfiguration; import android.net.ConnectivityManager; import android.net.LinkAddress; Loading @@ -33,6 +31,9 @@ import android.util.Slog; import com.android.server.net.BaseNetworkObserver; import com.android.internal.util.ArrayUtils; import java.net.Inet4Address; import java.util.Objects; /** * Class to manage a 464xlat CLAT daemon. * Loading Loading @@ -60,21 +61,18 @@ public class Nat464Xlat extends BaseNetworkObserver { // The network we're running on, and its type. private final NetworkAgentInfo mNetwork; // Internal state variables. // // The possible states are: // - Idle: start() not called. Everything is null. // - Starting: start() called. Interfaces are non-null. isStarted() returns true. // mIsRunning is false. // - Running: start() called, and interfaceLinkStateChanged() told us that mIface is up. // mIsRunning is true. // private enum State { IDLE, // start() not called. Base iface and stacked iface names are null. STARTING, // start() called. Base iface and stacked iface names are known. RUNNING; // start() called, and the stacked iface is known to be up. } // Once mIface is non-null and isStarted() is true, methods called by ConnectivityService on // its handler thread must not modify any internal state variables; they are only updated by the // interface observers, called on the notification threads. private String mBaseIface; private String mIface; private boolean mIsRunning; private volatile State mState = State.IDLE; public Nat464Xlat(INetworkManagementService nmService, Handler handler, NetworkAgentInfo nai) { mNMService = nmService; Loading @@ -99,20 +97,36 @@ public class Nat464Xlat extends BaseNetworkObserver { } /** * Determines whether clatd is started. Always true, except a) if start has not yet been called, * or b) if our interface was removed. * @return true if clatd has been started and has not yet stopped. * A true result corresponds to internal states STARTING and RUNNING. */ public boolean isStarted() { return mIface != null; return mState != State.IDLE; } /** * @return true if clatd has been started and the stacked interface is up. */ public boolean isRunning() { return mState == State.RUNNING; } /** * Sets internal state. */ private void enterStartingState(String baseIface) { mIface = CLAT_PREFIX + baseIface; mBaseIface = baseIface; mState = State.STARTING; } /** * Clears internal state. Must not be called by ConnectivityService. */ private void clear() { private void enterIdleState() { mIface = null; mBaseIface = null; mIsRunning = false; mState = State.IDLE; } /** Loading @@ -136,19 +150,19 @@ public class Nat464Xlat extends BaseNetworkObserver { return; } mBaseIface = mNetwork.linkProperties.getInterfaceName(); if (mBaseIface == null) { String baseIface = mNetwork.linkProperties.getInterfaceName(); if (baseIface == null) { Slog.e(TAG, "startClat: Can't start clat on null interface"); return; } mIface = CLAT_PREFIX + mBaseIface; // From now on, isStarted() will return true. // TODO: should we only do this if mNMService.startClatd() succeeds? enterStartingState(baseIface); Slog.i(TAG, "Starting clatd on " + mBaseIface); try { mNMService.startClatd(mBaseIface); } catch(RemoteException|IllegalStateException e) { Slog.e(TAG, "Error starting clatd: " + e); Slog.e(TAG, "Error starting clatd on " + mBaseIface, e); } } Loading @@ -156,18 +170,19 @@ public class Nat464Xlat extends BaseNetworkObserver { * Stops the clat daemon. Called by ConnectivityService on the handler thread. */ public void stop() { if (isStarted()) { Slog.i(TAG, "Stopping clatd"); if (!isStarted()) { Slog.e(TAG, "stopClat: already stopped or not started"); return; } Slog.i(TAG, "Stopping clatd on " + mBaseIface); try { mNMService.stopClatd(mBaseIface); } catch(RemoteException|IllegalStateException e) { Slog.e(TAG, "Error stopping clatd: " + e); Slog.e(TAG, "Error stopping clatd on " + mBaseIface, e); } // When clatd stops and its interface is deleted, interfaceRemoved() will notify // ConnectivityService and call clear(). } else { Slog.e(TAG, "clatd: already stopped"); } // ConnectivityService and call enterIdleState(). } private void updateConnectivityService(LinkProperties lp) { Loading @@ -183,16 +198,19 @@ public class Nat464Xlat extends BaseNetworkObserver { * has no idea that 464xlat is running on top of it. */ public void fixupLinkProperties(LinkProperties oldLp) { if (mNetwork.clatd != null && mIsRunning && mNetwork.linkProperties != null && !mNetwork.linkProperties.getAllInterfaceNames().contains(mIface)) { if (!isRunning()) { return; } LinkProperties lp = mNetwork.linkProperties; if (lp == null || lp.getAllInterfaceNames().contains(mIface)) { return; } Slog.d(TAG, "clatd running, updating NAI for " + mIface); for (LinkProperties stacked: oldLp.getStackedLinks()) { if (mIface.equals(stacked.getInterfaceName())) { mNetwork.linkProperties.addStackedLink(stacked); break; } if (Objects.equals(mIface, stacked.getInterfaceName())) { lp.addStackedLink(stacked); return; } } } Loading Loading @@ -238,33 +256,42 @@ public class Nat464Xlat extends BaseNetworkObserver { } } /** * Adds stacked link on base link and transitions to Running state * This is called by the InterfaceObserver on its own thread, so can race with stop(). */ @Override public void interfaceLinkStateChanged(String iface, boolean up) { // Called by the InterfaceObserver on its own thread, so can race with stop(). if (isStarted() && up && mIface.equals(iface)) { Slog.i(TAG, "interface " + iface + " is up, mIsRunning " + mIsRunning + "->true"); if (!mIsRunning) { if (!isStarted() || !up || !Objects.equals(mIface, iface)) { return; } if (isRunning()) { return; } LinkAddress clatAddress = getLinkAddress(iface); if (clatAddress == null) { return; } mIsRunning = true; mState = State.RUNNING; Slog.i(TAG, String.format("interface %s is up, adding stacked link %s on top of %s", mIface, mIface, mBaseIface)); maybeSetIpv6NdOffload(mBaseIface, false); LinkProperties lp = new LinkProperties(mNetwork.linkProperties); lp.addStackedLink(makeLinkProperties(clatAddress)); Slog.i(TAG, "Adding stacked link " + mIface + " on top of " + mBaseIface); updateConnectivityService(lp); } } } @Override public void interfaceRemoved(String iface) { if (isStarted() && mIface.equals(iface)) { Slog.i(TAG, "interface " + iface + " removed, mIsRunning " + mIsRunning + "->false"); if (!isStarted() || !Objects.equals(mIface, iface)) { return; } if (!isRunning()) { return; } if (mIsRunning) { Slog.i(TAG, "interface " + iface + " removed"); // The interface going away likely means clatd has crashed. Ask netd to stop it, // because otherwise when we try to start it again on the same base interface netd // will complain that it's already started. Loading @@ -281,14 +308,12 @@ public class Nat464Xlat extends BaseNetworkObserver { maybeSetIpv6NdOffload(mBaseIface, true); LinkProperties lp = new LinkProperties(mNetwork.linkProperties); lp.removeStackedLink(mIface); clear(); enterIdleState(); updateConnectivityService(lp); } } } @Override public String toString() { return "mBaseIface: " + mBaseIface + ", mIface: " + mIface + ", mIsRunning: " + mIsRunning; return "mBaseIface: " + mBaseIface + ", mIface: " + mIface + ", mState: " + mState; } }