/*
 * Copyright 2015-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;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

import org.onlab.packet.EthType;
import com.google.common.collect.Streams;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onlab.util.PredictableExecutor;
import org.onlab.util.PredictableExecutor.PickyCallable;
import org.onosproject.cluster.NodeId;
import org.onosproject.mastership.MastershipEvent;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.PortNumber;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.DeviceConfiguration;
import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.Serializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.concurrent.Executors.newScheduledThreadPool;
import static org.onlab.util.Tools.groupedThreads;

/**
 * Default routing handler that is responsible for route computing and
 * routing rule population.
 */
public class DefaultRoutingHandler {
    private static final int MAX_CONSTANT_RETRY_ATTEMPTS = 5;
    private static final long RETRY_INTERVAL_MS = 250L;
    private static final int RETRY_INTERVAL_SCALE = 1;
    private static final long STABLITY_THRESHOLD = 10; //secs
    private static final long MASTER_CHANGE_DELAY = 1000; // ms
    private static final long PURGE_DELAY = 1000; // ms
    private static Logger log = LoggerFactory.getLogger(DefaultRoutingHandler.class);

    private SegmentRoutingManager srManager;
    private RoutingRulePopulator rulePopulator;
    private HashMap<DeviceId, EcmpShortestPathGraph> currentEcmpSpgMap;
    private HashMap<DeviceId, EcmpShortestPathGraph> updatedEcmpSpgMap;
    private DeviceConfiguration config;
    private final Lock statusLock = new ReentrantLock();
    private volatile Status populationStatus;
    private ScheduledExecutorService executorService
        = newScheduledThreadPool(1, groupedThreads("retryftr", "retry-%d", log));
    private ScheduledExecutorService executorServiceMstChg
        = newScheduledThreadPool(1, groupedThreads("masterChg", "mstch-%d", log));
    private ScheduledExecutorService executorServiceFRR
        = newScheduledThreadPool(1, groupedThreads("fullRR", "fullRR-%d", log));
    // Route populators - 0 will leverage available processors
    private static final int DEFAULT_THREADS = 0;
    private ExecutorService routePopulators;

    private Instant lastRoutingChange = Instant.EPOCH;
    private Instant lastFullReroute = Instant.EPOCH;

    // Distributed store to keep track of ONOS instance that should program the
    // device pair. There should be only one instance (the king) that programs the same pair.
    Map<Set<DeviceId>, NodeId> shouldProgram;
    Map<DeviceId, Boolean> shouldProgramCache;

    // Local store to keep track of all devices that this instance was responsible
    // for programming in the last run. Helps to determine if mastership changed
    // during a run - only relevant for programming as a result of topo change.
    Set<DeviceId> lastProgrammed;

    /**
     * Represents the default routing population status.
     */
    public enum Status {
        // population process is not started yet.
        IDLE,
        // population process started.
        STARTED,
        // population process was aborted due to errors, mostly for groups not found.
        ABORTED,
        // population process was finished successfully.
        SUCCEEDED
    }

    /**
     * Creates a DefaultRoutingHandler object.
     *
     * @param srManager SegmentRoutingManager object
     */
    DefaultRoutingHandler(SegmentRoutingManager srManager) {
        this.shouldProgram = srManager.storageService.<Set<DeviceId>, NodeId>consistentMapBuilder()
                .withName("sr-should-program")
                .withSerializer(Serializer.using(KryoNamespaces.API))
                .withRelaxedReadConsistency()
                .build().asJavaMap();
        this.shouldProgramCache = Maps.newConcurrentMap();
        update(srManager);
        this.routePopulators = new PredictableExecutor(DEFAULT_THREADS,
                                                      groupedThreads("onos/sr", "r-populator-%d", log));
    }

    /**
     * Updates a DefaultRoutingHandler object.
     *
     * @param srManager SegmentRoutingManager object
     */
    void update(SegmentRoutingManager srManager) {
        this.srManager = srManager;
        this.rulePopulator = checkNotNull(srManager.routingRulePopulator);
        this.config = checkNotNull(srManager.deviceConfiguration);
        this.populationStatus = Status.IDLE;
        this.currentEcmpSpgMap = Maps.newHashMap();
        this.lastProgrammed = Sets.newConcurrentHashSet();
    }

    /**
     * Returns an immutable copy of the current ECMP shortest-path graph as
     * computed by this controller instance.
     *
     * @return immutable copy of the current ECMP graph
     */
    public ImmutableMap<DeviceId, EcmpShortestPathGraph> getCurrentEmcpSpgMap() {
        Builder<DeviceId, EcmpShortestPathGraph> builder = ImmutableMap.builder();
        currentEcmpSpgMap.entrySet().forEach(entry -> {
            if (entry.getValue() != null) {
                builder.put(entry.getKey(), entry.getValue());
            }
        });
        return builder.build();
    }

    /**
     * Acquires the lock used when making routing changes.
     */
    public void acquireRoutingLock() {
        statusLock.lock();
    }

    /**
     * Releases the lock used when making routing changes.
     */
    public void releaseRoutingLock() {
        statusLock.unlock();
    }

    /**
    * Determines if routing in the network has been stable in the last
    * STABLITY_THRESHOLD seconds, by comparing the current time to the last
    * routing change timestamp.
    *
    * @return true if stable
    */
   public boolean isRoutingStable() {
       long last = (long) (lastRoutingChange.toEpochMilli() / 1000.0);
       long now = (long) (Instant.now().toEpochMilli() / 1000.0);
       log.trace("Routing stable since {}s", now - last);
       return (now - last) > STABLITY_THRESHOLD;
   }

    /**
     * Gracefully shuts down the defaultRoutingHandler. Typically called when
     * the app is deactivated
     */
    public void shutdown() {
        executorService.shutdown();
        executorServiceMstChg.shutdown();
        executorServiceFRR.shutdown();
        routePopulators.shutdown();
    }

    //////////////////////////////////////
    //  Route path handling
    //////////////////////////////////////

    /* The following three methods represent the three major ways in which
     * route-path handling is triggered in the network
     *      a) due to configuration change
     *      b) due to route-added event
     *      c) due to change in the topology
     */

    /**
     * Populates all routing rules to all switches. Typically triggered at
     * startup or after a configuration event.
     */
    public void populateAllRoutingRules() {
        lastRoutingChange = Instant.now();
        statusLock.lock();
        try {
            if (populationStatus == Status.STARTED) {
                log.warn("Previous rule population is not finished. Cannot"
                        + " proceed with populateAllRoutingRules");
                return;
            }

            populationStatus = Status.STARTED;
            rulePopulator.resetCounter();
            log.info("Starting to populate all routing rules");
            log.debug("populateAllRoutingRules: populationStatus is STARTED");

            // take a snapshot of the topology
            updatedEcmpSpgMap = new HashMap<>();
            Set<EdgePair> edgePairs = new HashSet<>();
            Set<ArrayList<DeviceId>> routeChanges = new HashSet<>();
            for (DeviceId dstSw : srManager.deviceConfiguration.getRouters()) {
                EcmpShortestPathGraph ecmpSpgUpdated =
                        new EcmpShortestPathGraph(dstSw, srManager);
                updatedEcmpSpgMap.put(dstSw, ecmpSpgUpdated);
                Optional<DeviceId> pairDev = srManager.getPairDeviceId(dstSw);
                if (pairDev.isPresent()) {
                    // pairDev may not be available yet, but we still need to add
                    ecmpSpgUpdated = new EcmpShortestPathGraph(pairDev.get(), srManager);
                    updatedEcmpSpgMap.put(pairDev.get(), ecmpSpgUpdated);
                    edgePairs.add(new EdgePair(dstSw, pairDev.get()));
                }

                if (!shouldProgram(dstSw)) {
                    lastProgrammed.remove(dstSw);
                    continue;
                } else {
                    lastProgrammed.add(dstSw);
                }
                // To do a full reroute, assume all route-paths have changed
                for (DeviceId dev : deviceAndItsPair(dstSw)) {
                    for (DeviceId targetSw : srManager.deviceConfiguration.getRouters()) {
                        if (targetSw.equals(dev)) {
                            continue;
                        }
                        routeChanges.add(Lists.newArrayList(targetSw, dev));
                    }
                }
            }

            if (!redoRouting(routeChanges, edgePairs, null)) {
                log.debug("populateAllRoutingRules: populationStatus is ABORTED");
                populationStatus = Status.ABORTED;
                log.warn("Failed to repopulate all routing rules.");
                return;
            }

            log.debug("populateAllRoutingRules: populationStatus is SUCCEEDED");
            populationStatus = Status.SUCCEEDED;
            log.info("Completed all routing rule population. Total # of rules pushed : {}",
                    rulePopulator.getCounter());
            return;
        } catch (Exception e) {
            log.error("populateAllRoutingRules thrown an exception: {}",
                      e.getMessage(), e);
            populationStatus = Status.ABORTED;
        } finally {
            statusLock.unlock();
        }
    }

    /**
     * Populate rules from all other edge devices to the connect-point(s)
     * specified for the given subnets.
     *
     * @param cpts connect point(s) of the subnets being added
     * @param subnets subnets being added
     */
    // XXX refactor
    protected void populateSubnet(Set<ConnectPoint> cpts, Set<IpPrefix> subnets) {
        if (cpts == null || cpts.size() < 1 || cpts.size() > 2) {
            log.warn("Skipping populateSubnet due to illegal size of connect points. {}", cpts);
            return;
        }

        lastRoutingChange = Instant.now();
        statusLock.lock();
        try {
           if (populationStatus == Status.STARTED) {
                log.warn("Previous rule population is not finished. Cannot"
                        + " proceed with routing rules for added routes");
                return;
            }
            populationStatus = Status.STARTED;
            rulePopulator.resetCounter();
            log.info("Starting to populate routing rules for added routes, subnets={}, cpts={}",
                    subnets, cpts);
            // In principle an update to a subnet/prefix should not require a
            // new ECMPspg calculation as it is not a topology event. As a
            // result, we use the current/existing ECMPspg in the updated map
            // used by the redoRouting method.
            if (updatedEcmpSpgMap == null) {
                updatedEcmpSpgMap = new HashMap<>();
            }
            currentEcmpSpgMap.entrySet().forEach(entry -> {
                updatedEcmpSpgMap.put(entry.getKey(), entry.getValue());
                if (log.isTraceEnabled()) {
                    log.trace("Root switch: {}", entry.getKey());
                    log.trace("  Current/Existing SPG: {}", entry.getValue());
                }
            });
            Set<EdgePair> edgePairs = new HashSet<>();
            Set<ArrayList<DeviceId>> routeChanges = new HashSet<>();
            boolean handleRouting = false;

            if (cpts.size() == 2) {
                // ensure connect points are edge-pairs
                Iterator<ConnectPoint> iter = cpts.iterator();
                DeviceId dev1 = iter.next().deviceId();
                Optional<DeviceId> pairDev = srManager.getPairDeviceId(dev1);
                if (pairDev.isPresent() && iter.next().deviceId().equals(pairDev.get())) {
                    edgePairs.add(new EdgePair(dev1, pairDev.get()));
                } else {
                    log.warn("Connectpoints {} for subnets {} not on "
                            + "pair-devices.. aborting populateSubnet", cpts, subnets);
                    populationStatus = Status.ABORTED;
                    return;
                }
                for (ConnectPoint cp : cpts) {
                    if (updatedEcmpSpgMap.get(cp.deviceId()) == null) {
                        EcmpShortestPathGraph ecmpSpgUpdated =
                            new EcmpShortestPathGraph(cp.deviceId(), srManager);
                        updatedEcmpSpgMap.put(cp.deviceId(), ecmpSpgUpdated);
                        log.warn("populateSubnet: no updated graph for dev:{}"
                                + " ... creating", cp.deviceId());
                    }
                    if (!shouldProgram(cp.deviceId())) {
                        continue;
                    }
                    handleRouting = true;
                }
            } else {
                // single connect point
                DeviceId dstSw = cpts.iterator().next().deviceId();
                if (updatedEcmpSpgMap.get(dstSw) == null) {
                    EcmpShortestPathGraph ecmpSpgUpdated =
                        new EcmpShortestPathGraph(dstSw, srManager);
                    updatedEcmpSpgMap.put(dstSw, ecmpSpgUpdated);
                    log.warn("populateSubnet: no updated graph for dev:{}"
                            + " ... creating", dstSw);
                }
                handleRouting = shouldProgram(dstSw);
            }

            if (!handleRouting) {
                log.debug("This instance is not handling ecmp routing to the "
                        + "connectPoint(s) {}", cpts);
                populationStatus = Status.ABORTED;
                return;
            }

            // if it gets here, this instance should handle routing for the
            // connectpoint(s). Assume all route-paths have to be updated to
            // the connectpoint(s) with the following exceptions
            // 1. if target is non-edge no need for routing rules
            // 2. if target is one of the connectpoints
            for (ConnectPoint cp : cpts) {
                DeviceId dstSw = cp.deviceId();
                for (Device targetSw : srManager.deviceService.getDevices()) {
                    boolean isEdge = false;
                    try {
                        isEdge = config.isEdgeDevice(targetSw.id());
                    } catch (DeviceConfigNotFoundException e) {
                        log.warn(e.getMessage() + "aborting populateSubnet on targetSw {}", targetSw.id());
                        continue;
                    }
                    Optional<DeviceId> pairDev = srManager.getPairDeviceId(dstSw);
                    if (dstSw.equals(targetSw.id()) || !isEdge ||
                            (cpts.size() == 2 && pairDev.isPresent() && targetSw.id().equals(pairDev.get()))) {
                        continue;
                    }
                    routeChanges.add(Lists.newArrayList(targetSw.id(), dstSw));
                }
            }

            if (!redoRouting(routeChanges, edgePairs, subnets)) {
                log.debug("populateSubnet: populationStatus is ABORTED");
                populationStatus = Status.ABORTED;
                log.warn("Failed to repopulate the rules for subnet.");
                return;
            }

            log.debug("populateSubnet: populationStatus is SUCCEEDED");
            populationStatus = Status.SUCCEEDED;
            log.info("Completed subnet population. Total # of rules pushed : {}",
                    rulePopulator.getCounter());
            return;

        } catch (Exception e) {
            log.error("populateSubnet thrown an exception: {}",
                      e.getMessage(), e);
            populationStatus = Status.ABORTED;
        } finally {
            statusLock.unlock();
        }
    }

    /**
     * Populates the routing rules or makes hash group changes according to the
     * route-path changes due to link failure, switch failure or link up. This
     * method should only be called for one of these three possible event-types.
     * Note that when a switch goes away, all of its links fail as well, but
     * this is handled as a single switch removal event.
     *
     * @param linkDown the single failed link, or null for other conditions such
     *            as link-up or a removed switch
     * @param linkUp the single link up, or null for other conditions such as
     *            link-down or a removed switch
     * @param switchDown the removed switch, or null for other conditions such
     *            as link-down or link-up
     * @param seenBefore true if this event is for a linkUp or linkDown for a
     *            seen link
     */
    // TODO This method should be refactored into three separated methods
    public void populateRoutingRulesForLinkStatusChange(Link linkDown, Link linkUp,
                                                        DeviceId switchDown, boolean seenBefore) {
        if (Stream.of(linkDown, linkUp, switchDown).filter(Objects::nonNull)
                .count() != 1) {
            log.warn("Only one event can be handled for link status change .. aborting");
            return;
        }

        lastRoutingChange = Instant.now();
        statusLock.lock();
        try {

            if (populationStatus == Status.STARTED) {
                log.warn("Previous rule population is not finished. Cannot"
                        + " proceeed with routingRules for Topology change");
                return;
            }

            // Take snapshots of the topology
            updatedEcmpSpgMap = new HashMap<>();
            Set<EdgePair> edgePairs = new HashSet<>();
            for (Device sw : srManager.deviceService.getDevices()) {
                EcmpShortestPathGraph ecmpSpgUpdated =
                        new EcmpShortestPathGraph(sw.id(), srManager);
                updatedEcmpSpgMap.put(sw.id(), ecmpSpgUpdated);
                Optional<DeviceId> pairDev = srManager.getPairDeviceId(sw.id());
                if (pairDev.isPresent()) {
                    // pairDev may not be available yet, but we still need to add
                    ecmpSpgUpdated = new EcmpShortestPathGraph(pairDev.get(), srManager);
                    updatedEcmpSpgMap.put(pairDev.get(), ecmpSpgUpdated);
                    edgePairs.add(new EdgePair(sw.id(), pairDev.get()));
                }
            }

            log.info("Starting to populate routing rules from Topology change");

            Set<ArrayList<DeviceId>> routeChanges;
            log.debug("populateRoutingRulesForLinkStatusChange: "
                    + "populationStatus is STARTED");
            populationStatus = Status.STARTED;
            rulePopulator.resetCounter(); //XXX maybe useful to have a rehash ctr
            boolean hashGroupsChanged = false;
            // try optimized re-routing
            if (linkDown == null) {
                // either a linkUp or a switchDown - compute all route changes by
                // comparing all routes of existing ECMP SPG to new ECMP SPG
                routeChanges = computeRouteChange(switchDown);

                // deal with linkUp of a seen-before link
                if (linkUp != null && seenBefore) {
                    // link previously seen before
                    // do hash-bucket changes instead of a re-route
                    processHashGroupChange(routeChanges, false, null);
                    // clear out routesChanges so a re-route is not attempted
                    routeChanges = ImmutableSet.of();
                    hashGroupsChanged = true;
                }
                // for a linkUp of a never-seen-before link
                // let it fall through to a reroute of the routeChanges

                //deal with switchDown
                if (switchDown != null) {
                    processHashGroupChange(routeChanges, true, switchDown);
                    // clear out routesChanges so a re-route is not attempted
                    routeChanges = ImmutableSet.of();
                    hashGroupsChanged = true;
                }
            } else {
                // link has gone down
                // Compare existing ECMP SPG only with the link that went down
                routeChanges = computeDamagedRoutes(linkDown);
                processHashGroupChange(routeChanges, true, null);
                // clear out routesChanges so a re-route is not attempted
                routeChanges = ImmutableSet.of();
                hashGroupsChanged = true;
            }

            if (routeChanges.isEmpty()) {
                if (hashGroupsChanged) {
                    log.info("Hash-groups changed for link status change");
                } else {
                    log.info("No re-route or re-hash attempted for the link"
                            + " status change");
                    updatedEcmpSpgMap.keySet().forEach(devId -> {
                        currentEcmpSpgMap.put(devId, updatedEcmpSpgMap.get(devId));
                        log.debug("Updating ECMPspg for remaining dev:{}", devId);
                    });
                }
                log.debug("populateRoutingRulesForLinkStatusChange: populationStatus is SUCCEEDED");
                populationStatus = Status.SUCCEEDED;
                return;
            }

            // reroute of routeChanges
            if (redoRouting(routeChanges, edgePairs, null)) {
                log.debug("populateRoutingRulesForLinkStatusChange: populationStatus is SUCCEEDED");
                populationStatus = Status.SUCCEEDED;
                log.info("Completed repopulation of rules for link-status change."
                        + " # of rules populated : {}", rulePopulator.getCounter());
                return;
            } else {
                log.debug("populateRoutingRulesForLinkStatusChange: populationStatus is ABORTED");
                populationStatus = Status.ABORTED;
                log.warn("Failed to repopulate the rules for link status change.");
                return;
            }
        } catch (Exception e) {
            log.error("populateRoutingRulesForLinkStatusChange thrown an exception: {}",
                      e.getMessage(), e);
            populationStatus = Status.ABORTED;
        } finally {
            statusLock.unlock();
        }
    }

    /**
     * Processes a set a route-path changes by reprogramming routing rules and
     * creating new hash-groups or editing them if necessary. This method also
     * determines the next-hops for the route-path from the src-switch (target)
     * of the path towards the dst-switch of the path.
     *
     * @param routeChanges a set of route-path changes, where each route-path is
     *                     a list with its first element the src-switch (target)
     *                     of the path, and the second element the dst-switch of
     *                     the path.
     * @param edgePairs a set of edge-switches that are paired by configuration
     * @param subnets  a set of prefixes that need to be populated in the routing
     *                 table of the target switch in the route-path. Can be null,
     *                 in which case all the prefixes belonging to the dst-switch
     *                 will be populated in the target switch
     * @return true if successful in repopulating all routes
     */
    private boolean redoRouting(Set<ArrayList<DeviceId>> routeChanges,
                                Set<EdgePair> edgePairs, Set<IpPrefix> subnets) {
        // first make every entry two-elements
        Set<ArrayList<DeviceId>> changedRoutes = new HashSet<>();
        for (ArrayList<DeviceId> route : routeChanges) {
            if (route.size() == 1) {
                DeviceId dstSw = route.get(0);
                EcmpShortestPathGraph ec = updatedEcmpSpgMap.get(dstSw);
                if (ec == null) {
                    log.warn("No graph found for {} .. aborting redoRouting", dstSw);
                    return false;
                }
                ec.getAllLearnedSwitchesAndVia().keySet().forEach(key -> {
                    ec.getAllLearnedSwitchesAndVia().get(key).keySet().forEach(target -> {
                        changedRoutes.add(Lists.newArrayList(target, dstSw));
                    });
                });
            } else {
                DeviceId targetSw = route.get(0);
                DeviceId dstSw = route.get(1);
                changedRoutes.add(Lists.newArrayList(targetSw, dstSw));
            }
        }

        // now process changedRoutes according to edgePairs
        if (!redoRoutingEdgePairs(edgePairs, subnets, changedRoutes)) {
            return false; //abort routing and fail fast
        }

        // whatever is left in changedRoutes is now processed for individual dsts.
        Set<DeviceId> updatedDevices = Sets.newHashSet();
        if (!redoRoutingIndividualDests(subnets, changedRoutes,
                                        updatedDevices)) {
            return false; //abort routing and fail fast
        }

        // update ecmpSPG for all edge-pairs
        for (EdgePair ep : edgePairs) {
            currentEcmpSpgMap.put(ep.dev1, updatedEcmpSpgMap.get(ep.dev1));
            currentEcmpSpgMap.put(ep.dev2, updatedEcmpSpgMap.get(ep.dev2));
            log.debug("Updating ECMPspg for edge-pair:{}-{}", ep.dev1, ep.dev2);
        }

        // here is where we update all devices not touched by this instance
        updatedEcmpSpgMap.keySet().stream()
            .filter(devId -> !edgePairs.stream().anyMatch(ep -> ep.includes(devId)))
            .filter(devId -> !updatedDevices.contains(devId))
            .forEach(devId -> {
                currentEcmpSpgMap.put(devId, updatedEcmpSpgMap.get(devId));
                log.debug("Updating ECMPspg for remaining dev:{}", devId);
            });
        return true;
    }

    /**
     * Programs targetSw in the changedRoutes for given prefixes reachable by
     * an edgePair. If no prefixes are given, the method will use configured
     * subnets/prefixes. If some configured subnets belong only to a specific
     * destination in the edgePair, then the target switch will be programmed
     * only to that destination.
     *
     * @param edgePairs set of edge-pairs for which target will be programmed
     * @param subnets a set of prefixes that need to be populated in the routing
     *                 table of the target switch in the changedRoutes. Can be null,
     *                 in which case all the configured prefixes belonging to the
     *                 paired switches will be populated in the target switch
     * @param changedRoutes a set of route-path changes, where each route-path is
     *                     a list with its first element the src-switch (target)
     *                     of the path, and the second element the dst-switch of
     *                     the path.
     * @return true if successful
     */
    private boolean redoRoutingEdgePairs(Set<EdgePair> edgePairs, Set<IpPrefix> subnets,
                                         Set<ArrayList<DeviceId>> changedRoutes) {
        for (EdgePair ep : edgePairs) {
            // temp store for a target's changedRoutes to this edge-pair
            Map<DeviceId, Set<ArrayList<DeviceId>>> targetRoutes = new HashMap<>();
            Iterator<ArrayList<DeviceId>> i = changedRoutes.iterator();
            while (i.hasNext()) {
                ArrayList<DeviceId> route = i.next();
                DeviceId dstSw = route.get(1);
                if (ep.includes(dstSw)) {
                    // routeChange for edge pair found
                    // sort by target iff target is edge and remove from changedRoutes
                    DeviceId targetSw = route.get(0);
                    try {
                        if (!srManager.deviceConfiguration.isEdgeDevice(targetSw)) {
                            continue;
                        }
                    } catch (DeviceConfigNotFoundException e) {
                        log.warn(e.getMessage() + "aborting redoRouting");
                        return false;
                    }
                    // route is from another edge to this edge-pair
                    if (targetRoutes.containsKey(targetSw)) {
                        targetRoutes.get(targetSw).add(route);
                    } else {
                        Set<ArrayList<DeviceId>> temp = new HashSet<>();
                        temp.add(route);
                        targetRoutes.put(targetSw, temp);
                    }
                    i.remove();
                }
            }
            // so now for this edgepair we have a per target set of routechanges
            // process target->edgePair route
            List<Future<Boolean>> futures = Lists.newArrayList();
            for (Map.Entry<DeviceId, Set<ArrayList<DeviceId>>> entry :
                            targetRoutes.entrySet()) {
                log.debug("* redoRoutingDstPair Target:{} -> edge-pair {}",
                          entry.getKey(), ep);
                futures.add(routePopulators.submit(new RedoRoutingEdgePair(entry.getKey(), entry.getValue(),
                                                                           subnets, ep)));
            }
            if (!checkJobs(futures)) {
                return false;
            }
            // if it gets here it has succeeded for all targets to this edge-pair
        }
        return true;
    }

    private final class RedoRoutingEdgePair implements PickyCallable<Boolean> {
        private DeviceId targetSw;
        private Set<ArrayList<DeviceId>> routes;
        private Set<IpPrefix> subnets;
        private EdgePair ep;

        /**
         * Builds a RedoRoutingEdgePair task which provides a result.
         *
         * @param targetSw the target switch
         * @param routes the changed routes
         * @param subnets the subnets
         * @param ep the edge pair
         */
        RedoRoutingEdgePair(DeviceId targetSw, Set<ArrayList<DeviceId>> routes,
                            Set<IpPrefix> subnets, EdgePair ep) {
            this.targetSw = targetSw;
            this.routes = routes;
            this.subnets = subnets;
            this.ep = ep;
        }

        @Override
        public Boolean call() throws Exception {
            return redoRoutingEdgePair();
        }

        @Override
        public int hint() {
            return targetSw.hashCode();
        }

        private boolean redoRoutingEdgePair() {
            Map<DeviceId, Set<DeviceId>> perDstNextHops = new HashMap<>();
            routes.forEach(route -> {
                Set<DeviceId> nhops = getNextHops(route.get(0), route.get(1));
                log.debug("route: target {} -> dst {} found with next-hops {}",
                          route.get(0), route.get(1), nhops);
                perDstNextHops.put(route.get(1), nhops);
            });

            List<Set<IpPrefix>> batchedSubnetDev1, batchedSubnetDev2;
            if (subnets != null) {
                batchedSubnetDev1 = Lists.<Set<IpPrefix>>newArrayList(Sets.newHashSet(subnets));
                batchedSubnetDev2 = Lists.<Set<IpPrefix>>newArrayList(Sets.newHashSet(subnets));
            } else {
                batchedSubnetDev1 = config.getBatchedSubnets(ep.dev1);
                batchedSubnetDev2 = config.getBatchedSubnets(ep.dev2);
            }
            List<Set<IpPrefix>> batchedSubnetBoth = Streams
                    .zip(batchedSubnetDev1.stream(), batchedSubnetDev2.stream(), (a, b) -> Sets.intersection(a, b))
                    .filter(set -> !set.isEmpty())
                    .collect(Collectors.toList());
            List<Set<IpPrefix>> batchedSubnetDev1Only = Streams
                    .zip(batchedSubnetDev1.stream(), batchedSubnetDev2.stream(), (a, b) -> Sets.difference(a, b))
                    .filter(set -> !set.isEmpty())
                    .collect(Collectors.toList());
            List<Set<IpPrefix>> batchedSubnetDev2Only = Streams
                    .zip(batchedSubnetDev1.stream(), batchedSubnetDev2.stream(), (a, b) -> Sets.difference(b, a))
                    .filter(set -> !set.isEmpty())
                    .collect(Collectors.toList());

            Set<DeviceId> nhDev1 = perDstNextHops.get(ep.dev1);
            Set<DeviceId> nhDev2 = perDstNextHops.get(ep.dev2);

            // handle routing to subnets common to edge-pair
            // only if the targetSw is not part of the edge-pair and there
            // exists a next hop to at least one of the devices in the edge-pair
            if (!ep.includes(targetSw)
                    && ((nhDev1 != null && !nhDev1.isEmpty()) || (nhDev2 != null && !nhDev2.isEmpty()))) {
                log.trace("getSubnets on both {} and {}: {}", ep.dev1, ep.dev2, batchedSubnetBoth);
                for (Set<IpPrefix> prefixes : batchedSubnetBoth) {
                    if (!populateEcmpRoutingRulePartial(targetSw, ep.dev1, ep.dev2,
                                                        perDstNextHops, prefixes)) {
                        return false; // abort everything and fail fast
                    }
                }

            }
            // handle routing to subnets that only belong to dev1 only if
            // a next-hop exists from the target to dev1
            if (!batchedSubnetDev1Only.isEmpty() &&
                    batchedSubnetDev1Only.stream().anyMatch(subnet -> !subnet.isEmpty()) &&
                    nhDev1 != null  && !nhDev1.isEmpty()) {
                Map<DeviceId, Set<DeviceId>> onlyDev1NextHops = new HashMap<>();
                onlyDev1NextHops.put(ep.dev1, nhDev1);
                log.trace("getSubnets on {} only: {}", ep.dev1, batchedSubnetDev1Only);
                for (Set<IpPrefix> prefixes : batchedSubnetDev1Only) {
                    if (!populateEcmpRoutingRulePartial(targetSw, ep.dev1, null,
                                                        onlyDev1NextHops, prefixes)) {
                        return false; // abort everything and fail fast
                    }
                }
            }
            // handle routing to subnets that only belong to dev2 only if
            // a next-hop exists from the target to dev2
            if (!batchedSubnetDev2Only.isEmpty() &&
                    batchedSubnetDev2Only.stream().anyMatch(subnet -> !subnet.isEmpty()) &&
                    nhDev2 != null && !nhDev2.isEmpty()) {
                Map<DeviceId, Set<DeviceId>> onlyDev2NextHops = new HashMap<>();
                onlyDev2NextHops.put(ep.dev2, nhDev2);
                log.trace("getSubnets on {} only: {}", ep.dev2, batchedSubnetDev2Only);
                for (Set<IpPrefix> prefixes : batchedSubnetDev2Only) {
                    if (!populateEcmpRoutingRulePartial(targetSw, ep.dev2, null,
                                                        onlyDev2NextHops, prefixes)) {
                        return false; // abort everything and fail fast
                    }
                }
            }
            return true;
        }
    }

    /**
     * Programs targetSw in the changedRoutes for given prefixes reachable by
     * a destination switch that is not part of an edge-pair.
     * If no prefixes are given, the method will use configured subnets/prefixes.
     *
     * @param subnets a set of prefixes that need to be populated in the routing
     *                 table of the target switch in the changedRoutes. Can be null,
     *                 in which case all the configured prefixes belonging to the
     *                 paired switches will be populated in the target switch
     * @param changedRoutes a set of route-path changes, where each route-path is
     *                     a list with its first element the src-switch (target)
     *                     of the path, and the second element the dst-switch of
     *                     the path.
     * @return true if successful
     */
    private boolean redoRoutingIndividualDests(Set<IpPrefix> subnets, Set<ArrayList<DeviceId>> changedRoutes,
                                               Set<DeviceId> updatedDevices) {
        // aggregate route-path changes for each dst device
        HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> routesBydevice =
                new HashMap<>();
        for (ArrayList<DeviceId> route: changedRoutes) {
            DeviceId dstSw = route.get(1);
            ArrayList<ArrayList<DeviceId>> deviceRoutes =
                    routesBydevice.get(dstSw);
            if (deviceRoutes == null) {
                deviceRoutes = new ArrayList<>();
                routesBydevice.put(dstSw, deviceRoutes);
            }
            deviceRoutes.add(route);
        }
        // iterate over the impacted devices
        for (DeviceId impactedDstDevice : routesBydevice.keySet()) {
            ArrayList<ArrayList<DeviceId>> deviceRoutes =
                    routesBydevice.get(impactedDstDevice);
            List<Future<Boolean>> futures = Lists.newArrayList();
            for (ArrayList<DeviceId> route: deviceRoutes) {
                log.debug("* redoRoutingIndiDst Target: {} -> dst: {}",
                          route.get(0), route.get(1));
                futures.add(routePopulators.submit(new RedoRoutingIndividualDest(subnets, route)));
            }
            // check the execution of each job
            if (!checkJobs(futures)) {
                return false;
            }
            //Only if all the flows for all impacted routes to a
            //specific target are pushed successfully, update the
            //ECMP graph for that target. Or else the next event
            //would not see any changes in the ECMP graphs.
            //In another case, the target switch has gone away, so
            //routes can't be installed. In that case, the current map
            //is updated here, without any flows being pushed.
            currentEcmpSpgMap.put(impactedDstDevice,
                                  updatedEcmpSpgMap.get(impactedDstDevice));
            updatedDevices.add(impactedDstDevice);
            log.debug("Updating ECMPspg for impacted dev:{}", impactedDstDevice);
        }
        return true;
    }

    private final class RedoRoutingIndividualDest implements PickyCallable<Boolean> {
        private DeviceId targetSw;
        private ArrayList<DeviceId> route;
        private Set<IpPrefix> subnets;

        /**
         * Builds a RedoRoutingIndividualDest task, which provides a result.
         *
         * @param subnets a set of prefixes
         * @param route a route-path change
         */
        RedoRoutingIndividualDest(Set<IpPrefix> subnets, ArrayList<DeviceId> route) {
            this.targetSw = route.get(0);
            this.route = route;
            this.subnets = subnets;
        }

        @Override
        public Boolean call() throws Exception {
            DeviceId dstSw = route.get(1); // same as impactedDstDevice
            Set<DeviceId> nextHops = getNextHops(targetSw, dstSw);
            if (nextHops.isEmpty()) {
                log.debug("Could not find next hop from target:{} --> dst {} "
                                  + "skipping this route", targetSw, dstSw);
                return true;
            }
            Map<DeviceId, Set<DeviceId>> nhops = new HashMap<>();
            nhops.put(dstSw, nextHops);
            if (!populateEcmpRoutingRulePartial(targetSw, dstSw, null, nhops,
                                                (subnets == null) ? Sets.newHashSet() : subnets)) {
                return false; // abort routing and fail fast
            }
            log.debug("Populating flow rules from target: {} to dst: {}"
                              + " is successful", targetSw, dstSw);
            return true;
        }

        @Override
        public int hint() {
            return targetSw.hashCode();
        }
    }

    /**
     * Populate ECMP rules for subnets from target to destination via nexthops.
     *
     * @param targetSw Device ID of target switch in which rules will be programmed
     * @param destSw1 Device ID of final destination switch to which the rules will forward
     * @param destSw2 Device ID of paired destination switch to which the rules will forward
     *                A null deviceId indicates packets should only be sent to destSw1
     * @param nextHops Map of a set of next hops per destSw
     * @param subnets Subnets to be populated. If empty, populate all configured subnets.
     * @return true if it succeeds in populating rules
     */ // refactor
    private boolean populateEcmpRoutingRulePartial(DeviceId targetSw, DeviceId destSw1, DeviceId destSw2,
                                                   Map<DeviceId, Set<DeviceId>> nextHops, Set<IpPrefix> subnets) {
        boolean result;
        // If both target switch and dest switch are edge routers, then set IP
        // rule for both subnet and router IP.
        boolean targetIsEdge;
        boolean dest1IsEdge;
        Ip4Address dest1RouterIpv4, dest2RouterIpv4 = null;
        Ip6Address dest1RouterIpv6, dest2RouterIpv6 = null;

        try {
            targetIsEdge = config.isEdgeDevice(targetSw);
            dest1IsEdge = config.isEdgeDevice(destSw1);
            dest1RouterIpv4 = config.getRouterIpv4(destSw1);
            dest1RouterIpv6 = config.getRouterIpv6(destSw1);
            if (destSw2 != null) {
                dest2RouterIpv4 = config.getRouterIpv4(destSw2);
                dest2RouterIpv6 = config.getRouterIpv6(destSw2);
            }
        } catch (DeviceConfigNotFoundException e) {
            log.warn(e.getMessage() + " Aborting populateEcmpRoutingRulePartial.");
            return false;
        }

        if (targetIsEdge && dest1IsEdge) {
            List<Set<IpPrefix>> batchedSubnets;
            if (subnets != null && !subnets.isEmpty()) {
                batchedSubnets = Lists.<Set<IpPrefix>>newArrayList(Sets.newHashSet(subnets));
            } else {
                batchedSubnets = config.getBatchedSubnets(destSw1);
            }
            // XXX - Rethink this - ignoring routerIPs in all other switches
            // even edge to edge switches
            /*subnets.add(dest1RouterIpv4.toIpPrefix());
            if (dest1RouterIpv6 != null) {
                subnets.add(dest1RouterIpv6.toIpPrefix());
            }
            if (destSw2 != null && dest2RouterIpv4 != null) {
                subnets.add(dest2RouterIpv4.toIpPrefix());
                if (dest2RouterIpv6 != null) {
                    subnets.add(dest2RouterIpv6.toIpPrefix());
                }
            }*/
            log.trace("getSubnets on {}: {}", destSw1, batchedSubnets);
            for (Set<IpPrefix> prefixes : batchedSubnets) {
                log.debug(". populateEcmpRoutingRulePartial in device {} towards {} {} "
                                + "for subnets {}", targetSw, destSw1,
                        (destSw2 != null) ? ("& " + destSw2) : "",
                        prefixes);
                if (!rulePopulator.populateIpRuleForSubnet(targetSw, prefixes, destSw1, destSw2, nextHops)) {
                    return false;
                }
            }
        }

        if (!targetIsEdge && dest1IsEdge) {
            // MPLS rules in all non-edge target devices. These rules are for
            // individual destinations, even if the dsts are part of edge-pairs.
            log.debug(". populateEcmpRoutingRulePartial in device{} towards {} for "
                    + "all MPLS rules", targetSw, destSw1);
            result = rulePopulator.populateMplsRule(targetSw, destSw1, nextHops.get(destSw1), dest1RouterIpv4);
            if (!result) {
                return false;
            }
            if (dest1RouterIpv6 != null) {
                int v4sid = 0, v6sid = 0;
                try {
                    v4sid = config.getIPv4SegmentId(destSw1);
                    v6sid = config.getIPv6SegmentId(destSw1);
                } catch (DeviceConfigNotFoundException e) {
                    log.warn(e.getMessage());
                }
                if (v4sid != v6sid) {
                    result = rulePopulator.populateMplsRule(targetSw, destSw1, nextHops.get(destSw1),
                                                            dest1RouterIpv6);
                    if (!result) {
                        return false;
                    }
                }
            }
        }

        if (!targetIsEdge && !dest1IsEdge) {
            // MPLS rules for inter-connected spines
            // can be merged with above if, left it here for clarity
            log.debug(". populateEcmpRoutingRulePartial in device{} towards {} for "
                              + "all MPLS rules", targetSw, destSw1);

            result = rulePopulator.populateMplsRule(targetSw, destSw1, nextHops.get(destSw1), dest1RouterIpv4);
            if (!result) {
                return false;
            }

            if (dest1RouterIpv6 != null) {
                int v4sid = 0, v6sid = 0;
                try {
                    v4sid = config.getIPv4SegmentId(destSw1);
                    v6sid = config.getIPv6SegmentId(destSw1);
                } catch (DeviceConfigNotFoundException e) {
                    log.warn(e.getMessage());
                }
                if (v4sid != v6sid) {
                    result = rulePopulator.populateMplsRule(targetSw, destSw1, nextHops.get(destSw1),
                                                            dest1RouterIpv6);
                    if (!result) {
                        return false;
                    }
                }
           }
        }

        // To save on ECMP groups
        // avoid MPLS rules in non-edge-devices to non-edge-devices
        // avoid MPLS transit rules in edge-devices
        // avoid loopback IP rules in edge-devices to non-edge-devices
        return true;
    }

    /**
     * Processes a set a route-path changes by editing hash groups.
     *
     * @param routeChanges a set of route-path changes, where each route-path is
     *                     a list with its first element the src-switch of the path
     *                     and the second element the dst-switch of the path.
     * @param linkOrSwitchFailed true if the route changes are for a failed
     *                           switch or linkDown event
     * @param failedSwitch the switchId if the route changes are for a failed switch,
     *                     otherwise null
     */
    private void processHashGroupChange(Set<ArrayList<DeviceId>> routeChanges,
                                        boolean linkOrSwitchFailed,
                                        DeviceId failedSwitch) {
        Set<ArrayList<DeviceId>> changedRoutes = new HashSet<>();
        // first, ensure each routeChanges entry has two elements
        for (ArrayList<DeviceId> route : routeChanges) {
            if (route.size() == 1) {
                // route-path changes are from everyone else to this switch
                DeviceId dstSw = route.get(0);
                srManager.deviceService.getAvailableDevices().forEach(sw -> {
                    if (!sw.id().equals(dstSw)) {
                        changedRoutes.add(Lists.newArrayList(sw.id(), dstSw));
                    }
                });
            } else {
                changedRoutes.add(route);
            }
        }
        boolean someFailed = false;
        Set<DeviceId> updatedDevices = Sets.newHashSet();
        for (ArrayList<DeviceId> route : changedRoutes) {
            DeviceId targetSw = route.get(0);
            DeviceId dstSw = route.get(1);
            if (linkOrSwitchFailed) {
                boolean success = fixHashGroupsForRoute(route, true);
                // it's possible that we cannot fix hash groups for a route
                // if the target switch has failed. Nevertheless the ecmp graph
                // for the impacted switch must still be updated.
                if (!success && failedSwitch != null && targetSw.equals(failedSwitch)) {
                    currentEcmpSpgMap.put(dstSw, updatedEcmpSpgMap.get(dstSw));
                    currentEcmpSpgMap.remove(targetSw);
                    log.debug("Updating ECMPspg for dst:{} removing failed switch "
                            + "target:{}", dstSw, targetSw);
                    updatedDevices.add(targetSw);
                    updatedDevices.add(dstSw);
                    continue;
                }
                //linkfailed - update both sides
                if (success) {
                    currentEcmpSpgMap.put(targetSw, updatedEcmpSpgMap.get(targetSw));
                    currentEcmpSpgMap.put(dstSw, updatedEcmpSpgMap.get(dstSw));
                    log.debug("Updating ECMPspg for dst:{} and target:{} for linkdown"
                            + " or switchdown", dstSw, targetSw);
                    updatedDevices.add(targetSw);
                    updatedDevices.add(dstSw);
                } else {
                    someFailed = true;
                }
            } else {
                //linkup of seen before link
                boolean success = fixHashGroupsForRoute(route, false);
                if (success) {
                    currentEcmpSpgMap.put(targetSw, updatedEcmpSpgMap.get(targetSw));
                    currentEcmpSpgMap.put(dstSw, updatedEcmpSpgMap.get(dstSw));
                    log.debug("Updating ECMPspg for target:{} and dst:{} for linkup",
                              targetSw, dstSw);
                    updatedDevices.add(targetSw);
                    updatedDevices.add(dstSw);
                } else {
                    someFailed = true;
                }
            }
        }
        if (!someFailed) {
            // here is where we update all devices not touched by this instance
            updatedEcmpSpgMap.keySet().stream()
                .filter(devId -> !updatedDevices.contains(devId))
                .forEach(devId -> {
                    currentEcmpSpgMap.put(devId, updatedEcmpSpgMap.get(devId));
                    log.debug("Updating ECMPspg for remaining dev:{}", devId);
            });
        }
    }

    /**
     * Edits hash groups in the src-switch (targetSw) of a route-path by
     * calling the groupHandler to either add or remove buckets in an existing
     * hash group.
     *
     * @param route a single list representing a route-path where the first element
     *                  is the src-switch (targetSw) of the route-path and the
     *                  second element is the dst-switch
     * @param revoke true if buckets in the hash-groups need to be removed;
     *              false if buckets in the hash-groups need to be added
     * @return true if the hash group editing is successful
     */
    private boolean fixHashGroupsForRoute(ArrayList<DeviceId> route,
                                          boolean revoke) {
        DeviceId targetSw = route.get(0);
        if (route.size() < 2) {
            log.warn("Cannot fixHashGroupsForRoute - no dstSw in route {}", route);
            return false;
        }
        DeviceId destSw = route.get(1);
        log.debug("* processing fixHashGroupsForRoute: Target {} -> Dest {}",
                  targetSw, destSw);
        // figure out the new next hops at the targetSw towards the destSw
        Set<DeviceId> nextHops = getNextHops(targetSw, destSw);
        // call group handler to change hash group at targetSw
        DefaultGroupHandler grpHandler = srManager.getGroupHandler(targetSw);
        if (grpHandler == null) {
            log.warn("Cannot find grouphandler for dev:{} .. aborting"
                    + " {} hash group buckets for route:{} ", targetSw,
                    (revoke) ? "revoke" : "repopulate", route);
            return false;
        }
        log.debug("{} hash-groups buckets For Route {} -> {} to new next-hops {}",
                  (revoke) ? "revoke" : "repopulating",
                  targetSw, destSw, nextHops);
        return (revoke) ? grpHandler.fixHashGroups(targetSw, nextHops,
                                                       destSw, true)
                            : grpHandler.fixHashGroups(targetSw, nextHops,
                                                       destSw, false);
    }

    /**
     * Start the flow rule population process if it was never started. The
     * process finishes successfully when all flow rules are set and stops with
     * ABORTED status when any groups required for flows is not set yet.
     */
    public void startPopulationProcess() {
        statusLock.lock();
        try {
            if (populationStatus == Status.IDLE
                    || populationStatus == Status.SUCCEEDED
                    || populationStatus == Status.ABORTED) {
                populateAllRoutingRules();
            } else {
                log.warn("Not initiating startPopulationProcess as populationStatus is {}",
                         populationStatus);
            }
        } finally {
            statusLock.unlock();
        }
    }

    /**
     * Revoke rules of given subnet in all edge switches.
     *
     * @param subnets subnet being removed
     * @return true if succeed
     */
    protected boolean revokeSubnet(Set<IpPrefix> subnets) {
        DeviceId targetSw;
        List<Future<Boolean>> futures = Lists.newArrayList();
        for (Device sw : srManager.deviceService.getAvailableDevices()) {
            targetSw = sw.id();
            if (shouldProgram(targetSw)) {
                futures.add(routePopulators.submit(new RevokeSubnet(targetSw, subnets)));
            } else {
                futures.add(CompletableFuture.completedFuture(true));
            }
        }
        // check the execution of each job
        return checkJobs(futures);
    }

    private final class RevokeSubnet implements PickyCallable<Boolean> {
        private DeviceId targetSw;
        private Set<IpPrefix> subnets;

        /**
         * Builds a RevokeSubnet task, which provides a result.
         *
         * @param subnets a set of prefixes
         * @param targetSw target switch
         */
        RevokeSubnet(DeviceId targetSw, Set<IpPrefix> subnets) {
            this.targetSw = targetSw;
            this.subnets = subnets;
        }

        @Override
        public Boolean call() throws Exception {
            return srManager.routingRulePopulator.revokeIpRuleForSubnet(targetSw, subnets);
        }

        @Override
        public int hint() {
            return targetSw.hashCode();
        }
    }

    /**
     * Populates IP rules for a route that has direct connection to the switch
     * if the current instance is the master of the switch.
     *
     * @param deviceId device ID of the device that next hop attaches to
     * @param prefix IP prefix of the route
     * @param hostMac MAC address of the next hop
     * @param hostVlanId Vlan ID of the nexthop
     * @param outPort port where the next hop attaches to
     * @param directHost host is of type direct or indirect
     */
    void populateRoute(DeviceId deviceId, IpPrefix prefix,
                       MacAddress hostMac, VlanId hostVlanId, PortNumber outPort, boolean directHost) {
        if (shouldProgram(deviceId)) {
            srManager.routingRulePopulator.populateRoute(deviceId, prefix, hostMac, hostVlanId, outPort, directHost);
        }
    }

    /**
     * Removes IP rules for a route when the next hop is gone.
     * if the current instance is the master of the switch.
     *
     * @param deviceId device ID of the device that next hop attaches to
     * @param prefix IP prefix of the route
     * @param hostMac MAC address of the next hop
     * @param hostVlanId Vlan ID of the nexthop
     * @param outPort port that next hop attaches to
     * @param directHost host is of type direct or indirect
     */
    void revokeRoute(DeviceId deviceId, IpPrefix prefix,
                     MacAddress hostMac, VlanId hostVlanId, PortNumber outPort, boolean directHost) {
        if (shouldProgram(deviceId)) {
            srManager.routingRulePopulator.revokeRoute(deviceId, prefix, hostMac, hostVlanId, outPort, directHost);
        }
    }

    void populateBridging(DeviceId deviceId, PortNumber port, MacAddress mac, VlanId vlanId) {
        if (shouldProgram(deviceId)) {
            srManager.routingRulePopulator.populateBridging(deviceId, port, mac, vlanId);
        }
    }

    void revokeBridging(DeviceId deviceId, PortNumber port, MacAddress mac, VlanId vlanId) {
        if (shouldProgram(deviceId)) {
            srManager.routingRulePopulator.revokeBridging(deviceId, port, mac, vlanId);
        }
    }

    void updateBridging(DeviceId deviceId, PortNumber portNum, MacAddress hostMac,
                        VlanId vlanId, boolean popVlan, boolean install) {
        if (shouldProgram(deviceId)) {
            srManager.routingRulePopulator.updateBridging(deviceId, portNum, hostMac, vlanId, popVlan, install);
        }
    }

    void updateFwdObj(DeviceId deviceId, PortNumber portNumber, IpPrefix prefix, MacAddress hostMac,
                      VlanId vlanId, boolean popVlan, boolean install) {
        if (shouldProgram(deviceId)) {
            srManager.routingRulePopulator.updateFwdObj(deviceId, portNumber, prefix, hostMac,
                    vlanId, popVlan, install);
        }
    }

    /**
     * Populates IP rules for a route when the next hop is double-tagged.
     *
     * @param deviceId  device ID that next hop attaches to
     * @param prefix    IP prefix of the route
     * @param hostMac   MAC address of the next hop
     * @param innerVlan Inner Vlan ID of the next hop
     * @param outerVlan Outer Vlan ID of the next hop
     * @param outerTpid Outer TPID of the next hop
     * @param outPort   port that the next hop attaches to
     */
    void populateDoubleTaggedRoute(DeviceId deviceId, IpPrefix prefix, MacAddress hostMac, VlanId innerVlan,
                                   VlanId outerVlan, EthType outerTpid, PortNumber outPort) {
        if (srManager.mastershipService.isLocalMaster(deviceId)) {
            srManager.routingRulePopulator.populateDoubleTaggedRoute(
                    deviceId, prefix, hostMac, innerVlan, outerVlan, outerTpid, outPort);
            srManager.routingRulePopulator.processDoubleTaggedFilter(
                    deviceId, outPort, outerVlan, innerVlan, true);
        }
    }

    /**
     * Revokes IP rules for a route when the next hop is double-tagged.
     *
     * @param deviceId  device ID that next hop attaches to
     * @param prefix    IP prefix of the route
     * @param hostMac   MAC address of the next hop
     * @param innerVlan Inner Vlan ID of the next hop
     * @param outerVlan Outer Vlan ID of the next hop
     * @param outerTpid Outer TPID of the next hop
     * @param outPort   port that the next hop attaches to
     */
    void revokeDoubleTaggedRoute(DeviceId deviceId, IpPrefix prefix, MacAddress hostMac, VlanId innerVlan,
                                 VlanId outerVlan, EthType outerTpid, PortNumber outPort) {
        // Revoke route either if this node have the mastership (when device is available) or
        // if this node is the leader (even when device is unavailable)
        if (!srManager.mastershipService.isLocalMaster(deviceId)) {
            if (srManager.deviceService.isAvailable(deviceId)) {
                // Master node will revoke specified rule.
                log.debug("This node is not a master for {}, stop revoking route.", deviceId);
                return;
            }

            // isLocalMaster will return false when the device is unavailable.
            // Verify if this node is the leader in that case.
            NodeId leader = srManager.leadershipService.runForLeadership(
                    deviceId.toString()).leaderNodeId();
            if (!srManager.clusterService.getLocalNode().id().equals(leader)) {
                // Leader node will revoke specified rule.
                log.debug("This node is not a master for {}, stop revoking route.", deviceId);
                return;
            }
        }

        srManager.routingRulePopulator.revokeDoubleTaggedRoute(deviceId, prefix, hostMac,
                innerVlan, outerVlan, outerTpid, outPort);
        srManager.routingRulePopulator.processDoubleTaggedFilter(deviceId, outPort, outerVlan, innerVlan, false);
    }


    /**
     * Remove ECMP graph entry for the given device. Typically called when
     * device is no longer available.
     *
     * @param deviceId the device for which graphs need to be purged
     */
    void purgeEcmpGraph(DeviceId deviceId) {
        statusLock.lock();
        try {
            if (populationStatus == Status.STARTED) {
                log.warn("Previous rule population is not finished. Cannot"
                        + " proceeed with purgeEcmpGraph for {}", deviceId);
                return;
            }
            log.debug("Updating ECMPspg for unavailable dev:{}", deviceId);
            currentEcmpSpgMap.remove(deviceId);
            if (updatedEcmpSpgMap != null) {
                updatedEcmpSpgMap.remove(deviceId);
            }
        } finally {
            statusLock.unlock();
        }
    }

    /**
     * Attempts a full reroute of route-paths if topology has changed relatively
     * close to a mastership change event. Does not do a reroute if mastership
     * change is due to reasons other than a ONOS cluster event - for example a
     * call to balance-masters, or a switch up/down event.
     *
     * @param devId the device identifier for which mastership has changed
     * @param me the mastership event
     */
    void checkFullRerouteForMasterChange(DeviceId devId, MastershipEvent me) {
        // give small delay to absorb mastership events that are caused by
        // device that has disconnected from cluster
        executorServiceMstChg.schedule(new MasterChange(devId, me),
                                       MASTER_CHANGE_DELAY, TimeUnit.MILLISECONDS);
    }

    protected final class MasterChange implements Runnable {
        private DeviceId devId;
        private MastershipEvent me;
        private static final long CLUSTER_EVENT_THRESHOLD = 4500; // ms
        private static final long DEVICE_EVENT_THRESHOLD = 2000; // ms
        private static final long EDGE_PORT_EVENT_THRESHOLD = 10000; //ms
        private static final long FULL_REROUTE_THRESHOLD = 10000; // ms

        MasterChange(DeviceId devId, MastershipEvent me) {
            this.devId = devId;
            this.me = me;
        }

        @Override
        public void run() {
            long lce = srManager.clusterListener.timeSinceLastClusterEvent();
            boolean clusterEvent = lce < CLUSTER_EVENT_THRESHOLD;

            // ignore event for lost switch if cluster event hasn't happened -
            // device down event will handle it
            if ((me.roleInfo().master() == null
                    || !srManager.deviceService.isAvailable(devId))
                    && !clusterEvent) {
                log.debug("Full reroute not required for lost device: {}/{} "
                        + "clusterEvent/timeSince: {}/{}",
                          devId, me.roleInfo(), clusterEvent, lce);
                return;
            }

            long update = srManager.deviceService.getLastUpdatedInstant(devId);
            long lde = Instant.now().toEpochMilli() - update;
            boolean deviceEvent = lde < DEVICE_EVENT_THRESHOLD;

            // ignore event for recently connected switch if cluster event hasn't
            // happened - link up events will handle it
            if (srManager.deviceService.isAvailable(devId) && deviceEvent
                    && !clusterEvent) {
                log.debug("Full reroute not required for recently available"
                        + " device: {}/{} deviceEvent/timeSince: {}/{} "
                        + "clusterEvent/timeSince: {}/{}",
                        devId, me.roleInfo(), deviceEvent, lde, clusterEvent, lce);
                return;
            }

            long lepe = Instant.now().toEpochMilli()
                    - srManager.lastEdgePortEvent.toEpochMilli();
            boolean edgePortEvent = lepe < EDGE_PORT_EVENT_THRESHOLD;

            // if it gets here, then mastership change is likely due to onos
            // instance failure, or network partition in onos cluster
            // normally a mastership change like this does not require re-programming
            // but if topology changes happen at the same time then we may miss events
            if (!isRoutingStable() && clusterEvent) {
                log.warn("Mastership changed for dev: {}/{} while programming route-paths "
                        + "due to clusterEvent {} ms ago .. attempting full reroute",
                         devId, me.roleInfo(), lce);
                if (srManager.mastershipService.isLocalMaster(devId)) {
                    // old master could have died when populating filters
                    populatePortAddressingRules(devId);
                }
                // old master could have died when creating groups
                // XXX right now we have no fine-grained way to only make changes
                // for the route paths affected by this device. Thus we do a
                // full reroute after purging all hash groups. We also try to do
                // it only once, irrespective of the number of devices
                // that changed mastership when their master instance died.
                long lfrr = Instant.now().toEpochMilli() - lastFullReroute.toEpochMilli();
                boolean doFullReroute = lfrr > FULL_REROUTE_THRESHOLD;
                if (doFullReroute) {
                    lastFullReroute = Instant.now();
                    for (Device dev : srManager.deviceService.getDevices()) {
                        if (shouldProgram(dev.id())) {
                            srManager.purgeHashedNextObjectiveStore(dev.id());
                        }
                    }
                    // give small delay to ensure entire store is purged
                    executorServiceFRR.schedule(new FullRerouteAfterPurge(),
                                                PURGE_DELAY,
                                                TimeUnit.MILLISECONDS);
                } else {
                    log.warn("Full reroute attempted {} ms ago .. skipping", lfrr);
                }

            } else if (edgePortEvent && clusterEvent) {
                log.warn("Mastership changed for dev: {}/{} due to clusterEvent {} ms ago "
                        + "while edge-port event happened {} ms ago "
                        + " .. reprogramming all edge-ports",
                         devId, me.roleInfo(), lce, lepe);
                if (shouldProgram(devId)) {
                    srManager.deviceService.getPorts(devId).stream()
                        .filter(p -> srManager.interfaceService
                                .isConfigured(new ConnectPoint(devId, p.number())))
                        .forEach(p -> srManager.processPortUpdated(devId, p));
                }

            } else {
                log.debug("Stable route-paths .. full reroute not attempted for "
                        + "mastership change {}/{} deviceEvent/timeSince: {}/{} "
                        + "clusterEvent/timeSince: {}/{}", devId, me.roleInfo(),
                        deviceEvent, lde, clusterEvent, lce);
            }
        }
    }

    /**
     * Performs a full reroute of routing rules in all the switches. Assumes
     * caller has purged hash groups from the nextObjective store, otherwise
     * re-uses ones available in the store.
     */
    protected final class FullRerouteAfterPurge implements Runnable {
        @Override
        public void run() {
            populateAllRoutingRules();
        }
    }


    //////////////////////////////////////
    //  Routing helper methods and classes
    //////////////////////////////////////

    /**
     * Computes set of affected routes due to failed link. Assumes previous ecmp
     * shortest-path graph exists for a switch in order to compute affected
     * routes. If such a graph does not exist, the method returns null.
     *
     * @param linkFail the failed link
     * @return the set of affected routes which may be empty if no routes were
     *         affected
     */
    private Set<ArrayList<DeviceId>> computeDamagedRoutes(Link linkFail) {
        Set<ArrayList<DeviceId>> routes = new HashSet<>();

        for (Device sw : srManager.deviceService.getDevices()) {
            log.debug("Computing the impacted routes for device {} due to link fail",
                      sw.id());
            if (!shouldProgram(sw.id())) {
                lastProgrammed.remove(sw.id());
                continue;
            }
            for (DeviceId rootSw : deviceAndItsPair(sw.id())) {
                // check for mastership change since last run
                if (!lastProgrammed.contains(sw.id())) {
                    log.warn("New responsibility for this node to program dev:{}"
                            + " ... nuking current ECMPspg", sw.id());
                    currentEcmpSpgMap.remove(sw.id());
                }
                lastProgrammed.add(sw.id());

                EcmpShortestPathGraph ecmpSpg = currentEcmpSpgMap.get(rootSw);
                if (ecmpSpg == null) {
                    log.warn("No existing ECMP graph for switch {}. Assuming "
                            + "all route-paths have changed towards it.", rootSw);
                    for (DeviceId targetSw : srManager.deviceConfiguration.getRouters()) {
                        if (targetSw.equals(rootSw)) {
                            continue;
                        }
                        routes.add(Lists.newArrayList(targetSw, rootSw));
                        log.debug("Impacted route:{}->{}", targetSw, rootSw);
                    }
                    continue;
                }

                if (log.isDebugEnabled()) {
                    log.debug("Root switch: {}", rootSw);
                    log.debug("  Current/Existing SPG: {}", ecmpSpg);
                    log.debug("       New/Updated SPG: {}", updatedEcmpSpgMap.get(rootSw));
                }
                HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>>
                    switchVia = ecmpSpg.getAllLearnedSwitchesAndVia();
                // figure out if the broken link affected any route-paths in this graph
                for (Integer itrIdx : switchVia.keySet()) {
                    log.trace("Current/Exiting SPG Iterindex# {}", itrIdx);
                    HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> swViaMap =
                            switchVia.get(itrIdx);
                    for (DeviceId targetSw : swViaMap.keySet()) {
                        log.trace("TargetSwitch {} --> RootSwitch {}",
                                  targetSw, rootSw);
                        for (ArrayList<DeviceId> via : swViaMap.get(targetSw)) {
                            log.trace(" Via:");
                            via.forEach(e -> log.trace("  {}", e));
                        }
                        Set<ArrayList<DeviceId>> subLinks =
                                computeLinks(targetSw, rootSw, swViaMap);
                        for (ArrayList<DeviceId> alink: subLinks) {
                            if ((alink.get(0).equals(linkFail.src().deviceId()) &&
                                    alink.get(1).equals(linkFail.dst().deviceId()))
                                    ||
                                    (alink.get(0).equals(linkFail.dst().deviceId()) &&
                                         alink.get(1).equals(linkFail.src().deviceId()))) {
                                log.debug("Impacted route:{}->{}", targetSw, rootSw);
                                ArrayList<DeviceId> aRoute = new ArrayList<>();
                                aRoute.add(targetSw); // switch with rules to populate
                                aRoute.add(rootSw); // towards this destination
                                routes.add(aRoute);
                                break;
                            }
                        }
                    }
                }

            }

        }
        return routes;
    }

    /**
     * Computes set of affected routes due to new links or failed switches.
     *
     * @param failedSwitch deviceId of failed switch if any
     * @return the set of affected routes which may be empty if no routes were
     *         affected
     */
    private Set<ArrayList<DeviceId>> computeRouteChange(DeviceId failedSwitch) {
        ImmutableSet.Builder<ArrayList<DeviceId>> changedRtBldr =
                ImmutableSet.builder();

        for (Device sw : srManager.deviceService.getDevices()) {
            log.debug("Computing the impacted routes for device {}", sw.id());
            if (!shouldProgram(sw.id())) {
                lastProgrammed.remove(sw.id());
                continue;
            }
            for (DeviceId rootSw : deviceAndItsPair(sw.id())) {
                if (log.isTraceEnabled()) {
                    log.trace("Device links for dev: {}", rootSw);
                    for (Link link: srManager.linkService.getDeviceLinks(rootSw)) {
                        log.trace("{} -> {} ", link.src().deviceId(),
                                  link.dst().deviceId());
                    }
                }
                // check for mastership change since last run
                if (!lastProgrammed.contains(sw.id())) {
                    log.warn("New responsibility for this node to program dev:{}"
                            + " ... nuking current ECMPspg", sw.id());
                    currentEcmpSpgMap.remove(sw.id());
                }
                lastProgrammed.add(sw.id());
                EcmpShortestPathGraph currEcmpSpg = currentEcmpSpgMap.get(rootSw);
                if (currEcmpSpg == null) {
                    log.debug("No existing ECMP graph for device {}.. adding self as "
                            + "changed route", rootSw);
                    changedRtBldr.add(Lists.newArrayList(rootSw));
                    continue;
                }
                EcmpShortestPathGraph newEcmpSpg = updatedEcmpSpgMap.get(rootSw);
                if (newEcmpSpg == null) {
                    log.warn("Cannot find updated ECMP graph for dev:{}", rootSw);
                    continue;
                }
                if (log.isDebugEnabled()) {
                    log.debug("Root switch: {}", rootSw);
                    log.debug("  Current/Existing SPG: {}", currEcmpSpg);
                    log.debug("       New/Updated SPG: {}", newEcmpSpg);
                }
                // first use the updated/new map to compare to current/existing map
                // as new links may have come up
                changedRtBldr.addAll(compareGraphs(newEcmpSpg, currEcmpSpg, rootSw));
                // then use the current/existing map to compare to updated/new map
                // as switch may have been removed
                changedRtBldr.addAll(compareGraphs(currEcmpSpg, newEcmpSpg, rootSw));
            }
        }

        // handle clearing state for a failed switch in case the switch does
        // not have a pair, or the pair is not available
        if (failedSwitch != null) {
            Optional<DeviceId> pairDev = srManager.getPairDeviceId(failedSwitch);
            if (!pairDev.isPresent() || !srManager.deviceService.isAvailable(pairDev.get())) {
                log.debug("Proxy Route changes to downed Sw:{}", failedSwitch);
                srManager.deviceService.getDevices().forEach(dev -> {
                    if (!dev.id().equals(failedSwitch) &&
                            srManager.mastershipService.isLocalMaster(dev.id())) {
                        log.debug(" : {}", dev.id());
                        changedRtBldr.add(Lists.newArrayList(dev.id(), failedSwitch));
                    }
                });
            }
        }

        Set<ArrayList<DeviceId>> changedRoutes = changedRtBldr.build();
        for (ArrayList<DeviceId> route: changedRoutes) {
            log.debug("Route changes Target -> Root");
            if (route.size() == 1) {
                log.debug(" : all -> {}", route.get(0));
            } else {
                log.debug(" : {} -> {}", route.get(0), route.get(1));
            }
        }
        return changedRoutes;
    }

    /**
     * For the root switch, searches all the target nodes reachable in the base
     * graph, and compares paths to the ones in the comp graph.
     *
     * @param base the graph that is indexed for all reachable target nodes
     *             from the root node
     * @param comp the graph that the base graph is compared to
     * @param rootSw  both ecmp graphs are calculated for the root node
     * @return all the routes that have changed in the base graph
     */
    private Set<ArrayList<DeviceId>> compareGraphs(EcmpShortestPathGraph base,
                                                   EcmpShortestPathGraph comp,
                                                   DeviceId rootSw) {
        ImmutableSet.Builder<ArrayList<DeviceId>> changedRoutesBuilder =
                ImmutableSet.builder();
        HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> baseMap =
                base.getAllLearnedSwitchesAndVia();
        HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> compMap =
                comp.getAllLearnedSwitchesAndVia();
        for (Integer itrIdx : baseMap.keySet()) {
            HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> baseViaMap =
                    baseMap.get(itrIdx);
            for (DeviceId targetSw : baseViaMap.keySet()) {
                ArrayList<ArrayList<DeviceId>> basePath = baseViaMap.get(targetSw);
                ArrayList<ArrayList<DeviceId>> compPath = getVia(compMap, targetSw);
                if ((compPath == null) || !basePath.equals(compPath)) {
                    log.trace("Impacted route:{} -> {}", targetSw, rootSw);
                    ArrayList<DeviceId> route = new ArrayList<>();
                    route.add(targetSw); // switch with rules to populate
                    route.add(rootSw); // towards this destination
                    changedRoutesBuilder.add(route);
                }
            }
        }
        return changedRoutesBuilder.build();
    }

    /**
     * Returns the ECMP paths traversed to reach the target switch.
     *
     * @param switchVia a per-iteration view of the ECMP graph for a root switch
     * @param targetSw the switch to reach from the root switch
     * @return the nodes traversed on ECMP paths to the target switch
     */
    private ArrayList<ArrayList<DeviceId>> getVia(HashMap<Integer, HashMap<DeviceId,
            ArrayList<ArrayList<DeviceId>>>> switchVia, DeviceId targetSw) {
        for (Integer itrIdx : switchVia.keySet()) {
            HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> swViaMap =
                    switchVia.get(itrIdx);
            if (swViaMap.get(targetSw) == null) {
                continue;
            } else {
                return swViaMap.get(targetSw);
            }
        }

        return null;
    }

    /**
     * Utility method to break down a path from src to dst device into a collection
     * of links.
     *
     * @param src src device of the path
     * @param dst dst device of the path
     * @param viaMap path taken from src to dst device
     * @return collection of links in the path
     */
    private Set<ArrayList<DeviceId>> computeLinks(DeviceId src,
                                                  DeviceId dst,
                       HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> viaMap) {
        Set<ArrayList<DeviceId>> subLinks = Sets.newHashSet();
        for (ArrayList<DeviceId> via : viaMap.get(src)) {
            DeviceId linkSrc = src;
            DeviceId linkDst = dst;
            for (DeviceId viaDevice: via) {
                ArrayList<DeviceId> link = new ArrayList<>();
                linkDst = viaDevice;
                link.add(linkSrc);
                link.add(linkDst);
                subLinks.add(link);
                linkSrc = viaDevice;
            }
            ArrayList<DeviceId> link = new ArrayList<>();
            link.add(linkSrc);
            link.add(dst);
            subLinks.add(link);
        }

        return subLinks;
    }

    /**
     * Determines whether this controller instance should program the
     * given {@code deviceId}, based on mastership and pairDeviceId if one exists.
     * <p>
     * Once an instance is elected, it will be the only instance responsible for programming
     * both devices in the pair until it goes down.
     *
     * @param deviceId device identifier to consider for routing
     * @return true if current instance should handle the routing for given device
     */
    boolean shouldProgram(DeviceId deviceId) {
        Boolean cached = shouldProgramCache.get(deviceId);
        if (cached != null) {
            log.debug("shouldProgram dev:{} cached:{}", deviceId, cached);
            return cached;
        }

        Optional<DeviceId> pairDeviceId = srManager.getPairDeviceId(deviceId);

        NodeId currentNodeId = srManager.clusterService.getLocalNode().id();
        NodeId masterNodeId = srManager.mastershipService.getMasterFor(deviceId);
        Optional<NodeId> pairMasterNodeId = pairDeviceId.map(srManager.mastershipService::getMasterFor);
        log.debug("Evaluate shouldProgram {}/pair={}. currentNodeId={}, master={}, pairMaster={}",
                deviceId, pairDeviceId, currentNodeId, masterNodeId, pairMasterNodeId);

        // No pair device configured. Only handle when current instance is the master of the device
        if (!pairDeviceId.isPresent()) {
            log.debug("No pair device. currentNodeId={}, master={}", currentNodeId, masterNodeId);
            return currentNodeId.equals(masterNodeId);
        }

        // Should not handle if current instance is not the master of either switch
        if (!currentNodeId.equals(masterNodeId) &&
                !(pairMasterNodeId.isPresent() && currentNodeId.equals(pairMasterNodeId.get()))) {
            log.debug("Current nodeId {} is neither the master of target device {} nor pair device {}",
                    currentNodeId, deviceId, pairDeviceId);
            return false;
        }

        Set<DeviceId> key = Sets.newHashSet(deviceId, pairDeviceId.get());

        NodeId king = shouldProgram.compute(key, ((k, v) -> {
            if (v == null) {
                // There is no value in the map. Elect a node
                return elect(Lists.newArrayList(masterNodeId, pairMasterNodeId.orElse(null)));
            } else {
                if (v.equals(masterNodeId) || v.equals(pairMasterNodeId.orElse(null))) {
                    // Use the node in the map if it is still alive and is a master of any of the two switches
                    return v;
                } else {
                    // Previously elected node is no longer the master of either switch. Re-elect a node.
                    return elect(Lists.newArrayList(masterNodeId, pairMasterNodeId.orElse(null)));
                }
            }
        }));

        if (king != null) {
            log.debug("{} is king, should handle routing for {}/pair={}", king, deviceId, pairDeviceId);
            shouldProgramCache.put(deviceId, king.equals(currentNodeId));
            return king.equals(currentNodeId);
        } else {
            log.error("Fail to elect a king for {}/pair={}. Abort.", deviceId, pairDeviceId);
            shouldProgramCache.remove(deviceId);
            return false;
        }
    }

    /**
     * Elects a node who should take responsibility of programming devices.
     * @param nodeIds list of candidate node ID
     *
     * @return NodeId of the node that gets elected, or null if none of the node can be elected
     */
    private NodeId elect(List<NodeId> nodeIds) {
        // Remove all null elements. This could happen when some device has no master
        nodeIds.removeAll(Collections.singleton(null));
        nodeIds.sort(null);
        return nodeIds.size() == 0 ? null : nodeIds.get(0);
    }

    void invalidateShouldProgramCache(DeviceId deviceId) {
        shouldProgramCache.remove(deviceId);
    }

    /**
     * Returns a set of device ID, containing given device and its pair device if exist.
     *
     * @param deviceId Device ID
     * @return a set of device ID, containing given device and its pair device if exist.
     */
    private Set<DeviceId> deviceAndItsPair(DeviceId deviceId) {
        Set<DeviceId> ret = Sets.newHashSet(deviceId);
        srManager.getPairDeviceId(deviceId).ifPresent(ret::add);
        return ret;
    }

    /**
     * Returns the set of deviceIds which are the next hops from the targetSw
     * to the dstSw according to the latest ECMP spg.
     *
     * @param targetSw the switch for which the next-hops are desired
     * @param dstSw the switch to which the next-hops lead to from the targetSw
     * @return set of next hop deviceIds, could be empty if no next hops are found
     */
    private Set<DeviceId> getNextHops(DeviceId targetSw, DeviceId dstSw) {
        boolean targetIsEdge = false;
        try {
            targetIsEdge = srManager.deviceConfiguration.isEdgeDevice(targetSw);
        } catch (DeviceConfigNotFoundException e) {
            log.warn(e.getMessage() + "Cannot determine if targetIsEdge {}.. "
                    + "continuing to getNextHops", targetSw);
        }

        EcmpShortestPathGraph ecmpSpg = updatedEcmpSpgMap.get(dstSw);
        if (ecmpSpg == null) {
            log.debug("No ecmpSpg found for dstSw: {}", dstSw);
            return ImmutableSet.of();
        }
        HashMap<Integer,
            HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia =
                ecmpSpg.getAllLearnedSwitchesAndVia();
        for (Integer itrIdx : switchVia.keySet()) {
            HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> swViaMap =
                    switchVia.get(itrIdx);
            for (DeviceId target : swViaMap.keySet()) {
                if (!target.equals(targetSw)) {
                    continue;
                }
                // optimization for spines to not use leaves to get
                // to a spine or other leaves. Also leaves should not use other
                // leaves to get to the destination
                if ((!targetIsEdge && itrIdx > 1) || targetIsEdge) {
                    boolean pathdevIsEdge = false;
                    for (ArrayList<DeviceId> via : swViaMap.get(targetSw)) {
                        log.debug("Evaluating next-hop in path: {}", via);
                        for (DeviceId pathdev : via) {
                            try {
                                pathdevIsEdge = srManager.deviceConfiguration
                                        .isEdgeDevice(pathdev);
                            } catch (DeviceConfigNotFoundException e) {
                                log.warn(e.getMessage());
                            }
                            if (pathdevIsEdge) {
                                log.debug("Avoiding {} hop path for targetSw:{}"
                                        + " --> dstSw:{} which goes through an edge"
                                        + " device {} in path {}", itrIdx,
                                          targetSw, dstSw, pathdev, via);
                                return ImmutableSet.of();
                            }
                        }
                    }
                }
                Set<DeviceId> nextHops = new HashSet<>();
                for (ArrayList<DeviceId> via : swViaMap.get(targetSw)) {
                    if (via.isEmpty()) {
                        // the dstSw is the next-hop from the targetSw
                        nextHops.add(dstSw);
                    } else {
                        // first elem is next-hop in each ECMP path
                        nextHops.add(via.get(0));
                    }
                }
                log.debug("target {} --> dst: {} has next-hops:{}", targetSw,
                          dstSw, nextHops);
                return nextHops;
            }
        }
        log.debug("No next hops found for target:{} --> dst: {}", targetSw, dstSw);
        return ImmutableSet.of(); //no next-hops found
    }

    //////////////////////////////////////
    //  Filtering rule creation
    //////////////////////////////////////

    /**
     * Populates filtering rules for port, and punting rules
     * for gateway IPs, loopback IPs and arp/ndp traffic.
     * Should only be called by the master instance for this device/port.
     *
     * @param deviceId Switch ID to set the rules
     */
    void populatePortAddressingRules(DeviceId deviceId) {
        // Although device is added, sometimes device store does not have the
        // ports for this device yet. It results in missing filtering rules in the
        // switch. We will attempt it a few times. If it still does not work,
        // user can manually repopulate using CLI command sr-reroute-network
        PortFilterInfo firstRun = rulePopulator.populateVlanMacFilters(deviceId);
        if (firstRun == null) {
            firstRun = new PortFilterInfo(0, 0, 0);
        }
        executorService.schedule(new RetryFilters(deviceId, firstRun),
                                 RETRY_INTERVAL_MS, TimeUnit.MILLISECONDS);
    }

    /**
     * RetryFilters populates filtering objectives for a device and keeps retrying
     * till the number of ports filtered are constant for a predefined number
     * of attempts.
     */
    protected final class RetryFilters implements Runnable {
        int constantAttempts = MAX_CONSTANT_RETRY_ATTEMPTS;
        DeviceId devId;
        int counter;
        PortFilterInfo prevRun;

        private RetryFilters(DeviceId deviceId, PortFilterInfo previousRun) {
            devId = deviceId;
            prevRun = previousRun;
            counter = 0;
        }

        @Override
        public void run() {
            log.debug("RETRY FILTER ATTEMPT {} ** dev:{}", ++counter, devId);
            PortFilterInfo thisRun = rulePopulator.populateVlanMacFilters(devId);
            boolean sameResult = prevRun.equals(thisRun);
            log.debug("dev:{} prevRun:{} thisRun:{} sameResult:{}", devId, prevRun,
                      thisRun, sameResult);
            if (thisRun == null || !sameResult || (--constantAttempts > 0)) {
                // exponentially increasing intervals for retries
                executorService.schedule(this,
                    RETRY_INTERVAL_MS * (int) Math.pow(counter, RETRY_INTERVAL_SCALE),
                    TimeUnit.MILLISECONDS);
                if (!sameResult) {
                    constantAttempts = MAX_CONSTANT_RETRY_ATTEMPTS; //reset
                }
            }
            prevRun = (thisRun == null) ? prevRun : thisRun;
        }
    }

    // Check jobs completion. It returns false if one of the job fails
    // and cancel the remaining
    private boolean checkJobs(List<Future<Boolean>> futures) {
        boolean completed = true;
        for (Future<Boolean> future : futures) {
            try {
                if (completed) {
                    if (!future.get()) {
                        completed = false;
                    }
                } else {
                    future.cancel(true);
                }
            } catch (InterruptedException | ExecutionException e) {
                completed = false;
            }
        }
        return completed;
    }
}
