diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java
index 5533413..e46c1d8 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java
@@ -18,7 +18,6 @@
 
 import com.google.common.base.Objects;
 import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
@@ -46,13 +45,10 @@
 import org.onosproject.net.flowobjective.ForwardingObjective;
 import org.onosproject.net.flowobjective.NextObjective;
 import org.onosproject.net.flowobjective.ObjectiveContext;
-import org.onosproject.net.topology.LinkWeigher;
-import org.onosproject.net.topology.Topology;
-import org.onosproject.net.topology.TopologyService;
-import org.onosproject.segmentrouting.SRLinkWeigher;
 import org.onosproject.segmentrouting.SegmentRoutingManager;
 import org.onosproject.store.serializers.KryoNamespaces;
 import org.onosproject.store.service.ConsistentMap;
+import org.onosproject.store.service.ConsistentMultimap;
 import org.onosproject.store.service.DistributedSet;
 import org.onosproject.store.service.Serializer;
 import org.onosproject.store.service.Versioned;
@@ -96,10 +92,10 @@
     // Internal elements
     private static final Logger log = LoggerFactory.getLogger(McastHandler.class);
     private final SegmentRoutingManager srManager;
-    private final TopologyService topologyService;
     private final McastUtils mcastUtils;
     private final ConsistentMap<McastStoreKey, NextObjective> mcastNextObjStore;
     private final ConsistentMap<McastRoleStoreKey, McastRole> mcastRoleStore;
+    private final ConsistentMultimap<McastPathStoreKey, List<Link>> mcastPathStore;
     private final DistributedSet<McastFilteringObjStoreKey> mcastFilteringObjStore;
     // Stability threshold for Mcast. Seconds
     private static final long MCAST_STABLITY_THRESHOLD = 5;
@@ -125,7 +121,6 @@
     public McastHandler(SegmentRoutingManager srManager) {
         ApplicationId coreAppId = srManager.coreService.getAppId(CoreService.CORE_APP_NAME);
         this.srManager = srManager;
-        this.topologyService = srManager.topologyService;
         KryoNamespace.Builder mcastKryo = new KryoNamespace.Builder()
                 .register(KryoNamespaces.API)
                 .register(new McastStoreKeySerializer(), McastStoreKey.class);
@@ -152,6 +147,14 @@
                 .withSerializer(Serializer.using(mcastKryo.build("McastHandler-FilteringObj")))
                 .build()
                 .asDistributedSet();
+        mcastKryo = new KryoNamespace.Builder()
+                .register(KryoNamespaces.API)
+                .register(new McastPathStoreKeySerializer(), McastPathStoreKey.class);
+        mcastPathStore = srManager.storageService
+                .<McastPathStoreKey, List<Link>>consistentMultimapBuilder()
+                .withName("onos-mcast-path-store")
+                .withSerializer(Serializer.using(mcastKryo.build("McastHandler-Path")))
+                .build();
         mcastUtils = new McastUtils(srManager, coreAppId, log);
         // Init the executor for the buckets corrector
         mcastCorrector.scheduleWithFixedDelay(new McastBucketCorrector(), 10,
@@ -193,8 +196,8 @@
     }
 
     private void initInternal() {
-        lastMcastChange.set(Instant.now());
         srManager.multicastRouteService.getRoutes().forEach(mcastRoute -> {
+            lastMcastChange.set(Instant.now());
             log.debug("Init group {}", mcastRoute.group());
             if (!mcastUtils.isLeader(mcastRoute.group())) {
                 log.debug("Skip {} due to lack of leadership", mcastRoute.group());
@@ -203,11 +206,11 @@
             McastRouteData mcastRouteData = srManager.multicastRouteService.routeData(mcastRoute);
             // For each source process the mcast tree
             srManager.multicastRouteService.sources(mcastRoute).forEach(source -> {
-                Map<ConnectPoint, List<ConnectPoint>> mcastPaths = Maps.newHashMap();
-                Set<DeviceId> visited = Sets.newHashSet();
-                List<ConnectPoint> currentPath = Lists.newArrayList(source);
-                mcastUtils.buildMcastPaths(mcastNextObjStore.asJavaMap(), source.deviceId(), visited, mcastPaths,
-                                           currentPath, mcastRoute.group(), source);
+                McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastRoute.group(), source);
+                Collection<? extends List<Link>> storedPaths = Versioned.valueOrElse(
+                        mcastPathStore.get(pathStoreKey), Lists.newArrayList());
+                Map<ConnectPoint, List<ConnectPoint>> mcastPaths = buildMcastPaths(storedPaths, mcastRoute.group(),
+                                                                                   source);
                 // Get all the sinks and process them
                 Set<ConnectPoint> sinks = processSinksToBeAdded(source, mcastRoute.group(),
                                                                 mcastRouteData.sinks());
@@ -221,10 +224,10 @@
                     log.debug("Skip {} for source {} nothing to do", mcastRoute.group(), source);
                     return;
                 }
-                Map<ConnectPoint, List<Path>> mcasTree = computeSinkMcastTree(mcastRoute.group(),
-                                                                              source.deviceId(), sinks);
-                mcasTree.forEach((sink, paths) -> processSinkAddedInternal(source, sink,
-                                                                           mcastRoute.group(), paths));
+                Map<ConnectPoint, List<Path>> mcasTree = mcastUtils.computeSinkMcastTree(mcastRoute.group(),
+                                                                                         source.deviceId(), sinks);
+                mcasTree.forEach((sink, paths) -> processSinkAddedInternal(source, sink, mcastRoute.group(),
+                                                                             null));
             });
         });
     }
@@ -238,6 +241,7 @@
         mcastNextObjStore.destroy();
         mcastRoleStore.destroy();
         mcastFilteringObjStore.destroy();
+        mcastPathStore.destroy();
         mcastUtils.terminate();
         log.info("Terminated");
     }
@@ -310,8 +314,8 @@
         }
         sources.forEach(source -> {
             Set<ConnectPoint> sinksToBeAdded = processSinksToBeAdded(source, mcastIp, sinks);
-            Map<ConnectPoint, List<Path>> mcasTree = computeSinkMcastTree(mcastIp, source.deviceId(),
-                                                                          sinksToBeAdded);
+            Map<ConnectPoint, List<Path>> mcasTree = mcastUtils.computeSinkMcastTree(mcastIp, source.deviceId(),
+                                                                                     sinksToBeAdded);
             mcasTree.forEach((sink, paths) -> processSinkAddedInternal(source, sink, mcastIp, paths));
         });
     }
@@ -339,42 +343,41 @@
             processRouteRemovedInternal(sourcesToBeRemoved, mcastIp);
             return;
         }
-        // Skip offline devices
-        Set<ConnectPoint> candidateSources = sourcesToBeRemoved.stream()
-                .filter(source -> srManager.deviceService.isAvailable(source.deviceId()))
-                .collect(Collectors.toSet());
-        if (candidateSources.isEmpty()) {
-            log.debug("Skip {} due to empty sources to be removed", mcastIp);
-            return;
-        }
         // Let's heal the trees
-        Set<Link> remainingLinks = Sets.newHashSet();
-        Map<ConnectPoint, Set<Link>> candidateLinks = Maps.newHashMap();
+        Set<Link> notAffectedLinks = Sets.newHashSet();
+        Map<ConnectPoint, Set<Link>> affectedLinks = Maps.newHashMap();
         Map<ConnectPoint, Set<ConnectPoint>> candidateSinks = Maps.newHashMap();
-        Set<ConnectPoint> totalSources = Sets.newHashSet(candidateSources);
+        Set<ConnectPoint> totalSources = Sets.newHashSet(sourcesToBeRemoved);
         totalSources.addAll(remainingSources);
-        // Calculate all the links used by the sources
+        // Calculate all the links used by the sources and the current sinks
         totalSources.forEach(source -> {
             Set<ConnectPoint> currentSinks = sinks.values()
                     .stream().flatMap(Collection::stream)
                     .filter(sink -> isSinkForSource(mcastIp, sink, source))
                     .collect(Collectors.toSet());
             candidateSinks.put(source, currentSinks);
+            McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
+            Collection<? extends List<Link>> storedPaths = Versioned.valueOrElse(
+                    mcastPathStore.get(pathStoreKey), Lists.newArrayList());
             currentSinks.forEach(currentSink -> {
-                Optional<Path> currentPath = getPath(source.deviceId(), currentSink.deviceId(),
-                                                     mcastIp, null, source);
+                Optional<? extends List<Link>> currentPath = mcastUtils.getStoredPath(currentSink.deviceId(),
+                                                                                      storedPaths);
                 if (currentPath.isPresent()) {
-                    if (!candidateSources.contains(source)) {
-                        remainingLinks.addAll(currentPath.get().links());
+                    if (!sourcesToBeRemoved.contains(source)) {
+                        notAffectedLinks.addAll(currentPath.get());
                     } else {
-                        candidateLinks.put(source, Sets.newHashSet(currentPath.get().links()));
+                        affectedLinks.compute(source, (k, v) -> {
+                           v = v == null ? Sets.newHashSet() : v;
+                           v.addAll(currentPath.get());
+                           return v;
+                        });
                     }
                 }
             });
         });
         // Clean transit links
-        candidateLinks.forEach((source, currentCandidateLinks) -> {
-            Set<Link> linksToBeRemoved = Sets.difference(currentCandidateLinks, remainingLinks)
+        affectedLinks.forEach((source, currentCandidateLinks) -> {
+            Set<Link> linksToBeRemoved = Sets.difference(currentCandidateLinks, notAffectedLinks)
                     .immutableCopy();
             if (!linksToBeRemoved.isEmpty()) {
                 currentCandidateLinks.forEach(link -> {
@@ -391,8 +394,9 @@
             }
         });
         // Clean ingress and egress
-        candidateSources.forEach(source -> {
+        sourcesToBeRemoved.forEach(source -> {
             Set<ConnectPoint> currentSinks = candidateSinks.get(source);
+            McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
             currentSinks.forEach(currentSink -> {
                 VlanId assignedVlan = mcastUtils.assignedVlan(source.deviceId().equals(currentSink.deviceId()) ?
                                                                       source : null);
@@ -435,6 +439,8 @@
                 mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, currentSink.deviceId(),
                                                             source));
             });
+            // Clean the mcast paths
+            mcastPathStore.removeAll(pathStoreKey);
         });
     }
 
@@ -469,6 +475,7 @@
                     .stream().findFirst().orElse(null);
             Set<DeviceId> transitDevices = getDevice(mcastIp, TRANSIT, source);
             Set<DeviceId> egressDevices = getDevice(mcastIp, EGRESS, source);
+            McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
             // If there are no egress and transit devices, sinks could be only on the ingress
             if (!egressDevices.isEmpty()) {
                 egressDevices.forEach(deviceId -> {
@@ -486,6 +493,8 @@
                 removeGroupFromDevice(ingressDevice, mcastIp, mcastUtils.assignedVlan(source));
                 mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, ingressDevice, source));
             }
+            // Clean the mcast paths
+            mcastPathStore.removeAll(pathStoreKey);
         });
         // Finally, withdraw the leadership
         mcastUtils.withdrawLeader(mcastIp);
@@ -509,21 +518,48 @@
             log.debug("Skip {} due to lack of leadership", mcastIp);
             return;
         }
-        Map<ConnectPoint, Map<ConnectPoint, Optional<Path>>> treesToBeRemoved = Maps.newHashMap();
+        Map<ConnectPoint, Map<ConnectPoint, Optional<? extends List<Link>>>> treesToBeRemoved = Maps.newHashMap();
         Map<ConnectPoint, Set<ConnectPoint>> treesToBeAdded = Maps.newHashMap();
+        Set<Link> goodLinks = Sets.newHashSet();
+        Map<ConnectPoint, Set<DeviceId>> goodDevicesBySource = Maps.newHashMap();
         sources.forEach(source -> {
             // Save the path associated to the sinks to be removed
-            Set<ConnectPoint> candidateSinks = processSinksToBeRemoved(mcastIp, prevSinks,
+            Set<ConnectPoint> sinksToBeRemoved = processSinksToBeRemoved(mcastIp, prevSinks,
                                                                          newSinks, source);
-            // Skip offline devices
-            Set<ConnectPoint> sinksToBeRemoved = candidateSinks.stream()
-                    .filter(sink -> srManager.deviceService.isAvailable(sink.deviceId()))
-                    .collect(Collectors.toSet());
-            Map<ConnectPoint, Optional<Path>> treeToBeRemoved = Maps.newHashMap();
-            sinksToBeRemoved.forEach(sink -> treeToBeRemoved.put(sink, getPath(source.deviceId(),
-                                                                               sink.deviceId(), mcastIp,
-                                                                               null, source)));
+            Map<ConnectPoint, Optional<? extends List<Link>>> treeToBeRemoved = Maps.newHashMap();
+            McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
+            Collection<? extends List<Link>> storedPaths = Versioned.valueOrElse(
+                    mcastPathStore.get(pathStoreKey), Lists.newArrayList());
+            sinksToBeRemoved.forEach(sink -> treeToBeRemoved.put(sink, mcastUtils.getStoredPath(sink.deviceId(),
+                                                                                                storedPaths)));
             treesToBeRemoved.put(source, treeToBeRemoved);
+            // Save the good links and good devices
+            Set<DeviceId> goodDevices = Sets.newHashSet();
+            Set<DeviceId> totalDevices = Sets.newHashSet(getDevice(mcastIp, EGRESS, source));
+            totalDevices.addAll(getDevice(mcastIp, INGRESS, source));
+            Set<ConnectPoint> notAffectedSinks = Sets.newHashSet();
+            // Compute good sinks
+            totalDevices.forEach(device -> {
+                Set<ConnectPoint> sinks = getSinks(mcastIp, device, source);
+                notAffectedSinks.addAll(Sets.difference(sinks, sinksToBeRemoved));
+            });
+            // Compute good paths and good devices
+            notAffectedSinks.forEach(notAffectedSink -> {
+                Optional<? extends List<Link>> notAffectedPath = mcastUtils.getStoredPath(notAffectedSink.deviceId(),
+                                                                                          storedPaths);
+                if (notAffectedPath.isPresent()) {
+                    List<Link> goodPath = notAffectedPath.get();
+                    goodLinks.addAll(goodPath);
+                    goodPath.forEach(link -> goodDevices.add(link.src().deviceId()));
+                } else {
+                    goodDevices.add(notAffectedSink.deviceId());
+                }
+            });
+            goodDevicesBySource.compute(source, (k, v) -> {
+                v = v == null ? Sets.newHashSet() : v;
+                v.addAll(goodDevices);
+                return v;
+            });
             // Recover the dual-homed sinks
             Set<ConnectPoint> sinksToBeRecovered = processSinksToBeRecovered(mcastIp, newSinks,
                                                                              prevSinks, source);
@@ -531,7 +567,8 @@
         });
         // Remove the sinks taking into account the multiple sources and the original paths
         treesToBeRemoved.forEach((source, tree) ->
-            tree.forEach((sink, path) -> processSinkRemovedInternal(source, sink, mcastIp, path)));
+            tree.forEach((sink, path) -> processSinkRemovedInternal(source, sink, mcastIp, path,
+                                                                    goodLinks, goodDevicesBySource.get(source))));
         // Add new sinks according to the recovery procedure
         treesToBeAdded.forEach((source, sinks) ->
             sinks.forEach(sink -> processSinkAddedInternal(source, sink, mcastIp, null)));
@@ -544,9 +581,16 @@
      * @param sink connection point of the multicast sink
      * @param mcastIp multicast group IP address
      * @param mcastPath path associated to the sink
+     * @param usedLinks links used by the other sinks
+     * @param usedDevices devices used by other sinks
      */
     private void processSinkRemovedInternal(ConnectPoint source, ConnectPoint sink,
-                                            IpAddress mcastIp, Optional<Path> mcastPath) {
+                                            IpAddress mcastIp, Optional<? extends List<Link>> mcastPath,
+                                            Set<Link> usedLinks, Set<DeviceId> usedDevices) {
+
+        log.info("Used links {}", usedLinks);
+        log.info("Used devices {}", usedDevices);
+
         lastMcastChange.set(Instant.now());
         log.info("Processing sink removed {} for group {} and for source {}", sink, mcastIp, source);
         boolean isLast;
@@ -570,19 +614,24 @@
         }
         // If this is the last sink on the device, also update upstream
         if (mcastPath.isPresent()) {
-            List<Link> links = Lists.newArrayList(mcastPath.get().links());
-            Collections.reverse(links);
-            for (Link link : links) {
-                if (isLast) {
-                    isLast = removePortFromDevice(link.src().deviceId(), link.src().port(), mcastIp,
-                    mcastUtils.assignedVlan(link.src().deviceId().equals(source.deviceId()) ? source : null));
-                    if (isLast) {
+            List<Link> links = Lists.newArrayList(mcastPath.get());
+            if (isLast) {
+                // Clean the path
+                McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
+                mcastPathStore.remove(pathStoreKey, mcastPath.get());
+                Collections.reverse(links);
+                for (Link link : links) {
+                    // If nobody is using the port remove
+                    if (!usedLinks.contains(link)) {
+                        removePortFromDevice(link.src().deviceId(), link.src().port(), mcastIp,
+                          mcastUtils.assignedVlan(link.src().deviceId().equals(source.deviceId()) ? source : null));
+                    }
+                    // If nobody is using the device
+                    if (!usedDevices.contains(link.src().deviceId())) {
                         mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, link.src().deviceId(), source));
                     }
                 }
             }
-        } else {
-            log.warn("Unable to find a path from {} to {}. Abort sinkRemoved", source.deviceId(), sink.deviceId());
         }
     }
 
@@ -636,9 +685,10 @@
             return;
         }
         // Find a path. If present, create/update groups and flows for each hop
-        Optional<Path> mcastPath = getPath(source.deviceId(), sink.deviceId(), mcastIp, allPaths, source);
+        Optional<Path> mcastPath = getPath(source.deviceId(), sink.deviceId(), mcastIp, allPaths);
         if (mcastPath.isPresent()) {
             List<Link> links = mcastPath.get().links();
+            McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
             // Setup mcast role for ingress
             mcastRoleStore.put(new McastRoleStoreKey(mcastIp, source.deviceId(), source), INGRESS);
             // Setup properly the transit forwarding
@@ -653,15 +703,14 @@
             // Setup mcast role for the transit
             links.stream()
                     .filter(link -> !link.dst().deviceId().equals(sink.deviceId()))
-                    .forEach(link -> {
-                        log.trace("Transit links {}", link);
-                        mcastRoleStore.put(new McastRoleStoreKey(mcastIp, link.dst().deviceId(),
-                                source), TRANSIT);
-                    });
+                    .forEach(link -> mcastRoleStore.put(new McastRoleStoreKey(mcastIp, link.dst().deviceId(),
+                                                                              source), TRANSIT));
             // Process the egress device
             addPortToDevice(sink.deviceId(), sink.port(), mcastIp, mcastUtils.assignedVlan(null));
             // Setup mcast role for egress
             mcastRoleStore.put(new McastRoleStoreKey(mcastIp, sink.deviceId(), source), EGRESS);
+            // Store the used path
+            mcastPathStore.put(pathStoreKey, links);
         } else {
             log.warn("Unable to find a path from {} to {}. Abort sinkAdded", source.deviceId(), sink.deviceId());
         }
@@ -697,11 +746,11 @@
     }
 
     private void processLinkDownInternal(Link linkDown) {
-        lastMcastChange.set(Instant.now());
         // Get mcast groups affected by the link going down
         Set<IpAddress> affectedGroups = getAffectedGroups(linkDown);
         log.info("Processing link down {} for groups {}", linkDown, affectedGroups);
         affectedGroups.forEach(mcastIp -> {
+            lastMcastChange.set(Instant.now());
             log.debug("Processing link down {} for group {}", linkDown, mcastIp);
             recoverFailure(mcastIp, linkDown);
         });
@@ -717,12 +766,12 @@
     }
 
     private void processDeviceDownInternal(DeviceId deviceDown) {
-        lastMcastChange.set(Instant.now());
         // Get the mcast groups affected by the device going down
         Set<IpAddress> affectedGroups = getAffectedGroups(deviceDown);
         log.info("Processing device down {} for groups {}", deviceDown, affectedGroups);
         updateFilterObjStoreByDevice(deviceDown);
         affectedGroups.forEach(mcastIp -> {
+            lastMcastChange.set(Instant.now());
             log.debug("Processing device down {} for group {}", deviceDown, mcastIp);
             recoverFailure(mcastIp, deviceDown);
         });
@@ -735,151 +784,249 @@
      * @param failedElement the failed element
      */
     private void recoverFailure(IpAddress mcastIp, Object failedElement) {
-        // TODO Optimize when the group editing is in place
+        // Do not proceed if we are not the leaders
         if (!mcastUtils.isLeader(mcastIp)) {
             log.debug("Skip {} due to lack of leadership", mcastIp);
             return;
         }
+        // Skip if it is not an infra failure
+        Set<DeviceId> transitDevices = getDevice(mcastIp, TRANSIT);
+        if (!mcastUtils.isInfraFailure(transitDevices, failedElement)) {
+            log.debug("Skip {} not an infrastructure failure", mcastIp);
+            return;
+        }
         // Do not proceed if the sources of this group are missing
         Set<ConnectPoint> sources = getSources(mcastIp);
         if (sources.isEmpty()) {
             log.warn("Missing sources for group {}", mcastIp);
             return;
         }
-        // Find out the ingress devices of the affected group
-        // If sinks are in other leafs, we have ingress, transit, egress, and source
-        // If sinks are in the same leaf, we have just ingress and source
-        Set<DeviceId> ingressDevices = getDevice(mcastIp, INGRESS);
-        if (ingressDevices.isEmpty()) {
-            log.warn("Missing ingress devices for group {}", mcastIp);
-            return;
-        }
-        // For each tree, delete ingress-transit part
-        sources.forEach(source -> {
-            Set<DeviceId> transitDevices = getDevice(mcastIp, TRANSIT, source);
-            transitDevices.forEach(transitDevice -> {
-                removeGroupFromDevice(transitDevice, mcastIp, mcastUtils.assignedVlan(null));
-                mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, transitDevice, source));
+        // Get all the paths, affected paths, good links and good devices
+        Set<List<Link>> storedPaths = getStoredPaths(mcastIp);
+        Set<List<Link>> affectedPaths = mcastUtils.getAffectedPaths(storedPaths, failedElement);
+        Set<Link> goodLinks = Sets.newHashSet();
+        Map<DeviceId, Set<DeviceId>> goodDevicesBySource = Maps.newHashMap();
+        Map<DeviceId, Set<ConnectPoint>> processedSourcesByEgress = Maps.newHashMap();
+        Sets.difference(storedPaths, affectedPaths).forEach(goodPath -> {
+            goodLinks.addAll(goodPath);
+            DeviceId srcDevice = goodPath.get(0).src().deviceId();
+            Set<DeviceId> goodDevices = Sets.newHashSet();
+            goodPath.forEach(link -> goodDevices.add(link.src().deviceId()));
+            goodDevicesBySource.compute(srcDevice, (k, v) -> {
+                v = v == null ? Sets.newHashSet() : v;
+                v.addAll(goodDevices);
+                return v;
             });
         });
-        removeIngressTransitPorts(mcastIp, ingressDevices, sources);
-        // TODO Evaluate the possibility of building optimize trees between sources
-        Map<DeviceId, Set<ConnectPoint>> notRecovered = Maps.newHashMap();
-        sources.forEach(source -> {
-            Set<DeviceId> notRecoveredInternal = Sets.newHashSet();
-            DeviceId ingressDevice = ingressDevices.stream()
-                    .filter(deviceId -> deviceId.equals(source.deviceId())).findFirst().orElse(null);
-            // Clean also the ingress
-            if (failedElement instanceof DeviceId && ingressDevice.equals(failedElement)) {
-                removeGroupFromDevice((DeviceId) failedElement, mcastIp, mcastUtils.assignedVlan(source));
-                mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, (DeviceId) failedElement, source));
+        affectedPaths.forEach(affectedPath -> {
+            // TODO remove
+            log.info("Good links {}", goodLinks);
+            // TODO remove
+            log.info("Good devices {}", goodDevicesBySource);
+            // TODO trace
+            log.info("Healing the path {}", affectedPath);
+            DeviceId srcDevice = affectedPath.get(0).src().deviceId();
+            DeviceId dstDevice = affectedPath.get(affectedPath.size() - 1).dst().deviceId();
+            // Fix in one shot multiple sources
+            Set<ConnectPoint> affectedSources = sources.stream()
+                    .filter(device -> device.deviceId().equals(srcDevice))
+                    .collect(Collectors.toSet());
+            Set<ConnectPoint> processedSources = processedSourcesByEgress.getOrDefault(dstDevice,
+                                                                                       Collections.emptySet());
+            Optional<Path> alternativePath = getPath(srcDevice, dstDevice, mcastIp, null);
+            // If an alternative is possible go ahead
+            if (alternativePath.isPresent()) {
+                // TODO trace
+                log.info("Alternative path {}", alternativePath.get().links());
+            } else {
+                // Otherwise try to come up with an alternative
+                // TODO trace
+                log.info("No alternative path");
+                Set<ConnectPoint> notAffectedSources = Sets.difference(sources, affectedSources);
+                Set<ConnectPoint> remainingSources = Sets.difference(notAffectedSources, processedSources);
+                alternativePath = recoverSinks(dstDevice, mcastIp, affectedSources, remainingSources);
+                processedSourcesByEgress.compute(dstDevice, (k, v) -> {
+                    v = v == null ? Sets.newHashSet() : v;
+                    v.addAll(affectedSources);
+                    return v;
+                });
             }
-            if (ingressDevice == null) {
-                log.warn("Skip failure recovery - " +
-                                 "Missing ingress for source {} and group {}", source, mcastIp);
-                return;
-            }
-            Set<DeviceId> egressDevices = getDevice(mcastIp, EGRESS, source);
-            Map<DeviceId, List<Path>> mcastTree = computeMcastTree(mcastIp, ingressDevice, egressDevices);
-            // We have to verify, if there are egresses without paths
-            mcastTree.forEach((egressDevice, paths) -> {
-                Optional<Path> mcastPath = getPath(ingressDevice, egressDevice,
-                                                   mcastIp, paths, source);
-                // No paths, we have to try with alternative location
-                if (!mcastPath.isPresent()) {
-                    notRecovered.compute(egressDevice, (deviceId, listSources) -> {
-                        listSources = listSources == null ? Sets.newHashSet() : listSources;
-                        listSources.add(source);
-                        return listSources;
-                    });
-                    notRecoveredInternal.add(egressDevice);
-                }
-            });
-            // Fast path, we can recover all the locations
-            if (notRecoveredInternal.isEmpty()) {
-                mcastTree.forEach((egressDevice, paths) -> {
-                    Optional<Path> mcastPath = getPath(ingressDevice, egressDevice,
-                                                       mcastIp, paths, source);
-                    if (mcastPath.isPresent()) {
-                        installPath(mcastIp, source, mcastPath.get());
+            // Recover from the failure if possible
+            Optional<Path> finalPath = alternativePath;
+            affectedSources.forEach(affectedSource -> {
+                // Update the mcastPath store
+                McastPathStoreKey mcastPathStoreKey = new McastPathStoreKey(mcastIp, affectedSource);
+                // Verify if there are local sinks
+                Set<DeviceId> localSinks = getSinks(mcastIp, srcDevice, affectedSource).stream()
+                        .map(ConnectPoint::deviceId)
+                        .collect(Collectors.toSet());
+                Set<DeviceId> goodDevices = goodDevicesBySource.compute(affectedSource.deviceId(), (k, v) -> {
+                    v = v == null ? Sets.newHashSet() : v;
+                    v.addAll(localSinks);
+                    return v;
+                });
+                // TODO remove
+                log.info("Good devices {}", goodDevicesBySource);
+                Collection<? extends List<Link>> storedPathsBySource = Versioned.valueOrElse(
+                        mcastPathStore.get(mcastPathStoreKey), Lists.newArrayList());
+                Optional<? extends List<Link>> storedPath = storedPathsBySource.stream()
+                        .filter(path -> path.equals(affectedPath))
+                        .findFirst();
+                // Remove bad links
+                affectedPath.forEach(affectedLink -> {
+                    DeviceId affectedDevice = affectedLink.src().deviceId();
+                    // If there is overlap with good paths - skip it
+                    if (!goodLinks.contains(affectedLink)) {
+                        removePortFromDevice(affectedDevice, affectedLink.src().port(), mcastIp,
+                            mcastUtils.assignedVlan(affectedDevice.equals(affectedSource.deviceId()) ?
+                                                            affectedSource : null));
+                    }
+                    // Remove role on the affected links if last
+                    if (!goodDevices.contains(affectedDevice)) {
+                        mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, affectedDevice, affectedSource));
                     }
                 });
-            } else {
-                // Let's try to recover using alternative locations
-                recoverSinks(egressDevices, notRecoveredInternal, mcastIp,
-                             ingressDevice, source);
-            }
-        });
-        // Finally remove the egresses not recovered
-        notRecovered.forEach((egressDevice, listSources) -> {
-            Set<ConnectPoint> currentSources = getSources(mcastIp, egressDevice, EGRESS);
-            if (Objects.equal(currentSources, listSources)) {
-                log.warn("Fail to recover egress device {} from {} failure {}",
-                         egressDevice, failedElement instanceof Link ? "Link" : "Device", failedElement);
-                removeGroupFromDevice(egressDevice, mcastIp, mcastUtils.assignedVlan(null));
-            }
-            listSources.forEach(source -> mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, egressDevice, source)));
+                // Sometimes the removal fails for serialization issue
+                // trying with the original object as workaround
+                if (storedPath.isPresent()) {
+                    mcastPathStore.remove(mcastPathStoreKey, storedPath.get());
+                } else {
+                    log.warn("Unable to find the corresponding path - trying removeal");
+                    mcastPathStore.remove(mcastPathStoreKey, affectedPath);
+                }
+                // Program new links
+                if (finalPath.isPresent()) {
+                    List<Link> links = finalPath.get().links();
+                    installPath(mcastIp, affectedSource, links);
+                    mcastPathStore.put(mcastPathStoreKey, links);
+                    links.forEach(link -> goodDevices.add(link.src().deviceId()));
+                    goodDevicesBySource.compute(srcDevice, (k, v) -> {
+                        v = v == null ? Sets.newHashSet() : v;
+                        v.addAll(goodDevices);
+                        return v;
+                    });
+                    goodLinks.addAll(finalPath.get().links());
+                }
+            });
         });
     }
 
     /**
-     * Try to recover sinks using alternate locations.
+     * Try to recover sinks using alternative locations.
      *
-     * @param egressDevices the original egress devices
-     * @param notRecovered the devices not recovered
+     * @param notRecovered the device not recovered
      * @param mcastIp the group address
-     * @param ingressDevice the ingress device
-     * @param source the source connect point
+     * @param affectedSources affected sources
+     * @param goodSources sources not affected
      */
-    private void recoverSinks(Set<DeviceId> egressDevices, Set<DeviceId> notRecovered,
-                              IpAddress mcastIp, DeviceId ingressDevice, ConnectPoint source) {
-        log.debug("Processing recover sinks for group {} and for source {}",
-                  mcastIp, source);
-        Set<DeviceId> recovered = Sets.difference(egressDevices, notRecovered);
-        Set<ConnectPoint> totalAffectedSinks = Sets.newHashSet();
-        Set<ConnectPoint> totalSinks = Sets.newHashSet();
-        // Let's compute all the affected sinks and all the sinks
-        notRecovered.forEach(deviceId -> {
-            totalAffectedSinks.addAll(
-                    mcastUtils.getAffectedSinks(deviceId, mcastIp).values().stream()
-                            .flatMap(Collection::stream)
-                            .filter(connectPoint -> connectPoint.deviceId().equals(deviceId))
-                            .collect(Collectors.toSet())
-            );
-            totalSinks.addAll(
-                    mcastUtils.getAffectedSinks(deviceId, mcastIp).values().stream()
-                            .flatMap(Collection::stream).collect(Collectors.toSet())
-            );
+    private Optional<Path> recoverSinks(DeviceId notRecovered, IpAddress mcastIp,
+                                    Set<ConnectPoint> affectedSources,
+                                    Set<ConnectPoint> goodSources) {
+        log.debug("Processing recover sinks on {} for group {}", notRecovered, mcastIp);
+        Map<ConnectPoint, Set<ConnectPoint>> affectedSinksBySource = Maps.newHashMap();
+        Map<ConnectPoint, Set<ConnectPoint>> sinksBySource = Maps.newHashMap();
+        Set<ConnectPoint> sources = Sets.union(affectedSources, goodSources);
+        // Hosts influenced by the failure
+        Map<HostId, Set<ConnectPoint>> hostIdSetMap = mcastUtils.getAffectedSinks(notRecovered, mcastIp);
+        // Locations influenced by the failure
+        Set<ConnectPoint> affectedSinks = hostIdSetMap.values()
+                .stream()
+                .flatMap(Collection::stream)
+                .filter(connectPoint -> connectPoint.deviceId().equals(notRecovered))
+                .collect(Collectors.toSet());
+        // All locations
+        Set<ConnectPoint> sinks = hostIdSetMap.values()
+                .stream()
+                .flatMap(Collection::stream)
+                .collect(Collectors.toSet());
+        // Maps sinks with the sources
+        sources.forEach(source -> {
+            Set<ConnectPoint> currentSinks = affectedSinks.stream()
+                    .filter(sink -> isSinkForSource(mcastIp, sink, source))
+                    .collect(Collectors.toSet());
+            affectedSinksBySource.put(source, currentSinks);
         });
-        Set<ConnectPoint> sinksToBeAdded = Sets.difference(totalSinks, totalAffectedSinks);
-        Set<DeviceId> newEgressDevices = sinksToBeAdded.stream()
-                .map(ConnectPoint::deviceId).collect(Collectors.toSet());
-        newEgressDevices.addAll(recovered);
-        Set<DeviceId> copyNewEgressDevices = ImmutableSet.copyOf(newEgressDevices);
-        newEgressDevices = newEgressDevices.stream()
-                .filter(deviceId -> !deviceId.equals(ingressDevice)).collect(Collectors.toSet());
-        Map<DeviceId, List<Path>> mcastTree = computeMcastTree(mcastIp, ingressDevice, newEgressDevices);
-        // if the source was originally in the new locations, add new sinks
-        if (copyNewEgressDevices.contains(ingressDevice)) {
-            sinksToBeAdded.stream()
-                    .filter(connectPoint -> connectPoint.deviceId().equals(ingressDevice))
-                    .forEach(sink -> processSinkAddedInternal(source, sink, mcastIp, ImmutableList.of()));
-        }
-        // Construct a new path for each egress device
-        mcastTree.forEach((egressDevice, paths) -> {
-            Optional<Path> mcastPath = getPath(ingressDevice, egressDevice, mcastIp, paths, source);
-            if (mcastPath.isPresent()) {
-                // Using recovery procedure
-                if (recovered.contains(egressDevice)) {
-                    installPath(mcastIp, source, mcastPath.get());
-                } else {
-                    // otherwise we need to threat as new sink
-                    sinksToBeAdded.stream()
-                            .filter(connectPoint -> connectPoint.deviceId().equals(egressDevice))
-                            .forEach(sink -> processSinkAddedInternal(source, sink, mcastIp, paths));
+        // Remove sinks one by one if they are not used by other sources
+        affectedSources.forEach(affectedSource -> {
+            Set<ConnectPoint> currentSinks = affectedSinksBySource.get(affectedSource);
+            log.info("Current sinks {} for source {}", currentSinks, affectedSource);
+            currentSinks.forEach(currentSink -> {
+                VlanId assignedVlan = mcastUtils.assignedVlan(
+                        affectedSource.deviceId().equals(currentSink.deviceId()) ? affectedSource : null);
+                log.info("Assigned vlan {}", assignedVlan);
+                Set<VlanId> otherVlans = goodSources.stream()
+                        .filter(remainingSource -> affectedSinksBySource.get(remainingSource).contains(currentSink))
+                        .map(remainingSource -> mcastUtils.assignedVlan(
+                                remainingSource.deviceId().equals(currentSink.deviceId()) ? remainingSource : null))
+                        .collect(Collectors.toSet());
+                log.info("Other vlans {}", otherVlans);
+                // Sinks on other leaves
+                if (!otherVlans.contains(assignedVlan)) {
+                    removePortFromDevice(currentSink.deviceId(), currentSink.port(), mcastIp, assignedVlan);
                 }
-            }
+                mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, currentSink.deviceId(), affectedSource));
+            });
         });
+        // Get the sinks to be added and the new egress
+        Set<DeviceId> newEgress = Sets.newHashSet();
+        affectedSources.forEach(affectedSource -> {
+            Set<ConnectPoint> currentSinks = affectedSinksBySource.get(affectedSource);
+            Set<ConnectPoint> newSinks = Sets.difference(sinks, currentSinks);
+            sinksBySource.put(affectedSource, newSinks);
+            newSinks.stream()
+                    .map(ConnectPoint::deviceId)
+                    .forEach(newEgress::add);
+        });
+        log.info("newEgress {}", newEgress);
+        // If there are more than one new egresses, return the problem
+        if (newEgress.size() != 1) {
+            log.warn("There are {} new egress, wrong configuration. Abort.", newEgress.size());
+            return Optional.empty();
+        }
+        DeviceId egress = newEgress.stream()
+                .findFirst()
+                .orElse(null);
+        DeviceId ingress = affectedSources.stream()
+                .map(ConnectPoint::deviceId)
+                .findFirst()
+                .orElse(null);
+        log.info("Ingress {}", ingress);
+        if (ingress == null) {
+            log.warn("No new ingress, wrong configuration. Abort.");
+            return Optional.empty();
+        }
+        // Get an alternative path
+        Optional<Path> alternativePath = getPath(ingress, egress, mcastIp, null);
+        // If there are new path install sinks and return path
+        if (alternativePath.isPresent()) {
+            log.info("Alternative path {}", alternativePath.get().links());
+            affectedSources.forEach(affectedSource -> {
+                Set<ConnectPoint> newSinks = sinksBySource.get(affectedSource);
+                newSinks.forEach(newSink -> {
+                    addPortToDevice(newSink.deviceId(), newSink.port(), mcastIp, mcastUtils.assignedVlan(null));
+                    mcastRoleStore.put(new McastRoleStoreKey(mcastIp, newSink.deviceId(), affectedSource), EGRESS);
+                });
+            });
+            return alternativePath;
+        }
+        // No new path but sinks co-located with sources install sinks and return empty
+        if (ingress.equals(egress)) {
+            log.info("No Alternative path but sinks co-located");
+            affectedSources.forEach(affectedSource -> {
+                Set<ConnectPoint> newSinks = sinksBySource.get(affectedSource);
+                newSinks.forEach(newSink -> {
+                    if (affectedSource.port().equals(newSink.port())) {
+                        log.warn("Skip {} since sink {} is on the same port of source {}. Abort",
+                                 mcastIp, newSink, affectedSource);
+                        return;
+                    }
+                    addPortToDevice(newSink.deviceId(), newSink.port(), mcastIp,
+                                    mcastUtils.assignedVlan(affectedSource));
+                    mcastRoleStore.put(new McastRoleStoreKey(mcastIp, newSink.deviceId(), affectedSource), INGRESS);
+                });
+            });
+        }
+        return Optional.empty();
     }
 
     /**
@@ -1057,45 +1204,6 @@
     }
 
     /**
-     * Utility method to remove all the ingress transit ports.
-     *
-     * @param mcastIp the group ip
-     * @param ingressDevices the ingress devices
-     * @param sources the source connect points
-     */
-    private void removeIngressTransitPorts(IpAddress mcastIp, Set<DeviceId> ingressDevices,
-                                           Set<ConnectPoint> sources) {
-        Map<ConnectPoint, Set<PortNumber>> ingressTransitPorts = Maps.newHashMap();
-        sources.forEach(source -> {
-            DeviceId ingressDevice = ingressDevices.stream()
-                    .filter(deviceId -> deviceId.equals(source.deviceId()))
-                    .findFirst().orElse(null);
-            if (ingressDevice == null) {
-                log.warn("Skip removeIngressTransitPorts - " +
-                                 "Missing ingress for source {} and group {}",
-                         source, mcastIp);
-                return;
-            }
-            Set<PortNumber> ingressTransitPort = ingressTransitPort(mcastIp, ingressDevice, source);
-            if (ingressTransitPort.isEmpty()) {
-                log.warn("No transit ports to remove on device {}", ingressDevice);
-                return;
-            }
-            ingressTransitPorts.put(source, ingressTransitPort);
-        });
-        ingressTransitPorts.forEach((source, ports) -> ports.forEach(ingressTransitPort -> {
-            DeviceId ingressDevice = ingressDevices.stream()
-                    .filter(deviceId -> deviceId.equals(source.deviceId()))
-                    .findFirst().orElse(null);
-            boolean isLast = removePortFromDevice(ingressDevice, ingressTransitPort,
-                                                  mcastIp, mcastUtils.assignedVlan(source));
-            if (isLast) {
-                mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, ingressDevice, source));
-            }
-        }));
-    }
-
-    /**
      * Adds a port to given multicast group on given device. This involves the
      * update of L3 multicast group and multicast routing table entry.
      *
@@ -1106,6 +1214,8 @@
      */
     private void addPortToDevice(DeviceId deviceId, PortNumber port,
                                  IpAddress mcastIp, VlanId assignedVlan) {
+        // TODO trace
+        log.info("Adding {} on {}/{} and vlan {}", mcastIp, deviceId, port, assignedVlan);
         McastStoreKey mcastStoreKey = new McastStoreKey(mcastIp, deviceId, assignedVlan);
         ImmutableSet.Builder<PortNumber> portBuilder = ImmutableSet.builder();
         NextObjective newNextObj;
@@ -1184,6 +1294,8 @@
      */
     private boolean removePortFromDevice(DeviceId deviceId, PortNumber port,
                                          IpAddress mcastIp, VlanId assignedVlan) {
+        // TODO trace
+        log.info("Removing {} on {}/{} and vlan {}", mcastIp, deviceId, port, assignedVlan);
         McastStoreKey mcastStoreKey =
                 new McastStoreKey(mcastIp, deviceId, assignedVlan);
         // This device is not serving this multicast group
@@ -1247,6 +1359,8 @@
      */
     private void removeGroupFromDevice(DeviceId deviceId, IpAddress mcastIp,
                                        VlanId assignedVlan) {
+        // TODO trace
+        log.info("Removing {} on {} and vlan {}", mcastIp, deviceId, assignedVlan);
         McastStoreKey mcastStoreKey = new McastStoreKey(mcastIp, deviceId, assignedVlan);
         // This device is not serving this multicast group
         if (!mcastNextObjStore.containsKey(mcastStoreKey)) {
@@ -1268,8 +1382,7 @@
         mcastNextObjStore.remove(mcastStoreKey);
     }
 
-    private void installPath(IpAddress mcastIp, ConnectPoint source, Path mcastPath) {
-        List<Link> links = mcastPath.links();
+    private void installPath(IpAddress mcastIp, ConnectPoint source, List<Link> links) {
         if (links.isEmpty()) {
             log.warn("There is no link that can be used. Stopping installation.");
             return;
@@ -1281,7 +1394,7 @@
         // and a new filter objective on the destination port
         links.forEach(link -> {
             addPortToDevice(link.src().deviceId(), link.src().port(), mcastIp,
-                            mcastUtils.assignedVlan(link.src().deviceId().equals(source.deviceId()) ? source : null));
+                mcastUtils.assignedVlan(link.src().deviceId().equals(source.deviceId()) ? source : null));
             McastFilteringObjStoreKey mcastFilterObjStoreKey = new McastFilteringObjStoreKey(link.dst(),
                     mcastUtils.assignedVlan(null), mcastIp.isIp4());
             addFilterToDevice(mcastFilterObjStoreKey, mcastIp, null);
@@ -1294,145 +1407,6 @@
     }
 
     /**
-     * Go through all the paths, looking for shared links to be used
-     * in the final path computation.
-     *
-     * @param egresses egress devices
-     * @param availablePaths all the available paths towards the egress
-     * @return shared links between egress devices
-     */
-    private Set<Link> exploreMcastTree(Set<DeviceId> egresses,
-                                       Map<DeviceId, List<Path>> availablePaths) {
-        int minLength = Integer.MAX_VALUE;
-        int length;
-        List<Path> currentPaths;
-        // Verify the source can still reach all the egresses
-        for (DeviceId egress : egresses) {
-            // From the source we cannot reach all the sinks
-            // just continue and let's figure out after
-            currentPaths = availablePaths.get(egress);
-            if (currentPaths.isEmpty()) {
-                continue;
-            }
-            // Get the length of the first one available, update the min length
-            length = currentPaths.get(0).links().size();
-            if (length < minLength) {
-                minLength = length;
-            }
-        }
-        // If there are no paths
-        if (minLength == Integer.MAX_VALUE) {
-            return Collections.emptySet();
-        }
-        int index = 0;
-        Set<Link> sharedLinks = Sets.newHashSet();
-        Set<Link> currentSharedLinks;
-        Set<Link> currentLinks;
-        DeviceId egressToRemove = null;
-        // Let's find out the shared links
-        while (index < minLength) {
-            // Initialize the intersection with the paths related to the first egress
-            currentPaths = availablePaths.get(egresses.stream().findFirst().orElse(null));
-            currentSharedLinks = Sets.newHashSet();
-            // Iterate over the paths and take the "index" links
-            for (Path path : currentPaths) {
-                currentSharedLinks.add(path.links().get(index));
-            }
-            // Iterate over the remaining egress
-            for (DeviceId egress : egresses) {
-                // Iterate over the paths and take the "index" links
-                currentLinks = Sets.newHashSet();
-                for (Path path : availablePaths.get(egress)) {
-                    currentLinks.add(path.links().get(index));
-                }
-                // Do intersection
-                currentSharedLinks = Sets.intersection(currentSharedLinks, currentLinks);
-                // If there are no shared paths exit and record the device to remove
-                // we have to retry with a subset of sinks
-                if (currentSharedLinks.isEmpty()) {
-                    egressToRemove = egress;
-                    index = minLength;
-                    break;
-                }
-            }
-            sharedLinks.addAll(currentSharedLinks);
-            index++;
-        }
-        // If the shared links is empty and there are egress let's retry another time with less sinks,
-        // we can still build optimal subtrees
-        if (sharedLinks.isEmpty() && egresses.size() > 1 && egressToRemove != null) {
-            egresses.remove(egressToRemove);
-            sharedLinks = exploreMcastTree(egresses, availablePaths);
-        }
-        return sharedLinks;
-    }
-
-    /**
-     * Build Mcast tree having as root the given source and as leaves the given egress points.
-     *
-     * @param mcastIp multicast group
-     * @param source source of the tree
-     * @param sinks leaves of the tree
-     * @return the computed Mcast tree
-     */
-    private Map<ConnectPoint, List<Path>> computeSinkMcastTree(IpAddress mcastIp,
-                                                               DeviceId source,
-                                                               Set<ConnectPoint> sinks) {
-        // Get the egress devices, remove source from the egress if present
-        Set<DeviceId> egresses = sinks.stream().map(ConnectPoint::deviceId)
-                .filter(deviceId -> !deviceId.equals(source)).collect(Collectors.toSet());
-        Map<DeviceId, List<Path>> mcastTree = computeMcastTree(mcastIp, source, egresses);
-        final Map<ConnectPoint, List<Path>> finalTree = Maps.newHashMap();
-        // We need to put back the source if it was originally present
-        sinks.forEach(sink -> {
-            List<Path> sinkPaths = mcastTree.get(sink.deviceId());
-            finalTree.put(sink, sinkPaths != null ? sinkPaths : ImmutableList.of());
-        });
-        return finalTree;
-    }
-
-    /**
-     * Build Mcast tree having as root the given source and as leaves the given egress.
-     *
-     * @param mcastIp multicast group
-     * @param source source of the tree
-     * @param egresses leaves of the tree
-     * @return the computed Mcast tree
-     */
-    private Map<DeviceId, List<Path>> computeMcastTree(IpAddress mcastIp,
-                                                       DeviceId source,
-                                                       Set<DeviceId> egresses) {
-        log.debug("Computing tree for Multicast group {}, source {} and leafs {}",
-                  mcastIp, source, egresses);
-        // Pre-compute all the paths
-        Map<DeviceId, List<Path>> availablePaths = Maps.newHashMap();
-        egresses.forEach(egress -> availablePaths.put(egress, getPaths(source, egress,
-                                                                       Collections.emptySet())));
-        // Explore the topology looking for shared links amongst the egresses
-        Set<Link> linksToEnforce = exploreMcastTree(Sets.newHashSet(egresses), availablePaths);
-        // Build the final paths enforcing the shared links between egress devices
-        availablePaths.clear();
-        egresses.forEach(egress -> availablePaths.put(egress, getPaths(source, egress,
-                                                                       linksToEnforce)));
-        return availablePaths;
-    }
-
-    /**
-     * Gets path from src to dst computed using the custom link weigher.
-     *
-     * @param src source device ID
-     * @param dst destination device ID
-     * @return list of paths from src to dst
-     */
-    private List<Path> getPaths(DeviceId src, DeviceId dst, Set<Link> linksToEnforce) {
-        final Topology currentTopology = topologyService.currentTopology();
-        final LinkWeigher linkWeigher = new SRLinkWeigher(srManager, src, linksToEnforce);
-        List<Path> allPaths = Lists.newArrayList(topologyService.getPaths(currentTopology, src, dst, linkWeigher));
-        log.trace("{} path(s) found from {} to {}", allPaths.size(), src, dst);
-        return allPaths;
-    }
-
-    /**
      * Gets a path from src to dst.
      * If a path was allocated before, returns the allocated path.
      * Otherwise, randomly pick one from available paths.
@@ -1441,52 +1415,37 @@
      * @param dst destination device ID
      * @param mcastIp multicast group
      * @param allPaths paths list
+     *
      * @return an optional path from src to dst
      */
-    private Optional<Path> getPath(DeviceId src, DeviceId dst, IpAddress mcastIp,
-                                   List<Path> allPaths, ConnectPoint source) {
+    private Optional<Path> getPath(DeviceId src, DeviceId dst,
+                                   IpAddress mcastIp, List<Path> allPaths) {
         if (allPaths == null) {
-            allPaths = getPaths(src, dst, Collections.emptySet());
+            allPaths = mcastUtils.getPaths(src, dst, Collections.emptySet());
         }
         if (allPaths.isEmpty()) {
             return Optional.empty();
         }
         // Create a map index of suitability-to-list of paths. For example
-        // a path in the list associated to the index 1 shares only the
-        // first hop and it is less suitable of a path belonging to the index
-        // 2 that shares leaf-spine.
+        // a path in the list associated to the index 1 shares only one link
+        // and it is less suitable of a path belonging to the index 2
         Map<Integer, List<Path>> eligiblePaths = Maps.newHashMap();
-        int nhop;
-        McastStoreKey mcastStoreKey;
-        PortNumber srcPort;
-        Set<PortNumber> existingPorts;
-        NextObjective nextObj;
+        int score;
+        // Let's build the multicast tree
+        Set<List<Link>> storedPaths = getStoredPaths(mcastIp);
+        Set<Link> storedTree = storedPaths.stream()
+                .flatMap(Collection::stream).collect(Collectors.toSet());
+        log.trace("Stored tree {}", storedTree);
+        Set<Link> pathLinks;
         for (Path path : allPaths) {
             if (!src.equals(path.links().get(0).src().deviceId())) {
                 continue;
             }
-            nhop = 0;
-            // Iterate over the links
-            for (Link hop : path.links()) {
-                VlanId assignedVlan = mcastUtils.assignedVlan(hop.src().deviceId().equals(src) ?
-                                                                      source : null);
-                mcastStoreKey = new McastStoreKey(mcastIp, hop.src().deviceId(), assignedVlan);
-                // It does not exist in the store, go to the next link
-                if (!mcastNextObjStore.containsKey(mcastStoreKey)) {
-                    continue;
-                }
-                nextObj = mcastNextObjStore.get(mcastStoreKey).value();
-                existingPorts = mcastUtils.getPorts(nextObj.next());
-                srcPort = hop.src().port();
-                // the src port is not used as output, go to the next link
-                if (!existingPorts.contains(srcPort)) {
-                    continue;
-                }
-                nhop++;
-            }
-            // n_hop defines the index
-            if (nhop > 0) {
-                eligiblePaths.compute(nhop, (index, paths) -> {
+            pathLinks = Sets.newHashSet(path.links());
+            score = Sets.intersection(pathLinks, storedTree).size();
+            // score defines the index
+            if (score > 0) {
+                eligiblePaths.compute(score, (index, paths) -> {
                     paths = paths == null ? Lists.newArrayList() : paths;
                     paths.add(path);
                     return paths;
@@ -1509,6 +1468,19 @@
     }
 
     /**
+     * Gets stored paths of the group.
+     *
+     * @param mcastIp group address
+     * @return a collection of paths
+     */
+    private Set<List<Link>> getStoredPaths(IpAddress mcastIp) {
+        return mcastPathStore.stream()
+                .filter(entry -> entry.getKey().mcastIp().equals(mcastIp))
+                .map(Entry::getValue)
+                .collect(Collectors.toSet());
+    }
+
+    /**
      * Gets device(s) of given role and of given source in given multicast tree.
      *
      * @param mcastIp multicast IP
@@ -1539,21 +1511,6 @@
     }
 
     /**
-     * Gets source(s) of given role, given device in given multicast group.
-     *
-     * @param mcastIp multicast IP
-     * @param deviceId device id
-     * @param role multicast role
-     * @return set of device ID or empty set if not found
-     */
-    private Set<ConnectPoint> getSources(IpAddress mcastIp, DeviceId deviceId, McastRole role) {
-        return mcastRoleStore.entrySet().stream()
-                .filter(entry -> entry.getKey().mcastIp().equals(mcastIp) &&
-                        entry.getKey().deviceId().equals(deviceId) && entry.getValue().value() == role)
-                .map(Entry::getKey).map(McastRoleStoreKey::source).collect(Collectors.toSet());
-    }
-
-    /**
      * Gets source(s) of given multicast group.
      *
      * @param mcastIp multicast IP
@@ -1566,6 +1523,32 @@
     }
 
     /**
+     * Gets sink(s) of given multicast group.
+     *
+     * @param mcastIp multicast IP
+     * @return set of connect point or empty set if not found
+     */
+    private Set<ConnectPoint> getSinks(IpAddress mcastIp, DeviceId device, ConnectPoint source) {
+        McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
+        Collection<? extends List<Link>> storedPaths = Versioned.valueOrElse(
+                mcastPathStore.get(pathStoreKey), Lists.newArrayList());
+        VlanId assignedVlan = mcastUtils.assignedVlan(device.equals(source.deviceId()) ? source : null);
+        McastStoreKey mcastStoreKey = new McastStoreKey(mcastIp, device, assignedVlan);
+        NextObjective nextObjective = Versioned.valueOrNull(mcastNextObjStore.get(mcastStoreKey));
+        ImmutableSet.Builder<ConnectPoint> cpBuilder = ImmutableSet.builder();
+        if (nextObjective != null) {
+            Set<PortNumber> outputPorts = mcastUtils.getPorts(nextObjective.next());
+            outputPorts.forEach(portNumber -> cpBuilder.add(new ConnectPoint(device, portNumber)));
+        }
+        Set<ConnectPoint> egressCp = cpBuilder.build();
+        return egressCp.stream()
+                .filter(connectPoint -> !mcastUtils.isInfraPort(connectPoint, storedPaths))
+                .collect(Collectors.toSet());
+    }
+
+
+
+    /**
      * Gets groups which is affected by the link down event.
      *
      * @param link link going down
@@ -1594,41 +1577,6 @@
     }
 
     /**
-     * Gets the spine-facing port on ingress device of given multicast group.
-     *
-     * @param mcastIp multicast IP
-     * @param ingressDevice the ingress device
-     * @param source the source connect point
-     * @return spine-facing port on ingress device
-     */
-    private Set<PortNumber> ingressTransitPort(IpAddress mcastIp, DeviceId ingressDevice,
-                                               ConnectPoint source) {
-        ImmutableSet.Builder<PortNumber> portBuilder = ImmutableSet.builder();
-        if (ingressDevice != null) {
-            Versioned<NextObjective> nextObjVers = mcastNextObjStore.get(new McastStoreKey(mcastIp, ingressDevice,
-                                                                          mcastUtils.assignedVlan(source)));
-            if (nextObjVers == null) {
-                log.warn("Absent next objective for {}", new McastStoreKey(mcastIp, ingressDevice,
-                        mcastUtils.assignedVlan(source)));
-                return portBuilder.build();
-            }
-            NextObjective nextObj = nextObjVers.value();
-            Set<PortNumber> ports = mcastUtils.getPorts(nextObj.next());
-            // Let's find out all the ingress-transit ports
-            for (PortNumber port : ports) {
-                // Spine-facing port should have no subnet and no xconnect
-                if (srManager.deviceConfiguration() != null &&
-                        srManager.deviceConfiguration().getPortSubnets(ingressDevice, port).isEmpty() &&
-                        (srManager.xconnectService == null ||
-                        !srManager.xconnectService.hasXconnect(new ConnectPoint(ingressDevice, port)))) {
-                    portBuilder.add(port);
-                }
-            }
-        }
-        return portBuilder.build();
-    }
-
-    /**
      * Verify if a given connect point is sink for this group.
      *
      * @param mcastIp group address
@@ -1683,7 +1631,7 @@
     private boolean isSinkReachable(IpAddress mcastIp, ConnectPoint sink,
                                     ConnectPoint source) {
         return sink.deviceId().equals(source.deviceId()) ||
-                getPath(source.deviceId(), sink.deviceId(), mcastIp, null, source).isPresent();
+                getPath(source.deviceId(), sink.deviceId(), mcastIp, null).isPresent();
     }
 
     /**
@@ -1760,7 +1708,9 @@
             mcastFilteringObjStore.add(filterObjStoreKey);
         } else {
             // do nothing
-            log.debug("Filtering already present. Abort");
+            log.debug("Filtering already present for connect point {}, vlan {} and {}. Abort",
+                      filterObjStoreKey.ingressCP(), filterObjStoreKey.vlanId(),
+                      filterObjStoreKey.isIpv4() ? "IPv4" : "IPv6");
         }
     }
 
@@ -1954,6 +1904,7 @@
      * @return the mapping mcastIp-device to next id
      */
     public Map<McastStoreKey, Integer> getNextIds(IpAddress mcastIp) {
+        log.info("mcastNexts {}", mcastNextObjStore.size());
         if (mcastIp != null) {
             return mcastNextObjStore.entrySet().stream()
                     .filter(mcastEntry -> mcastIp.equals(mcastEntry.getKey().mcastIp()))
@@ -1977,6 +1928,39 @@
     }
 
     /**
+     * Build the mcast paths.
+     *
+     * @param storedPaths mcast tree
+     * @param mcastIp the group ip
+     * @param source the source
+     */
+    private Map<ConnectPoint, List<ConnectPoint>> buildMcastPaths(Collection<? extends List<Link>> storedPaths,
+                                                                  IpAddress mcastIp, ConnectPoint source) {
+        Map<ConnectPoint, List<ConnectPoint>> mcastTree = Maps.newHashMap();
+        // Local sinks
+        Set<ConnectPoint> localSinks = getSinks(mcastIp, source.deviceId(), source);
+        localSinks.forEach(localSink -> mcastTree.put(localSink, Lists.newArrayList(localSink, source)));
+        // Remote sinks
+        storedPaths.forEach(path -> {
+            List<Link> links = path;
+            DeviceId egressDevice = links.get(links.size() - 1).dst().deviceId();
+            Set<ConnectPoint> remoteSinks = getSinks(mcastIp, egressDevice, source);
+            List<ConnectPoint> connectPoints = Lists.newArrayList(source);
+            links.forEach(link -> {
+                connectPoints.add(link.src());
+                connectPoints.add(link.dst());
+            });
+            Collections.reverse(connectPoints);
+            remoteSinks.forEach(remoteSink -> {
+                List<ConnectPoint> finalPath = Lists.newArrayList(connectPoints);
+                finalPath.add(0, remoteSink);
+                mcastTree.put(remoteSink, finalPath);
+            });
+        });
+        return mcastTree;
+    }
+
+    /**
      * Returns the associated roles to the mcast groups.
      *
      * @param mcastIp the group ip
@@ -1985,6 +1969,7 @@
      */
     public Map<McastRoleStoreKey, McastRole> getMcastRoles(IpAddress mcastIp,
                                                        ConnectPoint sourcecp) {
+        log.info("mcastRoles {}", mcastRoleStore.size());
         if (mcastIp != null) {
             Map<McastRoleStoreKey, McastRole> roles = mcastRoleStore.entrySet().stream()
                     .filter(mcastEntry -> mcastIp.equals(mcastEntry.getKey().mcastIp()))
@@ -2012,6 +1997,8 @@
      */
     public Multimap<ConnectPoint, List<ConnectPoint>> getMcastTrees(IpAddress mcastIp,
                                                                     ConnectPoint sourcecp) {
+        // TODO remove
+        log.info("{}", getStoredPaths(mcastIp));
         Multimap<ConnectPoint, List<ConnectPoint>> mcastTrees = HashMultimap.create();
         Set<ConnectPoint> sources = mcastUtils.getSources(mcastIp);
         if (sourcecp != null) {
@@ -2020,12 +2007,13 @@
         }
         if (!sources.isEmpty()) {
             sources.forEach(source -> {
-                Map<ConnectPoint, List<ConnectPoint>> mcastPaths = Maps.newHashMap();
-                Set<DeviceId> visited = Sets.newHashSet();
-                List<ConnectPoint> currentPath = Lists.newArrayList(source);
-                mcastUtils.buildMcastPaths(mcastNextObjStore.asJavaMap(), source.deviceId(), visited, mcastPaths,
-                        currentPath, mcastIp, source);
-                mcastPaths.forEach(mcastTrees::put);
+                McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
+                Collection<? extends List<Link>> storedPaths = Versioned.valueOrElse(
+                        mcastPathStore.get(pathStoreKey), Lists.newArrayList());
+                // TODO remove
+                log.info("Paths for group {} and source {} - {}", mcastIp, source, storedPaths.size());
+                Map<ConnectPoint, List<ConnectPoint>> mcastTree = buildMcastPaths(storedPaths, mcastIp, source);
+                mcastTree.forEach(mcastTrees::put);
             });
         }
         return mcastTrees;
@@ -2047,6 +2035,8 @@
      * @return the mapping group-node
      */
     public Map<DeviceId, List<McastFilteringObjStoreKey>> getMcastFilters() {
+        // TODO remove
+        log.info("mcastFilters {}", mcastFilteringObjStore.size());
         Map<DeviceId, List<McastFilteringObjStoreKey>> mapping = Maps.newHashMap();
         Set<McastFilteringObjStoreKey> currentKeys = Sets.newHashSet(mcastFilteringObjStore);
         currentKeys.forEach(filteringObjStoreKey ->
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastPathStoreKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastPathStoreKey.java
new file mode 100644
index 0000000..76f46fe
--- /dev/null
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastPathStoreKey.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+ *
+ * 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 org.onosproject.segmentrouting.mcast;
+
+import org.onlab.packet.IpAddress;
+import org.onosproject.net.ConnectPoint;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Key of multicast path store.
+ */
+public class McastPathStoreKey {
+    // Identify path using group address and source
+    private final IpAddress mcastIp;
+    private final ConnectPoint source;
+
+    /**
+     * Constructs the key of multicast path store.
+     *
+     * @param mcastIp multicast group IP address
+     * @param source source connect point
+     */
+    public McastPathStoreKey(IpAddress mcastIp, ConnectPoint source) {
+        checkNotNull(mcastIp, "mcastIp cannot be null");
+        checkNotNull(source, "source cannot be null");
+        checkArgument(mcastIp.isMulticast(), "mcastIp must be a multicast address");
+        this.mcastIp = mcastIp;
+        this.source = source;
+    }
+
+    // Constructor for serialization
+    private McastPathStoreKey() {
+        this.mcastIp = null;
+        this.source = null;
+    }
+
+    /**
+     * Returns the multicast IP address of this key.
+     *
+     * @return multicast IP
+     */
+    public IpAddress mcastIp() {
+        return mcastIp;
+    }
+
+    /**
+     * Returns the device ID of this key.
+     *
+     * @return device ID
+     */
+    public ConnectPoint source() {
+        return source;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof McastPathStoreKey)) {
+            return false;
+        }
+        McastPathStoreKey that =
+                (McastPathStoreKey) o;
+        return (Objects.equals(this.mcastIp, that.mcastIp) &&
+                Objects.equals(this.source, that.source));
+    }
+
+    @Override
+    public int hashCode() {
+         return Objects.hash(mcastIp, source);
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(getClass())
+                .add("mcastIp", mcastIp)
+                .add("source", source)
+                .toString();
+    }
+}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastPathStoreKeySerializer.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastPathStoreKeySerializer.java
new file mode 100644
index 0000000..4ef0194
--- /dev/null
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastPathStoreKeySerializer.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+ *
+ * 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 org.onosproject.segmentrouting.mcast;
+
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.Serializer;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
+import org.onlab.packet.IpAddress;
+import org.onosproject.net.ConnectPoint;
+
+/**
+ * Custom serializer for {@link McastPathStoreKey}.
+ */
+class McastPathStoreKeySerializer extends Serializer<McastPathStoreKey> {
+
+    /**
+     * Creates {@link McastPathStoreKeySerializer} serializer instance.
+     */
+    McastPathStoreKeySerializer() {
+        // non-null, immutable
+        super(false, true);
+    }
+
+    @Override
+    public void write(Kryo kryo, Output output, McastPathStoreKey object) {
+        kryo.writeClassAndObject(output, object.mcastIp());
+        kryo.writeClassAndObject(output, object.source());
+    }
+
+    @Override
+    public McastPathStoreKey read(Kryo kryo, Input input, Class<McastPathStoreKey> type) {
+        IpAddress mcastIp = (IpAddress) kryo.readClassAndObject(input);
+        ConnectPoint source = (ConnectPoint) kryo.readClassAndObject(input);
+        return new McastPathStoreKey(mcastIp, source);
+    }
+}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastUtils.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastUtils.java
index c4e1ad4..396b998 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastUtils.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastUtils.java
@@ -16,6 +16,7 @@
 
 package org.onosproject.segmentrouting.mcast;
 
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
@@ -34,6 +35,7 @@
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.HostId;
 import org.onosproject.net.Link;
+import org.onosproject.net.Path;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.config.basics.McastConfig;
 import org.onosproject.net.flow.DefaultTrafficSelector;
@@ -50,6 +52,10 @@
 import org.onosproject.net.flowobjective.ForwardingObjective;
 import org.onosproject.net.flowobjective.NextObjective;
 import org.onosproject.net.flowobjective.ObjectiveContext;
+import org.onosproject.net.topology.LinkWeigher;
+import org.onosproject.net.topology.Topology;
+import org.onosproject.net.topology.TopologyService;
+import org.onosproject.segmentrouting.SRLinkWeigher;
 import org.onosproject.segmentrouting.SegmentRoutingManager;
 import org.onosproject.segmentrouting.SegmentRoutingService;
 import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
@@ -57,8 +63,10 @@
 import org.slf4j.Logger;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -66,11 +74,11 @@
  * Utility class for Multicast Handler.
  */
 class McastUtils {
-
     // Internal reference to the log
     private final Logger log;
-    // Internal reference to SR Manager
-    private SegmentRoutingManager srManager;
+    // Internal reference to SR Manager and topology service
+    private final SegmentRoutingManager srManager;
+    private final TopologyService topologyService;
     // Internal reference to the app id
     private ApplicationId coreAppId;
     // Hashing function for the multicast hasher
@@ -87,6 +95,7 @@
      */
     McastUtils(SegmentRoutingManager srManager, ApplicationId coreAppId, Logger log) {
         this.srManager = srManager;
+        this.topologyService = srManager.topologyService;
         this.coreAppId = coreAppId;
         this.log = log;
         this.mcastLeaderCache = Maps.newConcurrentMap();
@@ -95,7 +104,7 @@
     /**
      * Clean up when deactivating the application.
      */
-    public void terminate() {
+    void terminate() {
         mcastLeaderCache.clear();
     }
 
@@ -233,6 +242,8 @@
         return srManager.getDefaultInternalVlan();
     }
 
+
+
     /**
      * Gets sources connect points of given multicast group.
      *
@@ -477,64 +488,228 @@
     }
 
     /**
-     * Build recursively the mcast paths.
+     * Go through all the paths, looking for shared links to be used
+     * in the final path computation.
      *
-     * @param mcastNextObjStore mcast next obj store
-     * @param toVisit the node to visit
-     * @param visited the visited nodes
-     * @param mcastPaths the current mcast paths
-     * @param currentPath the current path
-     * @param mcastIp the group ip
-     * @param source the source
+     * @param egresses egress devices
+     * @param availablePaths all the available paths towards the egress
+     * @return shared links between egress devices
      */
-    void buildMcastPaths(Map<McastStoreKey, NextObjective> mcastNextObjStore,
-                                 DeviceId toVisit, Set<DeviceId> visited,
-                                 Map<ConnectPoint, List<ConnectPoint>> mcastPaths,
-                                 List<ConnectPoint> currentPath, IpAddress mcastIp,
-                                 ConnectPoint source) {
-        log.debug("Building Multicast paths recursively for {} - next device to visit is {}",
-                  mcastIp, toVisit);
-        // If we have visited the node to visit there is a loop
-        if (visited.contains(toVisit)) {
-            return;
-        }
-        // Visit next-hop
-        visited.add(toVisit);
-        VlanId assignedVlan = assignedVlan(toVisit.equals(source.deviceId()) ? source : null);
-        McastStoreKey mcastStoreKey = new McastStoreKey(mcastIp, toVisit, assignedVlan);
-        // Looking for next-hops
-        if (mcastNextObjStore.containsKey(mcastStoreKey)) {
-            // Build egress connect points, get ports and build relative cps
-            NextObjective nextObjective = mcastNextObjStore.get(mcastStoreKey);
-            Set<PortNumber> outputPorts = getPorts(nextObjective.next());
-            ImmutableSet.Builder<ConnectPoint> cpBuilder = ImmutableSet.builder();
-            outputPorts.forEach(portNumber -> cpBuilder.add(new ConnectPoint(toVisit, portNumber)));
-            Set<ConnectPoint> egressPoints = cpBuilder.build();
-            Set<Link> egressLinks;
-            List<ConnectPoint> newCurrentPath;
-            Set<DeviceId> newVisited;
-            DeviceId newToVisit;
-            for (ConnectPoint egressPoint : egressPoints) {
-                egressLinks = srManager.linkService.getEgressLinks(egressPoint);
-                // If it does not have egress links, stop
-                if (egressLinks.isEmpty()) {
-                    // Add the connect points to the path
-                    newCurrentPath = Lists.newArrayList(currentPath);
-                    newCurrentPath.add(0, egressPoint);
-                    mcastPaths.put(egressPoint, newCurrentPath);
-                } else {
-                    newVisited = Sets.newHashSet(visited);
-                    // Iterate over the egress links for the next hops
-                    for (Link egressLink : egressLinks) {
-                        newToVisit = egressLink.dst().deviceId();
-                        newCurrentPath = Lists.newArrayList(currentPath);
-                        newCurrentPath.add(0, egressPoint);
-                        newCurrentPath.add(0, egressLink.dst());
-                        buildMcastPaths(mcastNextObjStore, newToVisit, newVisited, mcastPaths, newCurrentPath, mcastIp,
-                                source);
-                    }
-                }
+    private Set<Link> exploreMcastTree(Set<DeviceId> egresses,
+                                       Map<DeviceId, List<Path>> availablePaths) {
+        int minLength = Integer.MAX_VALUE;
+        int length;
+        List<Path> currentPaths;
+        // Verify the source can still reach all the egresses
+        for (DeviceId egress : egresses) {
+            // From the source we cannot reach all the sinks
+            // just continue and let's figure out after
+            currentPaths = availablePaths.get(egress);
+            if (currentPaths.isEmpty()) {
+                continue;
+            }
+            // Get the length of the first one available, update the min length
+            length = currentPaths.get(0).links().size();
+            if (length < minLength) {
+                minLength = length;
             }
         }
+        // If there are no paths
+        if (minLength == Integer.MAX_VALUE) {
+            return Collections.emptySet();
+        }
+        int index = 0;
+        Set<Link> sharedLinks = Sets.newHashSet();
+        Set<Link> currentSharedLinks;
+        Set<Link> currentLinks;
+        DeviceId egressToRemove = null;
+        // Let's find out the shared links
+        while (index < minLength) {
+            // Initialize the intersection with the paths related to the first egress
+            currentPaths = availablePaths.get(egresses.stream().findFirst().orElse(null));
+            currentSharedLinks = Sets.newHashSet();
+            // Iterate over the paths and take the "index" links
+            for (Path path : currentPaths) {
+                currentSharedLinks.add(path.links().get(index));
+            }
+            // Iterate over the remaining egress
+            for (DeviceId egress : egresses) {
+                // Iterate over the paths and take the "index" links
+                currentLinks = Sets.newHashSet();
+                for (Path path : availablePaths.get(egress)) {
+                    currentLinks.add(path.links().get(index));
+                }
+                // Do intersection
+                currentSharedLinks = Sets.intersection(currentSharedLinks, currentLinks);
+                // If there are no shared paths exit and record the device to remove
+                // we have to retry with a subset of sinks
+                if (currentSharedLinks.isEmpty()) {
+                    egressToRemove = egress;
+                    index = minLength;
+                    break;
+                }
+            }
+            sharedLinks.addAll(currentSharedLinks);
+            index++;
+        }
+        // If the shared links is empty and there are egress let's retry another time with less sinks,
+        // we can still build optimal subtrees
+        if (sharedLinks.isEmpty() && egresses.size() > 1 && egressToRemove != null) {
+            egresses.remove(egressToRemove);
+            sharedLinks = exploreMcastTree(egresses, availablePaths);
+        }
+        return sharedLinks;
     }
+
+    /**
+     * Build Mcast tree having as root the given source and as leaves the given egress points.
+     *
+     * @param mcastIp multicast group
+     * @param source source of the tree
+     * @param sinks leaves of the tree
+     * @return the computed Mcast tree
+     */
+    Map<ConnectPoint, List<Path>> computeSinkMcastTree(IpAddress mcastIp,
+                                                       DeviceId source,
+                                                       Set<ConnectPoint> sinks) {
+        // Get the egress devices, remove source from the egress if present
+        Set<DeviceId> egresses = sinks.stream().map(ConnectPoint::deviceId)
+                .filter(deviceId -> !deviceId.equals(source)).collect(Collectors.toSet());
+        Map<DeviceId, List<Path>> mcastTree = computeMcastTree(mcastIp, source, egresses);
+        final Map<ConnectPoint, List<Path>> finalTree = Maps.newHashMap();
+        // We need to put back the source if it was originally present
+        sinks.forEach(sink -> {
+            List<Path> sinkPaths = mcastTree.get(sink.deviceId());
+            finalTree.put(sink, sinkPaths != null ? sinkPaths : ImmutableList.of());
+        });
+        return finalTree;
+    }
+
+    /**
+     * Build Mcast tree having as root the given source and as leaves the given egress.
+     *
+     * @param mcastIp multicast group
+     * @param source source of the tree
+     * @param egresses leaves of the tree
+     * @return the computed Mcast tree
+     */
+    private Map<DeviceId, List<Path>> computeMcastTree(IpAddress mcastIp,
+                                                       DeviceId source,
+                                                       Set<DeviceId> egresses) {
+        log.debug("Computing tree for Multicast group {}, source {} and leafs {}",
+                  mcastIp, source, egresses);
+        // Pre-compute all the paths
+        Map<DeviceId, List<Path>> availablePaths = Maps.newHashMap();
+        egresses.forEach(egress -> availablePaths.put(egress, getPaths(source, egress,
+                                                                       Collections.emptySet())));
+        // Explore the topology looking for shared links amongst the egresses
+        Set<Link> linksToEnforce = exploreMcastTree(Sets.newHashSet(egresses), availablePaths);
+        // Build the final paths enforcing the shared links between egress devices
+        availablePaths.clear();
+        egresses.forEach(egress -> availablePaths.put(egress, getPaths(source, egress,
+                                                                       linksToEnforce)));
+        return availablePaths;
+    }
+
+    /**
+     * Gets path from src to dst computed using the custom link weigher.
+     *
+     * @param src source device ID
+     * @param dst destination device ID
+     * @param linksToEnforce links to be enforced
+     * @return list of paths from src to dst
+     */
+    List<Path> getPaths(DeviceId src, DeviceId dst, Set<Link> linksToEnforce) {
+        final Topology currentTopology = topologyService.currentTopology();
+        final LinkWeigher linkWeigher = new SRLinkWeigher(srManager, src, linksToEnforce);
+        List<Path> allPaths = Lists.newArrayList(topologyService.getPaths(currentTopology, src, dst, linkWeigher));
+        log.trace("{} path(s) found from {} to {}", allPaths.size(), src, dst);
+        return allPaths;
+    }
+
+    /**
+     * Gets a stored path having dst as egress.
+     *
+     * @param dst destination device ID
+     * @param storedPaths paths list
+     * @return an optional path
+     */
+    Optional<? extends List<Link>> getStoredPath(DeviceId dst, Collection<? extends List<Link>> storedPaths) {
+        return storedPaths.stream()
+                .filter(path -> path.get(path.size() - 1).dst().deviceId().equals(dst))
+                .findFirst();
+    }
+
+    /**
+     * Returns a set of affected paths by the failed element.
+     *
+     * @param paths the paths to check
+     * @param failedElement the failed element
+     * @return the affected paths
+     */
+    Set<List<Link>> getAffectedPaths(Set<List<Link>> paths, Object failedElement) {
+        if (failedElement instanceof DeviceId) {
+            return getAffectedPathsByDevice(paths, failedElement);
+        }
+        return getAffectedPathsByLink(paths, failedElement);
+    }
+
+    private Set<List<Link>> getAffectedPathsByDevice(Set<List<Link>> paths, Object failedElement) {
+        DeviceId affectedDevice = (DeviceId) failedElement;
+        Set<List<Link>> affectedPaths = Sets.newHashSet();
+        paths.forEach(path -> {
+            if (path.stream().anyMatch(link -> link.src().deviceId().equals(affectedDevice))) {
+                affectedPaths.add(path);
+            }
+        });
+        return affectedPaths;
+    }
+
+    private Set<List<Link>> getAffectedPathsByLink(Set<List<Link>> paths, Object failedElement) {
+        Link affectedLink = (Link) failedElement;
+        Set<List<Link>> affectedPaths = Sets.newHashSet();
+        paths.forEach(path -> {
+            if (path.contains(affectedLink)) {
+                affectedPaths.add(path);
+            }
+        });
+        return affectedPaths;
+    }
+
+    /**
+     * Checks if the failure is affecting the transit device.
+     *
+     * @param devices the transit devices
+     * @param failedElement the failed element
+     * @return true if the failed element is affecting the transit devices
+     */
+    boolean isInfraFailure(Set<DeviceId> devices, Object failedElement) {
+        if (failedElement instanceof DeviceId) {
+            return isInfraFailureByDevice(devices, failedElement);
+        }
+        return true;
+    }
+
+    private boolean isInfraFailureByDevice(Set<DeviceId> devices, Object failedElement) {
+        DeviceId affectedDevice = (DeviceId) failedElement;
+        return devices.contains(affectedDevice);
+    }
+
+    /**
+     * Checks if a port is an infra port.
+     *
+     * @param connectPoint port to be checked
+     * @param storedPaths paths to be checked against
+     * @return true if the port is an infra port. False otherwise.
+     */
+    boolean isInfraPort(ConnectPoint connectPoint, Collection<? extends List<Link>> storedPaths) {
+        for (List<Link> path : storedPaths) {
+            if (path.stream().anyMatch(link -> link.src().equals(connectPoint) ||
+                    link.dst().equals(connectPoint))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
 }
