Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 568cd412 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Send add/removeDownstream info to offload HAL" into oc-mr1-dev

parents 53414a98 ed962a84
Loading
Loading
Loading
Loading
+92 −36
Original line number Diff line number Diff line
@@ -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;
@@ -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;

@@ -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) {
@@ -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) {
@@ -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);
            }

@@ -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.
@@ -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;
            }

@@ -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;
                }
@@ -1533,7 +1516,7 @@ public class Tethering extends BaseNetworkObserver {

            @Override
            public void exit() {
                mOffloadController.stop();
                mOffload.stop();
                mUpstreamNetworkMonitor.stop();
                mSimChange.stopListening();
                notifyDownstreamsOfNewUpstreamIface(null);
@@ -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;
@@ -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;
                    }
@@ -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
+46 −10
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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<>();

@@ -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;
@@ -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;
        }

@@ -296,9 +302,7 @@ public class OffloadController {
    }

    private void updateStatsForCurrentUpstream() {
        if (mUpstreamLinkProperties != null) {
            maybeUpdateStats(mUpstreamLinkProperties.getInterfaceName());
        }
        maybeUpdateStats(currentUpstreamInterface());
    }

    public void setUpstreamLinkProperties(LinkProperties lp) {
@@ -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() {
@@ -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");
+38 −0
Original line number Diff line number Diff line
@@ -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);
    }
+5 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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();
@@ -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); }
@@ -448,6 +452,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
    }

    private void sendInterfaceState(int newInterfaceState) {
        mServingMode = newInterfaceState;
        mTetherController.updateInterfaceState(
                TetherInterfaceStateMachine.this, newInterfaceState, mLastError);
        sendLinkProperties();
+2 −0
Original line number Diff line number Diff line
@@ -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;

    /**
@@ -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