diff --git a/framework/Android.bp b/framework/Android.bp
index f3d8689..432cabf 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -95,6 +95,7 @@
     ],
     impl_only_static_libs: [
         "net-utils-device-common-bpf",
+        "net-utils-device-common-struct",
     ],
     libs: [
         "androidx.annotation_annotation",
@@ -126,6 +127,7 @@
         // Even if the library is included in "impl_only_static_libs" of defaults. This is still
         // needed because java_library which doesn't understand "impl_only_static_libs".
         "net-utils-device-common-bpf",
+        "net-utils-device-common-struct",
     ],
     libs: [
         // This cannot be in the defaults clause above because if it were, it would be used
diff --git a/service/src/com/android/server/connectivity/MulticastRoutingCoordinatorService.java b/service/src/com/android/server/connectivity/MulticastRoutingCoordinatorService.java
new file mode 100644
index 0000000..4d5001b
--- /dev/null
+++ b/service/src/com/android/server/connectivity/MulticastRoutingCoordinatorService.java
@@ -0,0 +1,820 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity;
+
+import static android.net.MulticastRoutingConfig.FORWARD_NONE;
+import static android.net.MulticastRoutingConfig.FORWARD_SELECTED;
+import static android.net.MulticastRoutingConfig.FORWARD_WITH_MIN_SCOPE;
+import static android.system.OsConstants.AF_INET6;
+import static android.system.OsConstants.EADDRINUSE;
+import static android.system.OsConstants.IPPROTO_ICMPV6;
+import static android.system.OsConstants.IPPROTO_IPV6;
+import static android.system.OsConstants.SOCK_CLOEXEC;
+import static android.system.OsConstants.SOCK_NONBLOCK;
+import static android.system.OsConstants.SOCK_RAW;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.MulticastRoutingConfig;
+import android.net.NetworkUtils;
+import android.os.Handler;
+import android.os.Looper;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
+import com.android.net.module.util.PacketReader;
+import com.android.net.module.util.SocketUtils;
+import com.android.net.module.util.netlink.NetlinkUtils;
+import com.android.net.module.util.netlink.RtNetlinkRouteMessage;
+import com.android.net.module.util.structs.StructMf6cctl;
+import com.android.net.module.util.structs.StructMif6ctl;
+import com.android.net.module.util.structs.StructMrt6Msg;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.net.Inet6Address;
+import java.net.InetSocketAddress;
+import java.net.MulticastSocket;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.time.Clock;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Class to coordinate multicast routing between network interfaces.
+ *
+ * <p>Supports IPv6 multicast routing.
+ *
+ * <p>Note that usage of this class is not thread-safe. All public methods must be called from the
+ * same thread that the handler from {@code dependencies.getHandler} is associated.
+ */
+public class MulticastRoutingCoordinatorService {
+    private static final String TAG = MulticastRoutingCoordinatorService.class.getSimpleName();
+    private static final int ICMP6_FILTER = 1;
+    private static final int MRT6_INIT = 200;
+    private static final int MRT6_ADD_MIF = 202;
+    private static final int MRT6_DEL_MIF = 203;
+    private static final int MRT6_ADD_MFC = 204;
+    private static final int MRT6_DEL_MFC = 205;
+    private static final int ONE = 1;
+
+    private final Dependencies mDependencies;
+
+    private final Handler mHandler;
+    private final MulticastNocacheUpcallListener mMulticastNoCacheUpcallListener;
+    @NonNull private final FileDescriptor mMulticastRoutingFd; // For multicast routing config
+    @NonNull private final MulticastSocket mMulticastSocket; // For join group and leave group
+
+    @VisibleForTesting public static final int MFC_INACTIVE_CHECK_INTERVAL_MS = 60_000;
+    @VisibleForTesting public static final int MFC_INACTIVE_TIMEOUT_MS = 300_000;
+    @VisibleForTesting public static final int MFC_MAX_NUMBER_OF_ENTRIES = 1_000;
+
+    // The kernel supports max 32 virtual interfaces per multicast routing table.
+    private static final int MAX_NUM_OF_MULTICAST_VIRTUAL_INTERFACES = 32;
+
+    /** Tracks if checking for inactive MFC has been scheduled */
+    private boolean mMfcPollingScheduled = false;
+
+    /** Mapping from multicast virtual interface index to interface name */
+    private SparseArray<String> mVirtualInterfaces =
+            new SparseArray<>(MAX_NUM_OF_MULTICAST_VIRTUAL_INTERFACES);
+    /** Mapping from physical interface index to interface name */
+    private SparseArray<String> mInterfaces =
+            new SparseArray<>(MAX_NUM_OF_MULTICAST_VIRTUAL_INTERFACES);
+
+    /** Mapping of iif to PerInterfaceMulticastRoutingConfig */
+    private Map<String, PerInterfaceMulticastRoutingConfig> mMulticastRoutingConfigs =
+            new HashMap<String, PerInterfaceMulticastRoutingConfig>();
+
+    private static final class PerInterfaceMulticastRoutingConfig {
+        // mapping of oif name to MulticastRoutingConfig
+        public Map<String, MulticastRoutingConfig> oifConfigs =
+                new HashMap<String, MulticastRoutingConfig>();
+    }
+
+    /** Tracks the MFCs added to kernel. Using LinkedHashMap to keep the added order, so
+    // when the number of MFCs reaches the max limit then the earliest added one is removed. */
+    private LinkedHashMap<MfcKey, MfcValue> mMfcs = new LinkedHashMap<>();
+
+    public MulticastRoutingCoordinatorService(Handler h) {
+        this(h, new Dependencies());
+    }
+
+    @VisibleForTesting
+    /* @throws UnsupportedOperationException if multicast routing is not supported */
+    public MulticastRoutingCoordinatorService(Handler h, Dependencies dependencies) {
+        mDependencies = dependencies;
+        mMulticastRoutingFd = mDependencies.createMulticastRoutingSocket();
+        mMulticastSocket = mDependencies.createMulticastSocket();
+        mHandler = h;
+        mMulticastNoCacheUpcallListener =
+                new MulticastNocacheUpcallListener(mHandler, mMulticastRoutingFd);
+        mHandler.post(() -> mMulticastNoCacheUpcallListener.start());
+    }
+
+    private void checkOnHandlerThread() {
+        if (Looper.myLooper() != mHandler.getLooper()) {
+            throw new IllegalStateException(
+                    "Not running on ConnectivityService thread (" + mHandler.getLooper() + ") : "
+                            + Looper.myLooper());
+        }
+    }
+
+    private Integer getInterfaceIndex(String ifName) {
+        int mapIndex = mInterfaces.indexOfValue(ifName);
+        if (mapIndex < 0) return null;
+        return mInterfaces.keyAt(mapIndex);
+    }
+
+    /**
+     * Apply multicast routing configuration
+     *
+     * @param iifName name of the incoming interface
+     * @param oifName name of the outgoing interface
+     * @param newConfig the multicast routing configuration to be applied from iif to oif
+     * @throws MulticastRoutingException when failed to apply the config
+     */
+    public void applyMulticastRoutingConfig(
+            final String iifName, final String oifName, final MulticastRoutingConfig newConfig) {
+        checkOnHandlerThread();
+
+        if (newConfig.getForwardingMode() != FORWARD_NONE) {
+            // Make sure iif and oif are added as multicast forwarding interfaces
+            try {
+                maybeAddAndTrackInterface(iifName);
+                maybeAddAndTrackInterface(oifName);
+            } catch (IllegalStateException e) {
+                Log.e(TAG, "Failed to apply multicast routing config, ", e);
+                return;
+            }
+        }
+
+        final MulticastRoutingConfig oldConfig = getMulticastRoutingConfig(iifName, oifName);
+
+        if (oldConfig.equals(newConfig)) return;
+
+        int oldMode = oldConfig.getForwardingMode();
+        int newMode = newConfig.getForwardingMode();
+        Integer iifIndex = getInterfaceIndex(iifName);
+        if (iifIndex == null) {
+            // This cannot happen unless the new config has FORWARD_NONE but is not the same
+            // as the old config. This is not possible in current code.
+            Log.wtf(TAG, "Adding multicast configuration on null interface?");
+            return;
+        }
+
+        // When new addresses are added to FORWARD_SELECTED mode, join these multicast groups
+        // on their upstream interface, so upstream multicast routers know about the subscription.
+        // When addresses are removed from FORWARD_SELECTED mode, leave the multicast groups.
+        final Set<Inet6Address> oldListeningAddresses =
+                (oldMode == FORWARD_SELECTED)
+                        ? oldConfig.getListeningAddresses()
+                        : new ArraySet<>();
+        final Set<Inet6Address> newListeningAddresses =
+                (newMode == FORWARD_SELECTED)
+                        ? newConfig.getListeningAddresses()
+                        : new ArraySet<>();
+        final CompareResult<Inet6Address> addressDiff =
+                new CompareResult<>(oldListeningAddresses, newListeningAddresses);
+        joinGroups(iifIndex, addressDiff.added);
+        leaveGroups(iifIndex, addressDiff.removed);
+
+        setMulticastRoutingConfig(iifName, oifName, newConfig);
+        Log.d(
+                TAG,
+                "Applied multicast routing config for iif "
+                        + iifName
+                        + " to oif "
+                        + oifName
+                        + " with Config "
+                        + newConfig);
+
+        // Update existing MFCs to make sure they align with the updated configuration
+        updateMfcs();
+
+        if (newConfig.getForwardingMode() == FORWARD_NONE) {
+            if (!hasActiveMulticastConfig(iifName)) {
+                removeInterfaceFromMulticastRouting(iifName);
+            }
+            if (!hasActiveMulticastConfig(oifName)) {
+                removeInterfaceFromMulticastRouting(oifName);
+            }
+        }
+    }
+
+    /**
+     * Removes an network interface from multicast routing.
+     *
+     * <p>Remove the network interface from multicast configs and remove it from the list of
+     * multicast routing interfaces in the kernel
+     *
+     * @param ifName name of the interface that should be removed
+     */
+    @VisibleForTesting
+    public void removeInterfaceFromMulticastRouting(final String ifName) {
+        checkOnHandlerThread();
+        final Integer virtualIndex = getVirtualInterfaceIndex(ifName);
+        if (virtualIndex == null) return;
+
+        updateMfcs();
+        mInterfaces.removeAt(mInterfaces.indexOfValue(ifName));
+        mVirtualInterfaces.remove(virtualIndex);
+        try {
+            mDependencies.setsockoptMrt6DelMif(mMulticastRoutingFd, virtualIndex);
+            Log.d(TAG, "Removed mifi " + virtualIndex + " from MIF");
+        } catch (ErrnoException e) {
+            Log.e(TAG, "failed to remove multicast virtual interface" + virtualIndex, e);
+        }
+    }
+
+    private int getNextAvailableVirtualIndex() {
+        if (mVirtualInterfaces.size() >= MAX_NUM_OF_MULTICAST_VIRTUAL_INTERFACES) {
+            throw new IllegalStateException("Can't allocate new multicast virtual interface");
+        }
+        for (int i = 0; i < mVirtualInterfaces.size(); i++) {
+            if (!mVirtualInterfaces.contains(i)) {
+                return i;
+            }
+        }
+        return mVirtualInterfaces.size();
+    }
+
+    @VisibleForTesting
+    public Integer getVirtualInterfaceIndex(String ifName) {
+        int mapIndex = mVirtualInterfaces.indexOfValue(ifName);
+        if (mapIndex < 0) return null;
+        return mVirtualInterfaces.keyAt(mapIndex);
+    }
+
+    private Integer getVirtualInterfaceIndex(int physicalIndex) {
+        String ifName = mInterfaces.get(physicalIndex);
+        if (ifName == null) {
+            // This is only used to match MFCs from kernel to MFCs we know about.
+            // Unknown MFCs should be ignored.
+            return null;
+        }
+        return getVirtualInterfaceIndex(ifName);
+    }
+
+    private String getInterfaceName(int virtualIndex) {
+        return mVirtualInterfaces.get(virtualIndex);
+    }
+
+    private void maybeAddAndTrackInterface(String ifName) {
+        checkOnHandlerThread();
+        if (mVirtualInterfaces.indexOfValue(ifName) >= 0) return;
+
+        int nextVirtualIndex = getNextAvailableVirtualIndex();
+        int ifIndex = mDependencies.getInterfaceIndex(ifName);
+        final StructMif6ctl mif6ctl =
+                    new StructMif6ctl(
+                            nextVirtualIndex,
+                            (short) 0 /* mif6c_flags */,
+                            (short) 1 /* vifc_threshold */,
+                            ifIndex,
+                            0 /* vifc_rate_limit */);
+        try {
+            mDependencies.setsockoptMrt6AddMif(mMulticastRoutingFd, mif6ctl);
+            Log.d(TAG, "Added mifi " + nextVirtualIndex + " to MIF");
+        } catch (ErrnoException e) {
+            Log.e(TAG, "failed to add multicast virtual interface", e);
+            return;
+        }
+        mVirtualInterfaces.put(nextVirtualIndex, ifName);
+        mInterfaces.put(ifIndex, ifName);
+    }
+
+    @VisibleForTesting
+    public MulticastRoutingConfig getMulticastRoutingConfig(String iifName, String oifName) {
+        PerInterfaceMulticastRoutingConfig configs = mMulticastRoutingConfigs.get(iifName);
+        final MulticastRoutingConfig defaultConfig = MulticastRoutingConfig.CONFIG_FORWARD_NONE;
+        if (configs == null) {
+            return defaultConfig;
+        } else {
+            return configs.oifConfigs.getOrDefault(oifName, defaultConfig);
+        }
+    }
+
+    private void setMulticastRoutingConfig(
+            final String iifName, final String oifName, final MulticastRoutingConfig config) {
+        checkOnHandlerThread();
+        PerInterfaceMulticastRoutingConfig iifConfig = mMulticastRoutingConfigs.get(iifName);
+
+        if (config.getForwardingMode() == FORWARD_NONE) {
+            if (iifConfig != null) {
+                iifConfig.oifConfigs.remove(oifName);
+            }
+            if (iifConfig.oifConfigs.isEmpty()) {
+                mMulticastRoutingConfigs.remove(iifName);
+            }
+            return;
+        }
+
+        if (iifConfig == null) {
+            iifConfig = new PerInterfaceMulticastRoutingConfig();
+            mMulticastRoutingConfigs.put(iifName, iifConfig);
+        }
+        iifConfig.oifConfigs.put(oifName, config);
+    }
+
+    /** Returns whether an interface has multicast routing config */
+    private boolean hasActiveMulticastConfig(final String ifName) {
+        // FORWARD_NONE configs are not saved in the config tables, so
+        // any existing config is an active multicast routing config
+        if (mMulticastRoutingConfigs.containsKey(ifName)) return true;
+        for (var pic : mMulticastRoutingConfigs.values()) {
+            if (pic.oifConfigs.containsKey(ifName)) return true;
+        }
+        return false;
+    }
+
+    /**
+     * A multicast forwarding cache (MFC) entry holds a multicast forwarding route where packet from
+     * incoming interface(iif) with source address(S) to group address (G) are forwarded to outgoing
+     * interfaces(oifs).
+     *
+     * <p>iif, S and G identifies an MFC entry. For example an MFC1 is added: [iif1, S1, G1, oifs1]
+     * Adding another MFC2 of [iif1, S1, G1, oifs2] to the kernel overwrites MFC1.
+     */
+    private static final class MfcKey {
+        public final int mIifVirtualIdx;
+        public final Inet6Address mSrcAddr;
+        public final Inet6Address mDstAddr;
+
+        public MfcKey(int iif, Inet6Address src, Inet6Address dst) {
+            mIifVirtualIdx = iif;
+            mSrcAddr = src;
+            mDstAddr = dst;
+        }
+
+        public boolean equals(Object other) {
+            if (other == this) {
+                return true;
+            } else if (!(other instanceof MfcKey)) {
+                return false;
+            } else {
+                MfcKey otherKey = (MfcKey) other;
+                return mIifVirtualIdx == otherKey.mIifVirtualIdx
+                        && mSrcAddr.equals(otherKey.mSrcAddr)
+                        && mDstAddr.equals(otherKey.mDstAddr);
+            }
+        }
+
+        public int hashCode() {
+            return Objects.hash(mIifVirtualIdx, mSrcAddr, mDstAddr);
+        }
+
+        public String toString() {
+            return "{iifVirtualIndex: "
+                    + Integer.toString(mIifVirtualIdx)
+                    + ", sourceAddress: "
+                    + mSrcAddr.toString()
+                    + ", destinationAddress: "
+                    + mDstAddr.toString()
+                    + "}";
+        }
+    }
+
+    private static final class MfcValue {
+        private Set<Integer> mOifVirtualIndices;
+        // timestamp of when the mfc was last used in the kernel
+        // (e.g. created, or used to forward a packet)
+        private Instant mLastUsedAt;
+
+        public MfcValue(Set<Integer> oifs, Instant timestamp) {
+            mOifVirtualIndices = oifs;
+            mLastUsedAt = timestamp;
+        }
+
+        public boolean hasSameOifsAs(MfcValue other) {
+            return this.mOifVirtualIndices.equals(other.mOifVirtualIndices);
+        }
+
+        public boolean equals(Object other) {
+            if (other == this) {
+                return true;
+            } else if (!(other instanceof MfcValue)) {
+                return false;
+            } else {
+                MfcValue otherValue = (MfcValue) other;
+                return mOifVirtualIndices.equals(otherValue.mOifVirtualIndices)
+                        && mLastUsedAt.equals(otherValue.mLastUsedAt);
+            }
+        }
+
+        public int hashCode() {
+            return Objects.hash(mOifVirtualIndices, mLastUsedAt);
+        }
+
+        public Set<Integer> getOifIndices() {
+            return mOifVirtualIndices;
+        }
+
+        public void setLastUsedAt(Instant timestamp) {
+            mLastUsedAt = timestamp;
+        }
+
+        public Instant getLastUsedAt() {
+            return mLastUsedAt;
+        }
+
+        public String toString() {
+            return "{oifVirtualIdxes: "
+                    + mOifVirtualIndices.toString()
+                    + ", lastUsedAt: "
+                    + mLastUsedAt.toString()
+                    + "}";
+        }
+    }
+
+    /**
+     * Returns the MFC value for the given MFC key according to current multicast routing config. If
+     * the MFC should be removed return null.
+     */
+    private MfcValue computeMfcValue(int iif, Inet6Address dst) {
+        final int dstScope = getGroupAddressScope(dst);
+        Set<Integer> forwardingOifs = new ArraySet<>();
+
+        PerInterfaceMulticastRoutingConfig iifConfig =
+                mMulticastRoutingConfigs.get(getInterfaceName(iif));
+
+        if (iifConfig == null) {
+            // An iif may have been removed from multicast routing, in this
+            // case remove the MFC directly
+            return null;
+        }
+
+        for (var config : iifConfig.oifConfigs.entrySet()) {
+            if ((config.getValue().getForwardingMode() == FORWARD_WITH_MIN_SCOPE
+                            && config.getValue().getMinimumScope() <= dstScope)
+                    || (config.getValue().getForwardingMode() == FORWARD_SELECTED
+                            && config.getValue().getListeningAddresses().contains(dst))) {
+                forwardingOifs.add(getVirtualInterfaceIndex(config.getKey()));
+            }
+        }
+
+        return new MfcValue(forwardingOifs, Instant.now(mDependencies.getClock()));
+    }
+
+    /**
+     * Given the iif, source address and group destination address, add an MFC entry or update the
+     * existing MFC according to the multicast routing config. If such an MFC should not exist,
+     * return null for caller of the function to remove it.
+     *
+     * <p>Note that if a packet has no matching MFC entry in the kernel, kernel creates an
+     * unresolved route and notifies multicast socket with a NOCACHE upcall message. The unresolved
+     * route is kept for no less than 10s. If packets with the same source and destination arrives
+     * before the 10s timeout, they will not be notified. Thus we need to add a 'blocking' MFC which
+     * is an MFC with an empty oif list. When the multicast configs changes, the 'blocking' MFC
+     * will be updated to a 'forwarding' MFC so that corresponding multicast traffic can be
+     * forwarded instantly.
+     *
+     * @return {@code true} if the MFC is updated and no operation is needed from caller.
+     * {@code false} if the MFC should not be added, caller of the function should remove
+     * the MFC if needed.
+     */
+    private boolean addOrUpdateMfc(int vif, Inet6Address src, Inet6Address dst) {
+        checkOnHandlerThread();
+        final MfcKey key = new MfcKey(vif, src, dst);
+        final MfcValue value = mMfcs.get(key);
+        final MfcValue updatedValue = computeMfcValue(vif, dst);
+
+        if (updatedValue == null) {
+            return false;
+        }
+
+        if (value != null && value.hasSameOifsAs(updatedValue)) {
+            // no updates to make
+            return true;
+        }
+
+        final StructMf6cctl mf6cctl =
+                new StructMf6cctl(src, dst, vif, updatedValue.getOifIndices());
+        try {
+            mDependencies.setsockoptMrt6AddMfc(mMulticastRoutingFd, mf6cctl);
+        } catch (ErrnoException e) {
+            Log.e(TAG, "failed to add MFC: " + e);
+            return false;
+        }
+        mMfcs.put(key, updatedValue);
+        String operation = (value == null ? "Added" : "Updated");
+        Log.d(TAG, operation + " MFC key: " + key + " value: " + updatedValue);
+        return true;
+    }
+
+    private void checkMfcsExpiration() {
+        checkOnHandlerThread();
+        // Check if there are inactive MFCs that can be removed
+        refreshMfcInactiveDuration();
+        maybeExpireMfcs();
+        if (mMfcs.size() > 0) {
+            mHandler.postDelayed(() -> checkMfcsExpiration(), MFC_INACTIVE_CHECK_INTERVAL_MS);
+            mMfcPollingScheduled = true;
+        } else {
+            mMfcPollingScheduled = false;
+        }
+    }
+
+    private void checkMfcEntriesLimit() {
+        checkOnHandlerThread();
+        // If the max number of MFC entries is reached, remove the first MFC entry. This can be
+        // any entry, as if this entry is needed again there will be a NOCACHE upcall to add it
+        // back.
+        if (mMfcs.size() == MFC_MAX_NUMBER_OF_ENTRIES) {
+            Log.w(TAG, "Reached max number of MFC entries " + MFC_MAX_NUMBER_OF_ENTRIES);
+            var iter = mMfcs.entrySet().iterator();
+            MfcKey firstMfcKey = iter.next().getKey();
+            removeMfcFromKernel(firstMfcKey);
+            iter.remove();
+        }
+    }
+
+    /**
+     * Reads multicast routes information from the kernel, and update the last used timestamp for
+     * each multicast route save in this class.
+     */
+    private void refreshMfcInactiveDuration() {
+        checkOnHandlerThread();
+        final List<RtNetlinkRouteMessage> multicastRoutes = NetlinkUtils.getIpv6MulticastRoutes();
+
+        for (var route : multicastRoutes) {
+            if (!route.isResolved()) {
+                continue; // Don't handle unresolved mfc, the kernel will recycle in 10s
+            }
+            Integer iif = getVirtualInterfaceIndex(route.getIifIndex());
+            if (iif == null) {
+                Log.e(TAG, "Can't find kernel returned IIF " + route.getIifIndex());
+                return;
+            }
+            final MfcKey key =
+                    new MfcKey(
+                            iif,
+                            (Inet6Address) route.getSource().getAddress(),
+                            (Inet6Address) route.getDestination().getAddress());
+            MfcValue value = mMfcs.get(key);
+            if (value == null) {
+                Log.e(TAG, "Can't find kernel returned MFC " + key);
+                continue;
+            }
+            value.setLastUsedAt(
+                    Instant.now(mDependencies.getClock())
+                            .minusMillis(route.getSinceLastUseMillis()));
+        }
+    }
+
+    /** Remove MFC entry from mMfcs map and the kernel if exists. */
+    private void removeMfcFromKernel(MfcKey key) {
+        checkOnHandlerThread();
+
+        final MfcValue value = mMfcs.get(key);
+        final Set<Integer> oifs = new ArraySet<>();
+        final StructMf6cctl mf6cctl =
+                new StructMf6cctl(key.mSrcAddr, key.mDstAddr, key.mIifVirtualIdx, oifs);
+        try {
+            mDependencies.setsockoptMrt6DelMfc(mMulticastRoutingFd, mf6cctl);
+        } catch (ErrnoException e) {
+            Log.e(TAG, "failed to remove MFC: " + e);
+            return;
+        }
+        Log.d(TAG, "Removed MFC key: " + key + " value: " + value);
+    }
+
+    /**
+     * This is called every MFC_INACTIVE_CHECK_INTERVAL_MS milliseconds to remove any MFC that is
+     * inactive for more than MFC_INACTIVE_TIMEOUT_MS milliseconds.
+     */
+    private void maybeExpireMfcs() {
+        checkOnHandlerThread();
+
+        for (var it = mMfcs.entrySet().iterator(); it.hasNext(); ) {
+            var entry = it.next();
+            if (entry.getValue()
+                    .getLastUsedAt()
+                    .plusMillis(MFC_INACTIVE_TIMEOUT_MS)
+                    .isBefore(Instant.now(mDependencies.getClock()))) {
+                removeMfcFromKernel(entry.getKey());
+                it.remove();
+            }
+        }
+    }
+
+    private void updateMfcs() {
+        checkOnHandlerThread();
+
+        for (Iterator<Map.Entry<MfcKey, MfcValue>> it = mMfcs.entrySet().iterator();
+                it.hasNext(); ) {
+            MfcKey key = it.next().getKey();
+            if (!addOrUpdateMfc(key.mIifVirtualIdx, key.mSrcAddr, key.mDstAddr)) {
+                removeMfcFromKernel(key);
+                it.remove();
+            }
+        }
+
+        refreshMfcInactiveDuration();
+    }
+
+    private void joinGroups(int ifIndex, List<Inet6Address> addresses) {
+        for (Inet6Address address : addresses) {
+            InetSocketAddress socketAddress = new InetSocketAddress(address, 0);
+            try {
+                mMulticastSocket.joinGroup(
+                        socketAddress, mDependencies.getNetworkInterface(ifIndex));
+            } catch (IOException e) {
+                if (e.getCause() instanceof ErrnoException) {
+                    ErrnoException ee = (ErrnoException) e.getCause();
+                    if (ee.errno == EADDRINUSE) {
+                        // The list of added address are calculated from address changes,
+                        // repeated join group is unexpected
+                        Log.e(TAG, "Already joined group" + e);
+                        continue;
+                    }
+                }
+                Log.e(TAG, "failed to join group: " + e);
+            }
+        }
+    }
+
+    private void leaveGroups(int ifIndex, List<Inet6Address> addresses) {
+        for (Inet6Address address : addresses) {
+            InetSocketAddress socketAddress = new InetSocketAddress(address, 0);
+            try {
+                mMulticastSocket.leaveGroup(
+                        socketAddress, mDependencies.getNetworkInterface(ifIndex));
+            } catch (IOException e) {
+                Log.e(TAG, "failed to leave group: " + e);
+            }
+        }
+    }
+
+    private int getGroupAddressScope(Inet6Address address) {
+        return address.getAddress()[1] & 0xf;
+    }
+
+    /**
+     * Handles a NoCache upcall that indicates a multicast packet is received and requires
+     * a multicast forwarding cache to be added.
+     *
+     * A forwarding or blocking MFC is added according to the multicast config.
+     *
+     * The number of MFCs is checked to make sure it doesn't exceed the
+     * {@code MFC_MAX_NUMBER_OF_ENTRIES} limit.
+     */
+    @VisibleForTesting
+    public void handleMulticastNocacheUpcall(final StructMrt6Msg mrt6Msg) {
+        final int iifVid = mrt6Msg.mif;
+
+        // add MFC to forward the packet or add blocking MFC to not forward the packet
+        // If the packet comes from an interface the service doesn't care about, the
+        // addOrUpdateMfc function will return null and not MFC will be added.
+        if (!addOrUpdateMfc(iifVid, mrt6Msg.src, mrt6Msg.dst)) return;
+        // If the list of MFCs is not empty and there is no MFC check scheduled,
+        // schedule one now
+        if (!mMfcPollingScheduled) {
+            mHandler.postDelayed(() -> checkMfcsExpiration(), MFC_INACTIVE_CHECK_INTERVAL_MS);
+            mMfcPollingScheduled = true;
+        }
+
+        checkMfcEntriesLimit();
+    }
+
+    /**
+     * A packet reader that handles the packets sent to the multicast routing socket
+     */
+    private final class MulticastNocacheUpcallListener extends PacketReader {
+        private final FileDescriptor mFd;
+
+        public MulticastNocacheUpcallListener(Handler h, FileDescriptor fd) {
+            super(h);
+            mFd = fd;
+        }
+
+        @Override
+        protected FileDescriptor createFd() {
+            return mFd;
+        }
+
+        @Override
+        protected void handlePacket(byte[] recvbuf, int length) {
+            final ByteBuffer buf = ByteBuffer.wrap(recvbuf);
+            final StructMrt6Msg mrt6Msg = StructMrt6Msg.parse(buf);
+            if (mrt6Msg.msgType != StructMrt6Msg.MRT6MSG_NOCACHE) {
+                return;
+            }
+            handleMulticastNocacheUpcall(mrt6Msg);
+        }
+    }
+
+    /** Dependencies of RoutingCoordinatorService, for test injections. */
+    @VisibleForTesting
+    public static class Dependencies {
+        private final Clock mClock = Clock.system(ZoneId.systemDefault());
+
+        /**
+         * Creates a socket to configure multicast routing in the kernel.
+         *
+         * <p>If the kernel doesn't support multicast routing, then the {@code setsockoptInt} with
+         * {@code MRT6_INIT} method would fail.
+         *
+         * @return the multicast routing socket, or null if it fails to be created/configured.
+         */
+        public FileDescriptor createMulticastRoutingSocket() {
+            FileDescriptor sock = null;
+            byte[] filter = new byte[32]; // filter all ICMPv6 messages
+            try {
+                sock = Os.socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_ICMPV6);
+                Os.setsockoptInt(sock, IPPROTO_IPV6, MRT6_INIT, ONE);
+                NetworkUtils.setsockoptBytes(sock, IPPROTO_ICMPV6, ICMP6_FILTER, filter);
+            } catch (ErrnoException e) {
+                Log.e(TAG, "failed to create multicast socket: " + e);
+                if (sock != null) {
+                    SocketUtils.closeSocketQuietly(sock);
+                }
+                throw new UnsupportedOperationException("Multicast routing is not supported ", e);
+            }
+            Log.i(TAG, "socket created for multicast routing: " + sock);
+            return sock;
+        }
+
+        public MulticastSocket createMulticastSocket() {
+            try {
+                return new MulticastSocket();
+            } catch (IOException e) {
+                Log.wtf(TAG, "Failed to create multicast socket " + e);
+                throw new IllegalStateException(e);
+            }
+        }
+
+        public void setsockoptMrt6AddMif(FileDescriptor fd, StructMif6ctl mif6ctl)
+                throws ErrnoException {
+            final byte[] bytes = mif6ctl.writeToBytes();
+            NetworkUtils.setsockoptBytes(fd, IPPROTO_IPV6, MRT6_ADD_MIF, bytes);
+        }
+
+        public void setsockoptMrt6DelMif(FileDescriptor fd, int virtualIfIndex)
+                throws ErrnoException {
+            Os.setsockoptInt(fd, IPPROTO_IPV6, MRT6_DEL_MIF, virtualIfIndex);
+        }
+
+        public void setsockoptMrt6AddMfc(FileDescriptor fd, StructMf6cctl mf6cctl)
+                throws ErrnoException {
+            final byte[] bytes = mf6cctl.writeToBytes();
+            NetworkUtils.setsockoptBytes(fd, IPPROTO_IPV6, MRT6_ADD_MFC, bytes);
+        }
+
+        public void setsockoptMrt6DelMfc(FileDescriptor fd, StructMf6cctl mf6cctl)
+                throws ErrnoException {
+            final byte[] bytes = mf6cctl.writeToBytes();
+            NetworkUtils.setsockoptBytes(fd, IPPROTO_IPV6, MRT6_DEL_MFC, bytes);
+        }
+
+        public Integer getInterfaceIndex(String ifName) {
+            try {
+                NetworkInterface ni = NetworkInterface.getByName(ifName);
+                return ni.getIndex();
+            } catch (NullPointerException | SocketException e) {
+                return null;
+            }
+        }
+
+        public NetworkInterface getNetworkInterface(int physicalIndex) {
+            try {
+                return NetworkInterface.getByIndex(physicalIndex);
+            } catch (SocketException e) {
+                return null;
+            }
+        }
+
+        public Clock getClock() {
+            return mClock;
+        }
+    }
+}
diff --git a/tests/unit/java/com/android/server/connectivity/MulticastRoutingCoordinatorServiceTest.kt b/tests/unit/java/com/android/server/connectivity/MulticastRoutingCoordinatorServiceTest.kt
new file mode 100644
index 0000000..6c2c256
--- /dev/null
+++ b/tests/unit/java/com/android/server/connectivity/MulticastRoutingCoordinatorServiceTest.kt
@@ -0,0 +1,499 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity
+
+import android.net.MulticastRoutingConfig
+import android.os.Build
+import android.os.Handler
+import android.os.HandlerThread
+import android.os.Looper
+import android.os.ParcelFileDescriptor
+import android.os.SystemClock
+import android.os.test.TestLooper
+import android.system.Os
+import android.system.OsConstants.AF_INET6
+import android.system.OsConstants.IPPROTO_UDP
+import android.system.OsConstants.SOCK_DGRAM
+import android.util.Log
+import androidx.test.filters.LargeTest
+import com.android.net.module.util.structs.StructMf6cctl
+import com.android.net.module.util.structs.StructMrt6Msg
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
+import com.android.testutils.DevSdkIgnoreRunner
+import com.android.testutils.tryTest
+import com.google.common.truth.Truth.assertThat
+import java.io.FileDescriptor
+import java.net.DatagramPacket
+import java.net.DatagramSocket
+import java.net.InetAddress
+import java.net.Inet6Address
+import java.net.InetSocketAddress
+import java.net.MulticastSocket
+import java.net.NetworkInterface
+import java.time.Clock
+import java.time.Instant
+import java.time.ZoneId
+import java.util.concurrent.atomic.AtomicBoolean
+import kotlin.test.assertTrue
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mock
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.inOrder
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.timeout
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+import kotlin.test.assertEquals
+import kotlin.test.assertNotEquals
+import kotlin.test.assertNotNull
+import kotlin.test.assertNull
+
+private const val TIMEOUT_MS = 2_000L
+
+@RunWith(DevSdkIgnoreRunner::class)
+@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+class MulticastRoutingCoordinatorServiceTest {
+
+    // mocks are lateinit as they need to be setup between tests
+    @Mock private lateinit var mDeps: MulticastRoutingCoordinatorService.Dependencies
+    @Mock private lateinit var mMulticastSocket: MulticastSocket
+
+    val mSock = DatagramSocket()
+    val mPfd = ParcelFileDescriptor.fromDatagramSocket(mSock)
+    val mFd = mPfd.getFileDescriptor()
+    val mIfName1 = "interface1"
+    val mIfName2 = "interface2"
+    val mIfName3 = "interface3"
+    val mIfPhysicalIndex1 = 10
+    val mIfPhysicalIndex2 = 11
+    val mIfPhysicalIndex3 = 12
+    val mSourceAddress = Inet6Address.getByName("2000::8888") as Inet6Address
+    val mGroupAddressScope5 = Inet6Address.getByName("ff05::1234") as Inet6Address
+    val mGroupAddressScope4 = Inet6Address.getByName("ff04::1234") as Inet6Address
+    val mGroupAddressScope3 = Inet6Address.getByName("ff03::1234") as Inet6Address
+    val mSocketAddressScope5 = InetSocketAddress(mGroupAddressScope5, 0)
+    val mSocketAddressScope4 = InetSocketAddress(mGroupAddressScope4, 0)
+    val mEmptyOifs = setOf<Int>()
+    val mClock = FakeClock()
+    val mNetworkInterface1 = createEmptyNetworkInterface()
+    val mNetworkInterface2 = createEmptyNetworkInterface()
+    // MulticastRoutingCoordinatorService needs to be initialized after the dependencies
+    // are mocked.
+    lateinit var mService: MulticastRoutingCoordinatorService
+    lateinit var mLooper: TestLooper
+
+    class FakeClock() : Clock() {
+        private var offsetMs = 0L
+
+        fun fastForward(ms: Long) {
+            offsetMs += ms
+        }
+
+        override fun instant(): Instant {
+            return Instant.now().plusMillis(offsetMs)
+        }
+
+        override fun getZone(): ZoneId {
+            throw RuntimeException("Not implemented");
+        }
+
+        override fun withZone(zone: ZoneId): Clock {
+            throw RuntimeException("Not implemented");
+        }
+
+    }
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        doReturn(mClock).`when`(mDeps).getClock()
+        doReturn(mFd).`when`(mDeps).createMulticastRoutingSocket()
+        doReturn(mMulticastSocket).`when`(mDeps).createMulticastSocket()
+        doReturn(mIfPhysicalIndex1).`when`(mDeps).getInterfaceIndex(mIfName1)
+        doReturn(mIfPhysicalIndex2).`when`(mDeps).getInterfaceIndex(mIfName2)
+        doReturn(mIfPhysicalIndex3).`when`(mDeps).getInterfaceIndex(mIfName3)
+        doReturn(mNetworkInterface1).`when`(mDeps).getNetworkInterface(mIfPhysicalIndex1)
+        doReturn(mNetworkInterface2).`when`(mDeps).getNetworkInterface(mIfPhysicalIndex2)
+    }
+
+    @After
+    fun tearDown() {
+        mSock.close()
+    }
+
+    // Functions under @Before and @Test run in different threads,
+    // (i.e. androidx.test.runner.AndroidJUnitRunner vs Time-limited test)
+    // MulticastRoutingCoordinatorService requires the jobs are run on the thread looper,
+    // so TestLooper needs to be created inside each test case to install the
+    // correct looper.
+    fun prepareService() {
+        mLooper = TestLooper()
+        val handler = Handler(mLooper.getLooper())
+
+        mService = MulticastRoutingCoordinatorService(handler, mDeps)
+    }
+
+    private fun createEmptyNetworkInterface(): NetworkInterface {
+        val constructor = NetworkInterface::class.java.getDeclaredConstructor()
+        constructor.isAccessible = true
+        return constructor.newInstance()
+    }
+
+    private fun createStructMf6cctl(src: Inet6Address, dst: Inet6Address, iifIdx: Int,
+            oifSet: Set<Int>): StructMf6cctl {
+        return StructMf6cctl(src, dst, iifIdx, oifSet)
+    }
+
+    // Send a MRT6MSG_NOCACHE packet to sock, to indicate a packet has arrived without matching MulticastRoutingCache
+    private fun sendMrt6msgNocachePacket(interfaceVirtualIndex: Int,
+            source: Inet6Address, destination: Inet6Address) {
+        mLooper.dispatchAll() // let MulticastRoutingCoordinatorService handle all msgs first to
+                              // apply any possible multicast routing config changes
+        val mrt6Msg = StructMrt6Msg(0 /* mbz must be 0 */, StructMrt6Msg.MRT6MSG_NOCACHE,
+                interfaceVirtualIndex, source, destination)
+        mLooper.getNewExecutor().execute({ mService.handleMulticastNocacheUpcall(mrt6Msg) })
+        mLooper.dispatchAll()
+    }
+
+    private fun applyMulticastForwardNone(fromIf: String, toIf: String) {
+        val configNone = MulticastRoutingConfig.CONFIG_FORWARD_NONE
+
+        mService.applyMulticastRoutingConfig(fromIf, toIf, configNone)
+    }
+
+    private fun applyMulticastForwardMinimumScope(fromIf: String, toIf: String, minScope: Int) {
+        val configMinimumScope = MulticastRoutingConfig.Builder(
+            MulticastRoutingConfig.FORWARD_WITH_MIN_SCOPE, minScope).build()
+
+        mService.applyMulticastRoutingConfig(fromIf, toIf, configMinimumScope)
+    }
+
+    private fun applyMulticastForwardSelected(fromIf: String, toIf: String) {
+        val configSelected = MulticastRoutingConfig.Builder(
+            MulticastRoutingConfig.FORWARD_SELECTED)
+            .addListeningAddress(mGroupAddressScope5).build()
+
+        mService.applyMulticastRoutingConfig(fromIf, toIf, configSelected)
+    }
+
+    @Test
+    fun testConstructor_multicastRoutingSocketIsCreated() {
+        prepareService()
+        verify(mDeps).createMulticastRoutingSocket()
+    }
+
+    @Test
+    fun testMulticastRouting_applyForwardNone() {
+        prepareService()
+
+        applyMulticastForwardNone(mIfName1, mIfName2)
+        mLooper.dispatchAll()
+
+        // Both interfaces are not added as multicast routing interfaces
+        verify(mDeps, never()).setsockoptMrt6AddMif(eq(mFd), any())
+        // No MFC should be added for FORWARD_NONE
+        verify(mDeps, never()).setsockoptMrt6AddMfc(eq(mFd), any())
+        assertEquals(MulticastRoutingConfig.CONFIG_FORWARD_NONE,
+                mService.getMulticastRoutingConfig(mIfName1, mIfName2));
+    }
+
+    @Test
+    fun testMulticastRouting_applyForwardMinimumScope() {
+        prepareService()
+
+        applyMulticastForwardMinimumScope(mIfName1, mIfName2, 4 /* minScope */)
+        mLooper.dispatchAll()
+
+        // No MFC is added for FORWARD_WITH_MIN_SCOPE
+        verify(mDeps, never()).setsockoptMrt6AddMfc(eq(mFd), any())
+        assertEquals(MulticastRoutingConfig.FORWARD_WITH_MIN_SCOPE,
+                mService.getMulticastRoutingConfig(mIfName1, mIfName2).getForwardingMode())
+        assertEquals(4, mService.getMulticastRoutingConfig(mIfName1, mIfName2).getMinimumScope())
+    }
+
+    @Test
+    fun testMulticastRouting_addressScopelargerThanMinScope_allowMfcIsAdded() {
+        prepareService()
+        applyMulticastForwardMinimumScope(mIfName1, mIfName2, 4 /* minScope */)
+        mLooper.dispatchAll()
+        val oifs = setOf(mService.getVirtualInterfaceIndex(mIfName2))
+        val mf6cctl = createStructMf6cctl(mSourceAddress, mGroupAddressScope5,
+                mService.getVirtualInterfaceIndex(mIfName1), oifs)
+
+        // simulate a MRT6MSG_NOCACHE upcall for a packet sent to group address of scope 5
+        sendMrt6msgNocachePacket(0, mSourceAddress, mGroupAddressScope5)
+
+        // an MFC is added for the packet
+        verify(mDeps).setsockoptMrt6AddMfc(eq(mFd), eq(mf6cctl))
+    }
+
+    @Test
+    fun testMulticastRouting_addressScopeSmallerThanMinScope_blockingMfcIsAdded() {
+        prepareService()
+        applyMulticastForwardMinimumScope(mIfName1, mIfName2, 4)
+        val mf6cctl = createStructMf6cctl(mSourceAddress, mGroupAddressScope3,
+                mService.getVirtualInterfaceIndex(mIfName1), mEmptyOifs)
+
+        // simulate a MRT6MSG_NOCACHE upcall when a packet should not be forwarded
+        sendMrt6msgNocachePacket(0, mSourceAddress, mGroupAddressScope3)
+
+        // a blocking MFC is added
+        verify(mDeps).setsockoptMrt6AddMfc(eq(mFd), eq(mf6cctl))
+    }
+
+    @Test
+    fun testMulticastRouting_applyForwardSelected_joinsGroup() {
+        prepareService()
+
+        applyMulticastForwardSelected(mIfName1, mIfName2)
+        mLooper.dispatchAll()
+
+        verify(mMulticastSocket).joinGroup(eq(mSocketAddressScope5), eq(mNetworkInterface1))
+        assertEquals(MulticastRoutingConfig.FORWARD_SELECTED,
+                mService.getMulticastRoutingConfig(mIfName1, mIfName2).getForwardingMode())
+    }
+
+    @Test
+    fun testMulticastRouting_addListeningAddressInForwardSelected_joinsGroup() {
+        prepareService()
+
+        val configSelectedNoAddress = MulticastRoutingConfig.Builder(
+            MulticastRoutingConfig.FORWARD_SELECTED).build()
+        mService.applyMulticastRoutingConfig(mIfName1, mIfName2, configSelectedNoAddress)
+        mLooper.dispatchAll()
+
+        val configSelectedWithAddresses = MulticastRoutingConfig.Builder(
+            MulticastRoutingConfig.FORWARD_SELECTED)
+            .addListeningAddress(mGroupAddressScope5)
+            .addListeningAddress(mGroupAddressScope4)
+            .build()
+        mService.applyMulticastRoutingConfig(mIfName1, mIfName2, configSelectedWithAddresses)
+        mLooper.dispatchAll()
+
+        verify(mMulticastSocket).joinGroup(eq(mSocketAddressScope5), eq(mNetworkInterface1))
+        verify(mMulticastSocket).joinGroup(eq(mSocketAddressScope4), eq(mNetworkInterface1))
+    }
+
+    @Test
+    fun testMulticastRouting_removeListeningAddressInForwardSelected_leavesGroup() {
+        prepareService()
+        val configSelectedWith2Addresses = MulticastRoutingConfig.Builder(
+            MulticastRoutingConfig.FORWARD_SELECTED)
+            .addListeningAddress(mGroupAddressScope5)
+            .addListeningAddress(mGroupAddressScope4)
+            .build()
+        mService.applyMulticastRoutingConfig(mIfName1, mIfName2, configSelectedWith2Addresses)
+        mLooper.dispatchAll()
+
+        verify(mMulticastSocket).joinGroup(eq(mSocketAddressScope5), eq(mNetworkInterface1))
+        verify(mMulticastSocket).joinGroup(eq(mSocketAddressScope4), eq(mNetworkInterface1))
+
+        // remove the scope4 address
+        val configSelectedWith1Address = MulticastRoutingConfig.Builder(
+            MulticastRoutingConfig.FORWARD_SELECTED)
+            .addListeningAddress(mGroupAddressScope5)
+            .build()
+        mService.applyMulticastRoutingConfig(mIfName1, mIfName2, configSelectedWith1Address)
+        mLooper.dispatchAll()
+
+        verify(mMulticastSocket).leaveGroup(eq(mSocketAddressScope4), eq(mNetworkInterface1))
+        verify(mMulticastSocket, never())
+                .leaveGroup(eq(mSocketAddressScope5), eq(mNetworkInterface1))
+    }
+
+    @Test
+    fun testMulticastRouting_fromForwardSelectedToForwardNone_leavesGroup() {
+        prepareService()
+        applyMulticastForwardSelected(mIfName1, mIfName2)
+        mLooper.dispatchAll()
+
+        verify(mMulticastSocket).joinGroup(eq(mSocketAddressScope5), eq(mNetworkInterface1))
+
+        applyMulticastForwardNone(mIfName1, mIfName2)
+        mLooper.dispatchAll()
+
+        verify(mMulticastSocket).leaveGroup(eq(mSocketAddressScope5), eq(mNetworkInterface1))
+        assertEquals(MulticastRoutingConfig.CONFIG_FORWARD_NONE,
+                mService.getMulticastRoutingConfig(mIfName1, mIfName2));
+    }
+
+    @Test
+    fun testMulticastRouting_fromFowardSelectedToForwardNone_removesMulticastInterfaces() {
+        prepareService()
+
+        applyMulticastForwardSelected(mIfName1, mIfName2)
+        applyMulticastForwardSelected(mIfName1, mIfName3)
+        mLooper.dispatchAll()
+
+        assertNotNull(mService.getVirtualInterfaceIndex(mIfName1))
+        assertNotNull(mService.getVirtualInterfaceIndex(mIfName2))
+        assertNotNull(mService.getVirtualInterfaceIndex(mIfName3))
+
+        applyMulticastForwardNone(mIfName1, mIfName2)
+        mLooper.dispatchAll()
+
+        assertNotNull(mService.getVirtualInterfaceIndex(mIfName1))
+        assertNull(mService.getVirtualInterfaceIndex(mIfName2))
+        assertNotNull(mService.getVirtualInterfaceIndex(mIfName3))
+    }
+
+    @Test
+    fun testMulticastRouting_addMulticastRoutingInterfaces() {
+        prepareService()
+
+        applyMulticastForwardSelected(mIfName1, mIfName2)
+        mLooper.dispatchAll()
+
+        assertNotNull(mService.getVirtualInterfaceIndex(mIfName1))
+        assertNotNull(mService.getVirtualInterfaceIndex(mIfName2))
+        assertNotEquals(mService.getVirtualInterfaceIndex(mIfName1),
+                mService.getVirtualInterfaceIndex(mIfName2))
+    }
+
+    @Test
+    fun testMulticastRouting_removeMulticastRoutingInterfaces() {
+        prepareService()
+
+        applyMulticastForwardSelected(mIfName1, mIfName2)
+        mService.removeInterfaceFromMulticastRouting(mIfName1)
+        mLooper.dispatchAll()
+
+        assertNull(mService.getVirtualInterfaceIndex(mIfName1))
+        assertNotNull(mService.getVirtualInterfaceIndex(mIfName2))
+    }
+
+    @Test
+    fun testMulticastRouting_applyConfigNone_removesMfc() {
+        prepareService()
+
+        applyMulticastForwardMinimumScope(mIfName1, mIfName2, 4 /* minScope */)
+        applyMulticastForwardSelected(mIfName1, mIfName3)
+
+        sendMrt6msgNocachePacket(0, mSourceAddress, mGroupAddressScope5)
+        val oifs = setOf(mService.getVirtualInterfaceIndex(mIfName2),
+                mService.getVirtualInterfaceIndex(mIfName3))
+        val oifsUpdate = setOf(mService.getVirtualInterfaceIndex(mIfName3))
+        val mf6cctlAdd = createStructMf6cctl(mSourceAddress, mGroupAddressScope5,
+                mService.getVirtualInterfaceIndex(mIfName1), oifs)
+        val mf6cctlUpdate = createStructMf6cctl(mSourceAddress, mGroupAddressScope5,
+                mService.getVirtualInterfaceIndex(mIfName1), oifsUpdate)
+        val mf6cctlDel = createStructMf6cctl(mSourceAddress, mGroupAddressScope5,
+                mService.getVirtualInterfaceIndex(mIfName1), mEmptyOifs)
+
+        verify(mDeps).setsockoptMrt6AddMfc(eq(mFd), eq(mf6cctlAdd))
+
+        applyMulticastForwardNone(mIfName1, mIfName2)
+        mLooper.dispatchAll()
+
+        verify(mDeps).setsockoptMrt6AddMfc(eq(mFd), eq(mf6cctlUpdate))
+
+        applyMulticastForwardNone(mIfName1, mIfName3)
+        mLooper.dispatchAll()
+
+        verify(mDeps, timeout(TIMEOUT_MS).times(1)).setsockoptMrt6DelMfc(eq(mFd), eq(mf6cctlDel))
+    }
+
+    @Test
+    @LargeTest
+    fun testMulticastRouting_maxNumberOfMfcs() {
+        prepareService()
+
+        // add MFC_MAX_NUMBER_OF_ENTRIES MFCs
+        applyMulticastForwardMinimumScope(mIfName1, mIfName2, 4 /* minScope */)
+        for (i in 1..MulticastRoutingCoordinatorService.MFC_MAX_NUMBER_OF_ENTRIES) {
+            val groupAddress =
+                Inet6Address.getByName("ff05::" + Integer.toHexString(i)) as Inet6Address
+            sendMrt6msgNocachePacket(0, mSourceAddress, groupAddress)
+        }
+        val mf6cctlDel = createStructMf6cctl(mSourceAddress,
+                Inet6Address.getByName("ff05::1" ) as Inet6Address,
+                mService.getVirtualInterfaceIndex(mIfName1), mEmptyOifs)
+
+        verify(mDeps, times(MulticastRoutingCoordinatorService.MFC_MAX_NUMBER_OF_ENTRIES)).
+            setsockoptMrt6AddMfc(eq(mFd), any())
+        // when number of mfcs reaches the max value, one mfc should be removed
+        verify(mDeps).setsockoptMrt6DelMfc(eq(mFd), eq(mf6cctlDel))
+    }
+
+    @Test
+    fun testMulticastRouting_interfaceWithoutActiveConfig_isRemoved() {
+        prepareService()
+        applyMulticastForwardMinimumScope(mIfName1, mIfName2, 4 /* minScope */)
+        mLooper.dispatchAll()
+        val virtualIndexIf1 = mService.getVirtualInterfaceIndex(mIfName1)
+        val virtualIndexIf2 = mService.getVirtualInterfaceIndex(mIfName2)
+
+        applyMulticastForwardNone(mIfName1, mIfName2)
+        mLooper.dispatchAll()
+
+        verify(mDeps).setsockoptMrt6DelMif(eq(mFd), eq(virtualIndexIf1))
+        verify(mDeps).setsockoptMrt6DelMif(eq(mFd), eq(virtualIndexIf2))
+    }
+
+    @Test
+    fun testMulticastRouting_interfaceWithActiveConfig_isNotRemoved() {
+        prepareService()
+        applyMulticastForwardMinimumScope(mIfName1, mIfName2, 4 /* minScope */)
+        applyMulticastForwardMinimumScope(mIfName2, mIfName3, 4 /* minScope */)
+        mLooper.dispatchAll()
+        val virtualIndexIf1 = mService.getVirtualInterfaceIndex(mIfName1)
+        val virtualIndexIf2 = mService.getVirtualInterfaceIndex(mIfName2)
+        val virtualIndexIf3 = mService.getVirtualInterfaceIndex(mIfName3)
+
+        applyMulticastForwardNone(mIfName1, mIfName2)
+        mLooper.dispatchAll()
+
+        verify(mDeps).setsockoptMrt6DelMif(eq(mFd), eq(virtualIndexIf1))
+        verify(mDeps, never()).setsockoptMrt6DelMif(eq(mFd), eq(virtualIndexIf2))
+        verify(mDeps, never()).setsockoptMrt6DelMif(eq(mFd), eq(virtualIndexIf3))
+    }
+
+    @Test
+    fun testMulticastRouting_unusedMfc_isRemovedAfterTimeout() {
+        prepareService()
+        applyMulticastForwardMinimumScope(mIfName1, mIfName2, 4 /* minScope */)
+        sendMrt6msgNocachePacket(0, mSourceAddress, mGroupAddressScope5)
+        val oifs = setOf(mService.getVirtualInterfaceIndex(mIfName2))
+        val mf6cctlAdd = createStructMf6cctl(mSourceAddress, mGroupAddressScope5,
+                mService.getVirtualInterfaceIndex(mIfName1), oifs)
+        val mf6cctlDel = createStructMf6cctl(mSourceAddress, mGroupAddressScope5,
+                mService.getVirtualInterfaceIndex(mIfName1), mEmptyOifs)
+
+        // An MFC is added
+        verify(mDeps).setsockoptMrt6AddMfc(eq(mFd), eq(mf6cctlAdd))
+
+        repeat(MulticastRoutingCoordinatorService.MFC_INACTIVE_TIMEOUT_MS /
+                MulticastRoutingCoordinatorService.MFC_INACTIVE_CHECK_INTERVAL_MS + 1) {
+            mClock.fastForward(MulticastRoutingCoordinatorService
+                    .MFC_INACTIVE_CHECK_INTERVAL_MS.toLong())
+            mLooper.moveTimeForward(MulticastRoutingCoordinatorService
+                    .MFC_INACTIVE_CHECK_INTERVAL_MS.toLong())
+            mLooper.dispatchAll();
+        }
+
+        verify(mDeps).setsockoptMrt6DelMfc(eq(mFd), eq(mf6cctlDel))
+    }
+}
