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

Commit 09952a8e authored by Mark Chien's avatar Mark Chien Committed by Gerrit Code Review
Browse files

Merge "Adjust TTL for ipv6 tethering"

parents 68a9de91 aa8cecec
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);