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

Commit 8c380bae authored by Xiao Ma's avatar Xiao Ma
Browse files

Get the updated link state from netlink event instead of Netd.

Get the updated link state from ifi_flags of ifinfomsg header, and
sync up with IpClient on the link state change.

Also do the initialization of mDependencies in IpClientLinkObserver
prior to mNetlinkMonitor. The purpose is to prevent the NPE when
calling isNetlinkEventParsingEnabled in MyNetlinkMonitor ctor. This
change is safe, just adjusting the initialization order of private
members, it doesn't bring any side-effect.

Bug: 163492391
Test: atest NetworkStackTests NetworkStackIntegrationTests
Change-Id: I6bf5929fefd00526c439178defba2ac2597682d0
parent ac715e44
Loading
Loading
Loading
Loading
+51 −12
Original line number Diff line number Diff line
@@ -18,8 +18,11 @@ package android.net.ip;

import static android.net.util.NetworkStackUtils.IPCLIENT_PARSE_NETLINK_EVENTS_VERSION;
import static android.system.OsConstants.AF_INET6;
import static android.system.OsConstants.AF_UNSPEC;
import static android.system.OsConstants.IFF_LOOPBACK;

import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT;
import static com.android.net.module.util.netlink.NetlinkConstants.IFF_LOWER_UP;

import android.app.AlarmManager;
import android.content.Context;
@@ -37,6 +40,8 @@ import android.util.Log;
import com.android.net.module.util.netlink.NduseroptMessage;
import com.android.net.module.util.netlink.NetlinkConstants;
import com.android.net.module.util.netlink.NetlinkMessage;
import com.android.net.module.util.netlink.RtNetlinkLinkMessage;
import com.android.net.module.util.netlink.StructIfinfoMsg;
import com.android.net.module.util.netlink.StructNdOptPref64;
import com.android.net.module.util.netlink.StructNdOptRdnss;
import com.android.networkstack.apishim.NetworkInformationShimImpl;
@@ -137,9 +142,9 @@ public class IpClientLinkObserver implements NetworkObserver {
        mInterfaceLinkState = true; // Assume up by default
        mDnsServerRepository = new DnsServerRepository(config.minRdnssLifetime);
        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        mDependencies = deps;
        mNetlinkMonitor = new MyNetlinkMonitor(h, log, mTag);
        mHandler.post(mNetlinkMonitor::start);
        mDependencies = deps;
    }

    public void shutdown() {
@@ -183,12 +188,10 @@ public class IpClientLinkObserver implements NetworkObserver {

    @Override
    public void onInterfaceLinkStateChanged(String iface, boolean state) {
        if (mInterfaceName.equals(iface)) {
        if (isNetlinkEventParsingEnabled()) return;
        if (!mInterfaceName.equals(iface)) return;
        maybeLog("interfaceLinkStateChanged", iface + (state ? " up" : " down"));
            synchronized (this) {
                setInterfaceLinkStateLocked(state);
            }
        }
        updateInterfaceLinkStateChanged(state);
    }

    @Override
@@ -259,11 +262,15 @@ public class IpClientLinkObserver implements NetworkObserver {
    public void onInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) {
        if (isNetlinkEventParsingEnabled()) return;
        if (!mInterfaceName.equals(iface)) return;
        maybeLog("interfaceDnsServerInfo", Arrays.toString(addresses));
        updateInterfaceDnsServerInfo(lifetime, addresses);
    }

    private synchronized void updateInterfaceLinkStateChanged(boolean state) {
        setInterfaceLinkStateLocked(state);
    }

    private void updateInterfaceDnsServerInfo(long lifetime, final String[] addresses) {
        maybeLog("interfaceDnsServerInfo", Arrays.toString(addresses));
        final boolean changed = mDnsServerRepository.addServers(lifetime, addresses);
        final boolean linkState;
        if (changed) {
@@ -314,14 +321,17 @@ public class IpClientLinkObserver implements NetworkObserver {
    }

    /**
     * Simple NetlinkMonitor. Currently only listens for PREF64 events.
     * Simple NetlinkMonitor. Listen for netlink events from kernel.
     * All methods except the constructor must be called on the handler thread.
     */
    private class MyNetlinkMonitor extends NetlinkMonitor {
        private final Handler mHandler;

        MyNetlinkMonitor(Handler h, SharedLog log, String tag) {
            super(h, log, tag, OsConstants.NETLINK_ROUTE, NetlinkConstants.RTMGRP_ND_USEROPT);
            super(h, log, tag, OsConstants.NETLINK_ROUTE,
                    !isNetlinkEventParsingEnabled()
                    ? NetlinkConstants.RTMGRP_ND_USEROPT
                    : (NetlinkConstants.RTMGRP_ND_USEROPT | NetlinkConstants.RTMGRP_LINK));
            mHandler = h;
        }

@@ -451,10 +461,39 @@ public class IpClientLinkObserver implements NetworkObserver {
            }
        }

        private void processRtNetlinkLinkMessage(RtNetlinkLinkMessage msg) {
            if (!isNetlinkEventParsingEnabled()) return;

            final StructIfinfoMsg ifinfoMsg = msg.getIfinfoHeader();
            if (ifinfoMsg.family != AF_UNSPEC || ifinfoMsg.index != mIfindex) return;
            if ((ifinfoMsg.flags & IFF_LOOPBACK) != 0) return;

            switch (msg.getHeader().nlmsg_type) {
                case NetlinkConstants.RTM_NEWLINK:
                    final boolean state = (ifinfoMsg.flags & IFF_LOWER_UP) != 0;
                    maybeLog("interfaceLinkStateChanged", "ifindex " + mIfindex
                            + (state ? " up" : " down"));
                    updateInterfaceLinkStateChanged(state);
                    break;

                case NetlinkConstants.RTM_DELLINK:
                    break;

                default:
                    Log.e(mTag, "Unknown rtnetlink link msg type " + msg.getHeader().nlmsg_type);
                    break;
            }
        }

        @Override
        protected void processNetlinkMessage(NetlinkMessage nlMsg, long whenMs) {
            if (!(nlMsg instanceof NduseroptMessage)) return;
            if (nlMsg instanceof NduseroptMessage) {
                processNduseroptMessage((NduseroptMessage) nlMsg, whenMs);
            } else if (nlMsg instanceof RtNetlinkLinkMessage) {
                processRtNetlinkLinkMessage((RtNetlinkLinkMessage) nlMsg);
            } else {
                Log.e(mTag, "Unknown netlink message: " + nlMsg);
            }
        }
    }

+4 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.net.ip;

import static android.net.util.NetworkStackUtils.IPCLIENT_PARSE_NETLINK_EVENTS_VERSION;
import static android.system.OsConstants.RT_SCOPE_UNIVERSE;

import static org.junit.Assert.assertArrayEquals;
@@ -25,6 +26,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
@@ -164,6 +166,8 @@ public class IpClientTest {
        when(mDependencies.getIpMemoryStore(mContext, mNetworkStackServiceManager))
                .thenReturn(mIpMemoryStore);
        when(mDependencies.getIpConnectivityLog()).thenReturn(mMetricsLog);
        when(mDependencies.isFeatureEnabled(eq(mContext),
                eq(IPCLIENT_PARSE_NETLINK_EVENTS_VERSION), anyBoolean())).thenReturn(false);

        mIfParams = null;
    }