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

Commit 5ea9d599 authored by Mark Chien's avatar Mark Chien Committed by Automerger Merge Worker
Browse files

Merge "Adjust TTL for ipv6 tethering" into rvc-dev am: d0355d7d am: d41b3608

Change-Id: Iec61bd98f56bb27b2602ac99fcddebe224a902d5
parents 31fdc90a d41b3608
Loading
Loading
Loading
Loading
+6 −7
Original line number Diff line number Diff line
@@ -738,7 +738,7 @@ public class IpServer extends StateMachine {
    //
    // TODO: Evaluate using a data structure than is more directly suited to
    // communicating only the relevant information.
    private void updateUpstreamIPv6LinkProperties(LinkProperties v6only) {
    private void updateUpstreamIPv6LinkProperties(LinkProperties v6only, int ttlAdjustment) {
        if (mRaDaemon == null) return;

        // Avoid unnecessary work on spurious updates.
@@ -761,7 +761,7 @@ public class IpServer extends StateMachine {
            params.mtu = mUsingBpfOffload ? v6only.getMtu() - 16 : v6only.getMtu();
            params.hasDefaultRoute = v6only.hasIpv6DefaultRoute();

            if (params.hasDefaultRoute) params.hopLimit = getHopLimit(upstreamIface);
            if (params.hasDefaultRoute) params.hopLimit = getHopLimit(upstreamIface, ttlAdjustment);

            for (LinkAddress linkAddr : v6only.getLinkAddresses()) {
                if (linkAddr.getPrefixLength() != RFC7421_PREFIX_LENGTH) continue;
@@ -1052,12 +1052,11 @@ public class IpServer extends StateMachine {
        }
    }

    private byte getHopLimit(String upstreamIface) {
    private byte getHopLimit(String upstreamIface, int adjustTTL) {
        try {
            int upstreamHopLimit = Integer.parseUnsignedInt(
                    mNetd.getProcSysNet(INetd.IPV6, INetd.CONF, upstreamIface, "hop_limit"));
            // Add one hop to account for this forwarding device
            upstreamHopLimit++;
            upstreamHopLimit = upstreamHopLimit + adjustTTL;
            // Cap the hop limit to 255.
            return (byte) Integer.min(upstreamHopLimit, 255);
        } catch (Exception e) {
@@ -1145,7 +1144,7 @@ public class IpServer extends StateMachine {
                    transitionTo(mUnavailableState);
                    break;
                case CMD_IPV6_TETHER_UPDATE:
                    updateUpstreamIPv6LinkProperties((LinkProperties) message.obj);
                    updateUpstreamIPv6LinkProperties((LinkProperties) message.obj, message.arg1);
                    break;
                default:
                    return NOT_HANDLED;
@@ -1209,7 +1208,7 @@ public class IpServer extends StateMachine {
                    if (DBG) Log.d(TAG, "Untethered (ifdown)" + mIfaceName);
                    break;
                case CMD_IPV6_TETHER_UPDATE:
                    updateUpstreamIPv6LinkProperties((LinkProperties) message.obj);
                    updateUpstreamIPv6LinkProperties((LinkProperties) message.obj, message.arg1);
                    sendLinkProperties();
                    break;
                case CMD_IP_FORWARDING_ENABLE_ERROR:
+18 −1
Original line number Diff line number Diff line
@@ -161,11 +161,28 @@ public class IPv6TetheringCoordinator {
    private void updateIPv6TetheringInterfaces() {
        for (IpServer ipServer : mNotifyList) {
            final LinkProperties lp = getInterfaceIPv6LinkProperties(ipServer);
            ipServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, lp);
            ipServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, getTtlAdjustment(), 0, lp);
            break;
        }
    }

    private int getTtlAdjustment() {
        if (mUpstreamNetworkState == null || mUpstreamNetworkState.networkCapabilities == null) {
            return 0;
        }

        // If upstream is cellular, set the TTL in Router Advertisements to "network-set TTL" - 1
        // for carrier requirement.
        if (mUpstreamNetworkState.networkCapabilities.hasTransport(
                NetworkCapabilities.TRANSPORT_CELLULAR)) {
            return -1;
        }

        // For other non-cellular upstream, set TTL as "network-set TTL" + 1 to preventing arbitrary
        // distinction between tethered and untethered traffic.
        return 1;
    }

    private LinkProperties getInterfaceIPv6LinkProperties(IpServer ipServer) {
        final Downstream ds = findDownstream(ipServer);
        if (ds == null) return null;
+54 −8
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.net.ip;

import static android.net.INetd.IF_STATE_UP;
import static android.net.RouteInfo.RTN_UNICAST;
import static android.net.TetheringManager.TETHERING_BLUETOOTH;
import static android.net.TetheringManager.TETHERING_NCM;
import static android.net.TetheringManager.TETHERING_USB;
@@ -74,6 +75,7 @@ import android.net.dhcp.IDhcpServer;
import android.net.dhcp.IDhcpServerCallbacks;
import android.net.ip.IpNeighborMonitor.NeighborEvent;
import android.net.ip.IpNeighborMonitor.NeighborEventConsumer;
import android.net.ip.RouterAdvertisementDaemon.RaParams;
import android.net.util.InterfaceParams;
import android.net.util.InterfaceSet;
import android.net.util.SharedLog;
@@ -196,7 +198,7 @@ public class IpServerTest {
        if (upstreamIface != null) {
            LinkProperties lp = new LinkProperties();
            lp.setInterfaceName(upstreamIface);
            dispatchTetherConnectionChanged(upstreamIface, lp);
            dispatchTetherConnectionChanged(upstreamIface, lp, 0);
        }
        reset(mNetd, mCallback);
    }
@@ -694,7 +696,7 @@ public class IpServerTest {
        InOrder inOrder = inOrder(mNetd);
        LinkProperties lp = new LinkProperties();
        lp.setInterfaceName(UPSTREAM_IFACE2);
        dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp);
        dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp, -1);
        inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX2, neighA, macA));
        inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighA, macA));
        inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX2, neighB, macB));
@@ -702,7 +704,7 @@ public class IpServerTest {
        reset(mNetd);

        // When the upstream is lost, rules are removed.
        dispatchTetherConnectionChanged(null, null);
        dispatchTetherConnectionChanged(null, null, 0);
        verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX2, neighA, macA));
        verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX2, neighB, macB));
        reset(mNetd);
@@ -715,19 +717,19 @@ public class IpServerTest {

        // Rules can be added again once upstream IPv6 connectivity is available.
        lp.setInterfaceName(UPSTREAM_IFACE);
        dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp);
        dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
        recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
        verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighB, macB));
        verify(mNetd, never()).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighA, macA));

        // If upstream IPv6 connectivity is lost, rules are removed.
        reset(mNetd);
        dispatchTetherConnectionChanged(UPSTREAM_IFACE, null);
        dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0);
        verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighB, macB));

        // When the interface goes down, rules are removed.
        lp.setInterfaceName(UPSTREAM_IFACE);
        dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp);
        dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
        recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA);
        recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
        verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighA, macA));
@@ -788,6 +790,49 @@ public class IpServerTest {
        verify(mIpNeighborMonitor, never()).start();
    }

    private LinkProperties buildIpv6OnlyLinkProperties(final String iface) {
        final LinkProperties linkProp = new LinkProperties();
        linkProp.setInterfaceName(iface);
        linkProp.addLinkAddress(new LinkAddress("2001:db8::1/64"));
        linkProp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, iface, RTN_UNICAST));
        final InetAddress dns = InetAddresses.parseNumericAddress("2001:4860:4860::8888");
        linkProp.addDnsServer(dns);

        return linkProp;
    }

    @Test
    public void testAdjustTtlValue() throws Exception {
        final ArgumentCaptor<RaParams> raParamsCaptor =
                ArgumentCaptor.forClass(RaParams.class);
        initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
        verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
        final RaParams noV6Params = raParamsCaptor.getValue();
        assertEquals(65, noV6Params.hopLimit);
        reset(mRaDaemon);

        when(mNetd.getProcSysNet(
                INetd.IPV6, INetd.CONF, UPSTREAM_IFACE, "hop_limit")).thenReturn("64");
        final LinkProperties lp = buildIpv6OnlyLinkProperties(UPSTREAM_IFACE);
        dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 1);
        verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
        final RaParams nonCellularParams = raParamsCaptor.getValue();
        assertEquals(65, nonCellularParams.hopLimit);
        reset(mRaDaemon);

        dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0);
        verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
        final RaParams noUpstream = raParamsCaptor.getValue();
        assertEquals(65, nonCellularParams.hopLimit);
        reset(mRaDaemon);

        dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
        verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
        final RaParams cellularParams = raParamsCaptor.getValue();
        assertEquals(63, cellularParams.hopLimit);
        reset(mRaDaemon);
    }

    private void assertDhcpServingParams(final DhcpServingParamsParcel params,
            final IpPrefix prefix) {
        // Last address byte is random
@@ -838,9 +883,10 @@ public class IpServerTest {
     * @param upstreamIface String name of upstream interface (or null)
     * @param v6lp IPv6 LinkProperties of the upstream interface, or null for an IPv4-only upstream.
     */
    private void dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp) {
    private void dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp,
            int ttlAdjustment) {
        dispatchTetherConnectionChanged(upstreamIface);
        mIpServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, v6lp);
        mIpServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, ttlAdjustment, 0, v6lp);
        mLooper.dispatchAll();
    }

+2 −2
Original line number Diff line number Diff line
@@ -128,7 +128,7 @@ public class IPv6TetheringCoordinatorTest {
        final UpstreamNetworkState mobileUpstream = createDualStackUpstream(TRANSPORT_CELLULAR);
        final ArgumentCaptor<LinkProperties> lp = ArgumentCaptor.forClass(LinkProperties.class);
        mIPv6TetheringCoordinator.updateUpstreamNetworkState(mobileUpstream);
        verify(firstServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(0), eq(0),
        verify(firstServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(-1), eq(0),
                lp.capture());
        final LinkProperties v6OnlyLink = lp.getValue();
        assertOnlyOneV6AddressAndNoV4(v6OnlyLink);
@@ -140,7 +140,7 @@ public class IPv6TetheringCoordinatorTest {
        mNotifyList.remove(firstServer);
        mIPv6TetheringCoordinator.removeActiveDownstream(firstServer);
        verify(firstServer).sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, null);
        verify(secondServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(0), eq(0),
        verify(secondServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(-1), eq(0),
                lp.capture());
        final LinkProperties localOnlyLink = lp.getValue();
        assertNotNull(localOnlyLink);